Files
at-container-registry/pkg/atproto/directory_test.go
T
2026-01-04 22:39:48 -06:00

148 lines
3.8 KiB
Go

package atproto
import (
"sync"
"testing"
)
func TestGetDirectorySingleton(t *testing.T) {
t.Run("returns non-nil directory", func(t *testing.T) {
dir := GetDirectory()
if dir == nil {
t.Fatal("GetDirectory() returned nil")
}
})
t.Run("singleton behavior - same instance", func(t *testing.T) {
// Get directory twice
dir1 := GetDirectory()
dir2 := GetDirectory()
// They should be the exact same instance (same pointer)
if dir1 != dir2 {
t.Error("GetDirectory() returned different instances, expected singleton")
}
})
}
func TestGetDirectoryConcurrency(t *testing.T) {
t.Run("concurrent access is thread-safe", func(t *testing.T) {
const numGoroutines = 100
var wg sync.WaitGroup
// Channel to collect all directory instances
instances := make(chan any, numGoroutines)
// Launch many goroutines concurrently accessing GetDirectory
for range numGoroutines {
wg.Go(func() {
dir := GetDirectory()
instances <- dir
})
}
// Wait for all goroutines to complete
wg.Wait()
close(instances)
// Collect all instances
var dirs []any
for dir := range instances {
dirs = append(dirs, dir)
}
// Verify we got the expected number of results
if len(dirs) != numGoroutines {
t.Fatalf("Expected %d directory instances, got %d", numGoroutines, len(dirs))
}
// All instances should be identical (singleton)
firstDir := dirs[0]
for i, dir := range dirs {
if dir != firstDir {
t.Errorf("Directory instance %d differs from first instance", i)
}
}
})
}
func TestGetDirectorySequential(t *testing.T) {
t.Run("multiple calls in sequence", func(t *testing.T) {
// Get directory multiple times in sequence
dirs := make([]any, 10)
for i := range 10 {
dirs[i] = GetDirectory()
}
// All should be the same instance
for i := 1; i < len(dirs); i++ {
if dirs[i] != dirs[0] {
t.Errorf("Call %d returned different instance than first call", i)
}
}
})
}
// TestGetDirectoryInterface verifies the directory is properly initialized
func TestGetDirectoryInterface(t *testing.T) {
// Verify the directory instance works as expected
dir := GetDirectory()
// Verify directory is not nil
if dir == nil {
t.Fatal("Directory should not be nil")
}
// Verify it's the indigo Directory interface type
// We can't easily introspect the methods without importing indigo's types,
// but we can verify the instance is usable by checking it's not nil
// and that it's the same as subsequent calls (already tested above)
// Additional verification: the directory should be the same across calls
dir2 := GetDirectory()
if dir != dir2 {
t.Error("Directory instances differ, singleton pattern broken")
}
}
// TestGetDirectoryRaceConditions specifically tests race conditions during initialization
func TestGetDirectoryRaceConditions(t *testing.T) {
// This test would ideally reset the singleton, but since we can't do that
// safely, we instead verify that even if GetDirectory is called concurrently
// before initialization completes, it still works correctly.
//
// The sync.Once ensures this is safe, so calling GetDirectory from multiple
// goroutines simultaneously should still result in exactly one initialization
// and all goroutines getting the same instance.
const numGoroutines = 50
var wg sync.WaitGroup
instances := make([]any, numGoroutines)
var mu sync.Mutex
// Simulate many goroutines trying to get the directory simultaneously
for i := 0; i < numGoroutines; i++ {
wg.Go(func() {
dir := GetDirectory()
mu.Lock()
instances[i] = dir
mu.Unlock()
})
}
wg.Wait()
// Verify all instances are identical
firstDir := instances[0]
for i, dir := range instances {
if dir == nil {
t.Errorf("Instance %d is nil", i)
}
if dir != firstDir {
t.Errorf("Instance %d differs from first instance", i)
}
}
}