Files
go-jdenticon/jdenticon/resource_protection_test.go
Kevin McIntyre d9e84812ff Initial release: Go Jdenticon library v0.1.0
- 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
2026-01-03 23:41:48 -05:00

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)
}
}