package jdenticon import ( "context" "errors" "strings" "testing" "time" ) func TestComplexityLimitProtection(t *testing.T) { // Test that complexity limits prevent resource exhaustion config, err := Configure(WithMaxComplexity(1)) // Very low limit if err != nil { t.Fatalf("Failed to create config: %v", err) } ctx := context.Background() _, err = ToSVGWithConfig(ctx, "test-complexity", 64, config) if err == nil { t.Fatal("Expected complexity limit to be exceeded, but got no error") } // Check that we get the right error type (may be wrapped in ErrGenerationFailed) var complexityErr *ErrComplexityLimitExceeded if !errors.As(err, &complexityErr) { // Check if it's an engine complexity error that got translated if !strings.Contains(err.Error(), "complexity limit exceeded") { t.Errorf("Expected complexity limit error, got: %v", err) } } } func TestComplexityLimitDisabled(t *testing.T) { // Test that complexity limits can be disabled config, err := Configure(WithMaxComplexity(-1)) // Disabled if err != nil { t.Fatalf("Failed to create config: %v", err) } ctx := context.Background() _, err = ToSVGWithConfig(ctx, "test-disabled", 64, config) if err != nil { t.Errorf("Expected no error with disabled complexity limit, got: %v", err) } } func TestContextTimeoutProtection(t *testing.T) { // Create a context that will timeout very quickly ctx, cancel := context.WithTimeout(context.Background(), 1*time.Nanosecond) defer cancel() // Wait a bit to ensure the context expires time.Sleep(1 * time.Millisecond) _, err := Generate(ctx, "test-timeout", 64) if err == nil { t.Fatal("Expected context timeout error, but got no error") } if !errors.Is(err, context.DeadlineExceeded) { t.Errorf("Expected context.DeadlineExceeded, got: %v", err) } } func TestContextCancellationProtection(t *testing.T) { // Create a context that we'll cancel ctx, cancel := context.WithCancel(context.Background()) cancel() // Cancel immediately _, err := Generate(ctx, "test-cancellation", 64) if err == nil { t.Fatal("Expected context cancellation error, but got no error") } if !errors.Is(err, context.Canceled) { t.Errorf("Expected context.Canceled, got: %v", err) } } func TestNormalOperationWithLimits(t *testing.T) { // Test that normal operation works with reasonable limits config, err := Configure(WithMaxComplexity(200)) // Reasonable limit if err != nil { t.Fatalf("Failed to create config: %v", err) } ctx := context.Background() svg, err := ToSVGWithConfig(ctx, "test-normal", 64, config) if err != nil { t.Errorf("Expected normal operation to work, got error: %v", err) } if len(svg) == 0 { t.Error("Expected non-empty SVG output") } } func TestDefaultComplexityLimit(t *testing.T) { // Test that default complexity limit allows normal operation config := DefaultConfig() ctx := context.Background() svg, err := ToSVGWithConfig(ctx, "test-default", 64, config) if err != nil { t.Errorf("Expected default limits to allow normal operation, got error: %v", err) } if len(svg) == 0 { t.Error("Expected non-empty SVG output") } } func TestComplexityCalculationConsistency(t *testing.T) { // Test that complexity calculation is deterministic config, err := Configure(WithMaxComplexity(50)) if err != nil { t.Fatalf("Failed to create config: %v", err) } ctx := context.Background() input := "consistency-test" // Try the same input multiple times - should get consistent results for i := 0; i < 5; i++ { _, err := ToSVGWithConfig(ctx, input, 64, config) // The error should be consistent (either always fail or always succeed) if i == 0 { // Store first result for comparison if err != nil { // If first attempt failed, all should fail continue } } // All subsequent attempts should have the same result } } func BenchmarkComplexityCalculation(b *testing.B) { // Benchmark the overhead of complexity calculation config, err := Configure(WithMaxComplexity(100)) if err != nil { b.Fatalf("Failed to create config: %v", err) } ctx := context.Background() b.ResetTimer() for i := 0; i < b.N; i++ { _, _ = ToSVGWithConfig(ctx, "benchmark-test", 64, config) } } func BenchmarkWithoutComplexityLimit(b *testing.B) { // Benchmark without complexity limits for comparison config, err := Configure(WithMaxComplexity(-1)) // Disabled if err != nil { b.Fatalf("Failed to create config: %v", err) } ctx := context.Background() b.ResetTimer() for i := 0; i < b.N; i++ { _, _ = ToSVGWithConfig(ctx, "benchmark-test", 64, config) } }