package automc import ( "context" "encoding/json" "net/http" "net/http/httptest" "strings" "sync/atomic" "testing" "time" ) func TestWakerNilWhenURLEmpty(t *testing.T) { w := newWakerConfig("", "") if w != nil { t.Fatalf("expected nil waker config when URL empty, got %+v", w) } if w.wakerFor("foo") != nil { t.Fatalf("expected nil WakerFunc from nil config") } } func TestWakerStartThenPoll(t *testing.T) { var startCalls int32 var pollCalls int32 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("X-API-Key") != "secret" { http.Error(w, "no auth", http.StatusUnauthorized) return } switch { case r.Method == http.MethodPost && strings.HasSuffix(r.URL.Path, "/start"): atomic.AddInt32(&startCalls, 1) w.WriteHeader(http.StatusAccepted) case r.Method == http.MethodGet: n := atomic.AddInt32(&pollCalls, 1) state := "starting" addr := "" if n >= 2 { state = "running" addr = "10.0.0.5:25565" } _ = json.NewEncoder(w).Encode(map[string]string{ "state": state, "address": addr, }) default: http.NotFound(w, r) } })) defer srv.Close() wc := newWakerConfig(srv.URL, "secret") wc.client.Timeout = 2 * time.Second // Tighten poll interval for the test only. saved := wakerPollIntervalForTest wakerPollIntervalForTest = 10 * time.Millisecond t.Cleanup(func() { wakerPollIntervalForTest = saved }) fn := wc.wakerFor("test1") if fn == nil { t.Fatal("expected non-nil WakerFunc") } ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() addr, err := fn(ctx) if err != nil { t.Fatalf("wake failed: %v", err) } if addr != "10.0.0.5:25565" { t.Errorf("addr: got %q want 10.0.0.5:25565", addr) } if atomic.LoadInt32(&startCalls) != 1 { t.Errorf("expected 1 start call, got %d", startCalls) } if got := atomic.LoadInt32(&pollCalls); got < 2 { t.Errorf("expected >=2 polls, got %d", got) } } func TestWakerStartHandles409(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost && strings.HasSuffix(r.URL.Path, "/start") { http.Error(w, "already running", http.StatusConflict) return } _ = json.NewEncoder(w).Encode(map[string]string{ "state": "running", "address": "10.0.0.6:25565", }) })) defer srv.Close() wc := newWakerConfig(srv.URL, "") wakerPollIntervalForTest = 10 * time.Millisecond ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() addr, err := wc.wakerFor("x")(ctx) if err != nil { t.Fatalf("expected 409 to be treated as success, got err: %v", err) } if addr != "10.0.0.6:25565" { t.Errorf("addr: got %q", addr) } }