package scheduler_test import ( "testing" "github.com/jfraeys/fetch_ml/internal/scheduler" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestPortAllocator_BasicAllocation(t *testing.T) { pa := scheduler.NewPortAllocator(10000, 10010) // Allocate first port port1, err := pa.Allocate("service-1") require.NoError(t, err) assert.Equal(t, 10000, port1) // Allocate second port port2, err := pa.Allocate("service-2") require.NoError(t, err) assert.Equal(t, 10001, port2) } func TestPortAllocator_Exhaustion(t *testing.T) { pa := scheduler.NewPortAllocator(10000, 10002) // Only 3 ports available // Allocate all ports port1, _ := pa.Allocate("service-1") assert.Equal(t, 10000, port1) port2, _ := pa.Allocate("service-2") assert.Equal(t, 10001, port2) port3, _ := pa.Allocate("service-3") assert.Equal(t, 10002, port3) // Should fail - no ports left _, err := pa.Allocate("service-4") assert.Error(t, err) } func TestPortAllocator_Release(t *testing.T) { pa := scheduler.NewPortAllocator(10000, 10005) // Allocate and release port, _ := pa.Allocate("service-1") assert.Equal(t, 10000, port) pa.Release(port) // Should be able to allocate again port2, err := pa.Allocate("service-2") require.NoError(t, err) assert.Equal(t, 10000, port2) // Reuses released port } func TestPortAllocator_DuplicateServiceID(t *testing.T) { pa := scheduler.NewPortAllocator(10000, 10010) // Allocate for service port1, err := pa.Allocate("service-1") require.NoError(t, err) // Allocate again with same service ID - gets new port (current behavior) port2, err := pa.Allocate("service-1") require.NoError(t, err) assert.NotEqual(t, port1, port2) // Each call returns new port } func TestPortAllocator_ConcurrentAccess(t *testing.T) { pa := scheduler.NewPortAllocator(10000, 10100) // 101 ports done := make(chan bool, 10) // Concurrent allocations for i := 0; i < 10; i++ { go func(id int) { for j := 0; j < 10; j++ { pa.Allocate("service-") } done <- true }(i) } for i := 0; i < 10; i++ { <-done } // All 100 ports should be allocated // (10 goroutines * 10 allocations, but only 100 unique service IDs) }