mirror of
https://github.com/lukaszraczylo/gohoarder.git
synced 2026-06-05 22:53:53 +00:00
6b037a92b4
- [x] Reorder struct fields across codebase for consistency - [x] Add analytics event handlers and tests - [x] Add authentication API key management handlers and tests - [x] Add pre-warming control handlers and tests - [x] Implement S3 storage backend with tests - [x] Implement SMB/CIFS storage backend with tests - [x] Add CDN middleware tests - [x] Integrate analytics tracking into cache manager - [x] Add S3 and SMB storage initialization in app setup - [x] Add CDN caching to proxy handlers - [x] Remove distributed locking (Redis lock manager) - [x] Remove proxy common package and utilities - [x] Remove standalone HTTP server package - [x] Remove logger middleware - [x] Simplify error handling utilities - [x] Update config with S3 and SMB options - [x] Update cache manager signature to include analytics
218 lines
5.6 KiB
Go
218 lines
5.6 KiB
Go
package uuid
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestNew tests UUID generation
|
|
func TestNew(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
runs int
|
|
}{
|
|
{
|
|
name: "generate single UUID",
|
|
runs: 1,
|
|
},
|
|
{
|
|
name: "generate multiple UUIDs",
|
|
runs: 100,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
seen := make(map[string]bool)
|
|
|
|
for i := 0; i < tt.runs; i++ {
|
|
uuid := New()
|
|
|
|
// Verify UUID is 16 bytes
|
|
assert.Equal(t, 16, len(uuid))
|
|
|
|
// Verify version is 4
|
|
version := (uuid[6] >> 4) & 0x0f
|
|
assert.Equal(t, uint8(4), version, "UUID version should be 4")
|
|
|
|
// Verify variant is RFC 4122
|
|
variant := (uuid[8] >> 6) & 0x03
|
|
assert.Equal(t, uint8(2), variant, "UUID variant should be RFC 4122 (10 in binary)")
|
|
|
|
// Check uniqueness
|
|
str := uuid.String()
|
|
assert.False(t, seen[str], "UUID should be unique")
|
|
seen[str] = true
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestString tests UUID string formatting
|
|
func TestString(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
expected string
|
|
uuid UUID
|
|
}{
|
|
{
|
|
name: "zero UUID",
|
|
uuid: UUID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
expected: "00000000-0000-0000-0000-000000000000",
|
|
},
|
|
{
|
|
name: "all ones UUID",
|
|
uuid: UUID{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
|
expected: "ffffffff-ffff-ffff-ffff-ffffffffffff",
|
|
},
|
|
{
|
|
name: "mixed values UUID",
|
|
uuid: UUID{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88},
|
|
expected: "12345678-9abc-def0-1122-334455667788",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
str := tt.uuid.String()
|
|
assert.Equal(t, tt.expected, str)
|
|
|
|
// Verify format matches UUID regex
|
|
matched, err := regexp.MatchString(`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, str)
|
|
require.NoError(t, err)
|
|
assert.True(t, matched, "UUID string should match standard format")
|
|
|
|
// Verify dashes are in correct positions
|
|
assert.Equal(t, "-", string(str[8]))
|
|
assert.Equal(t, "-", string(str[13]))
|
|
assert.Equal(t, "-", string(str[18]))
|
|
assert.Equal(t, "-", string(str[23]))
|
|
|
|
// Verify length
|
|
assert.Equal(t, 36, len(str))
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestUUIDFormat tests that generated UUIDs match the standard format
|
|
func TestUUIDFormat(t *testing.T) {
|
|
const iterations = 1000
|
|
|
|
// Compile regex once for performance
|
|
hexPattern := regexp.MustCompile(`^[0-9a-f]+$`)
|
|
|
|
for i := 0; i < iterations; i++ {
|
|
uuid := New()
|
|
str := uuid.String()
|
|
|
|
// Test standard UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
parts := strings.Split(str, "-")
|
|
require.Len(t, parts, 5, "UUID should have 5 parts separated by dashes")
|
|
assert.Equal(t, 8, len(parts[0]), "First part should be 8 characters")
|
|
assert.Equal(t, 4, len(parts[1]), "Second part should be 4 characters")
|
|
assert.Equal(t, 4, len(parts[2]), "Third part should be 4 characters")
|
|
assert.Equal(t, 4, len(parts[3]), "Fourth part should be 4 characters")
|
|
assert.Equal(t, 12, len(parts[4]), "Fifth part should be 12 characters")
|
|
|
|
// Verify all characters are hexadecimal
|
|
for _, part := range parts {
|
|
assert.True(t, hexPattern.MatchString(part), "UUID parts should only contain hex characters")
|
|
}
|
|
|
|
// Verify version bits (4th character of third part should start with 4)
|
|
versionChar := parts[2][0]
|
|
assert.Equal(t, byte('4'), versionChar, "UUID version should be 4")
|
|
|
|
// Verify variant bits (first character of fourth part should be 8, 9, a, or b)
|
|
variantChar := parts[3][0]
|
|
assert.Contains(t, []byte{'8', '9', 'a', 'b'}, variantChar, "UUID variant should be RFC 4122")
|
|
}
|
|
}
|
|
|
|
// TestConcurrentGeneration tests that UUID generation is safe for concurrent use
|
|
func TestConcurrentGeneration(t *testing.T) {
|
|
const numGoroutines = 100
|
|
const uuidsPerGoroutine = 100
|
|
|
|
results := make(chan UUID, numGoroutines*uuidsPerGoroutine)
|
|
|
|
// Generate UUIDs concurrently
|
|
for i := 0; i < numGoroutines; i++ {
|
|
go func() {
|
|
for j := 0; j < uuidsPerGoroutine; j++ {
|
|
results <- New()
|
|
}
|
|
}()
|
|
}
|
|
|
|
// Collect all UUIDs
|
|
seen := make(map[string]bool)
|
|
for i := 0; i < numGoroutines*uuidsPerGoroutine; i++ {
|
|
uuid := <-results
|
|
str := uuid.String()
|
|
|
|
// Verify uniqueness
|
|
assert.False(t, seen[str], "UUID should be unique even in concurrent generation")
|
|
seen[str] = true
|
|
|
|
// Verify version and variant
|
|
version := (uuid[6] >> 4) & 0x0f
|
|
assert.Equal(t, uint8(4), version)
|
|
|
|
variant := (uuid[8] >> 6) & 0x03
|
|
assert.Equal(t, uint8(2), variant)
|
|
}
|
|
|
|
// Verify we got all expected UUIDs
|
|
assert.Equal(t, numGoroutines*uuidsPerGoroutine, len(seen))
|
|
}
|
|
|
|
// TestUUIDEquality tests UUID equality
|
|
func TestUUIDEquality(t *testing.T) {
|
|
uuid1 := New()
|
|
uuid2 := New()
|
|
|
|
// Different UUIDs should not be equal
|
|
assert.NotEqual(t, uuid1, uuid2)
|
|
assert.NotEqual(t, uuid1.String(), uuid2.String())
|
|
|
|
// Same UUID should be equal
|
|
uuid3 := uuid1
|
|
assert.Equal(t, uuid1, uuid3)
|
|
assert.Equal(t, uuid1.String(), uuid3.String())
|
|
}
|
|
|
|
// TestUUIDArrayAccess tests that UUID can be accessed as a byte array
|
|
func TestUUIDArrayAccess(t *testing.T) {
|
|
uuid := New()
|
|
|
|
// Verify we can access all bytes
|
|
for i := 0; i < 16; i++ {
|
|
_ = uuid[i]
|
|
}
|
|
|
|
// Verify length
|
|
assert.Equal(t, 16, len(uuid))
|
|
}
|
|
|
|
// BenchmarkNew benchmarks UUID generation
|
|
func BenchmarkNew(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
_ = New()
|
|
}
|
|
}
|
|
|
|
// BenchmarkString benchmarks UUID string conversion
|
|
func BenchmarkString(b *testing.B) {
|
|
uuid := New()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_ = uuid.String()
|
|
}
|
|
}
|