- Core library with SVG and PNG generation - CLI tool with generate and batch commands - Cross-platform path handling for Windows compatibility - Comprehensive test suite with integration tests
174 lines
4.5 KiB
Go
174 lines
4.5 KiB
Go
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)
|
|
}
|
|
}
|