package antigravity import ( "testing" "time" "github.com/stretchr/testify/assert" ) func TestGetUserAgent(t *testing.T) { ua := GetUserAgent() assert.Contains(t, ua, "antigravity/") assert.Contains(t, ua, "windows/amd64") } func TestBaseURLs(t *testing.T) { assert.NotEmpty(t, BaseURLs) assert.GreaterOrEqual(t, len(BaseURLs), 2) assert.Contains(t, BaseURLs, antigravityProdBaseURL) assert.Contains(t, BaseURLs, antigravityDailyBaseURL) } func TestForwardBaseURLs(t *testing.T) { urls := ForwardBaseURLs() assert.NotEmpty(t, urls) // daily should be first if it exists if len(urls) >= 2 { assert.Equal(t, antigravityDailyBaseURL, urls[0]) } } func TestForwardBaseURLsEmpty(t *testing.T) { // Temporarily set BaseURLs to empty originalURLs := BaseURLs BaseURLs = []string{} defer func() { BaseURLs = originalURLs }() urls := ForwardBaseURLs() assert.Empty(t, urls) } func TestURLAvailability(t *testing.T) { ua := NewURLAvailability(URLAvailabilityTTL) t.Run("mark unavailable", func(t *testing.T) { url := "http://example.com" ua.MarkUnavailable(url) assert.False(t, ua.IsAvailable(url)) }) t.Run("mark success", func(t *testing.T) { url := "http://example.com" ua.MarkSuccess(url) assert.True(t, ua.IsAvailable(url)) }) t.Run("expired unavailable", func(t *testing.T) { // Create with very short TTL ua := NewURLAvailability(1 * time.Nanosecond) url := "http://expired.com" ua.MarkUnavailable(url) time.Sleep(10 * time.Millisecond) assert.True(t, ua.IsAvailable(url)) }) t.Run("get available URLs", func(t *testing.T) { ua := NewURLAvailability(URLAvailabilityTTL) baseURLs := []string{"http://a.com", "http://b.com", "http://c.com"} // Mark one as unavailable ua.MarkUnavailable("http://b.com") available := ua.GetAvailableURLsWithBase(baseURLs) assert.Contains(t, available, "http://a.com") assert.Contains(t, available, "http://c.com") assert.NotContains(t, available, "http://b.com") }) t.Run("last success priority", func(t *testing.T) { ua := NewURLAvailability(URLAvailabilityTTL) baseURLs := []string{"http://a.com", "http://b.com"} ua.MarkSuccess("http://b.com") available := ua.GetAvailableURLsWithBase(baseURLs) // b.com should be first assert.Equal(t, "http://b.com", available[0]) }) } func TestSessionStore(t *testing.T) { store := NewSessionStore() defer store.Stop() t.Run("set and get", func(t *testing.T) { session := &OAuthSession{ State: "state123", CodeVerifier: "verifier456", CreatedAt: time.Now(), } store.Set("session1", session) got, ok := store.Get("session1") assert.True(t, ok) assert.Equal(t, "state123", got.State) }) t.Run("get non-existent", func(t *testing.T) { _, ok := store.Get("nonexistent") assert.False(t, ok) }) t.Run("expired session", func(t *testing.T) { expiredSession := &OAuthSession{ State: "expired", CodeVerifier: "verifier", CreatedAt: time.Now().Add(-2 * SessionTTL), } store.Set("expired", expiredSession) _, ok := store.Get("expired") assert.False(t, ok) }) t.Run("delete", func(t *testing.T) { session := &OAuthSession{ State: "to_delete", CreatedAt: time.Now(), } store.Set("to_delete", session) store.Delete("to_delete") _, ok := store.Get("to_delete") assert.False(t, ok) }) } func TestGenerateFunctions(t *testing.T) { t.Run("random bytes", func(t *testing.T) { b1, err := GenerateRandomBytes(32) assert.NoError(t, err) assert.Equal(t, 32, len(b1)) b2, _ := GenerateRandomBytes(32) assert.NotEqual(t, b1, b2) }) t.Run("state", func(t *testing.T) { state, err := GenerateState() assert.NoError(t, err) assert.NotEmpty(t, state) state2, _ := GenerateState() assert.NotEqual(t, state, state2) }) t.Run("session ID", func(t *testing.T) { id, err := GenerateSessionID() assert.NoError(t, err) assert.NotEmpty(t, id) assert.Equal(t, 32, len(id)) // 16 bytes * 2 hex chars }) t.Run("code verifier", func(t *testing.T) { verifier, err := GenerateCodeVerifier() assert.NoError(t, err) assert.NotEmpty(t, verifier) }) t.Run("code challenge", func(t *testing.T) { challenge := GenerateCodeChallenge("test_verifier") assert.NotEmpty(t, challenge) // Deterministic challenge2 := GenerateCodeChallenge("test_verifier") assert.Equal(t, challenge, challenge2) }) } func TestBase64URLEncode(t *testing.T) { tests := []struct { input []byte expected string }{ {[]byte("hello"), "aGVsbG8"}, {[]byte("test"), "dGVzdA"}, {[]byte{}, ""}, } for _, tt := range tests { result := base64URLEncode(tt.input) assert.Equal(t, tt.expected, result) assert.NotContains(t, result, "=") } } func TestBuildAuthorizationURL(t *testing.T) { url := BuildAuthorizationURL("test_state", "test_challenge") assert.Contains(t, url, AuthorizeURL) assert.Contains(t, url, "client_id="+ClientID) assert.Contains(t, url, "state=test_state") assert.Contains(t, url, "code_challenge=test_challenge") assert.Contains(t, url, "code_challenge_method=S256") assert.Contains(t, url, "redirect_uri=") assert.Contains(t, url, "response_type=code") } func TestConstants(t *testing.T) { assert.NotEmpty(t, ClientID) assert.NotEmpty(t, RedirectURI) assert.NotEmpty(t, AuthorizeURL) assert.NotEmpty(t, TokenURL) assert.NotEmpty(t, Scopes) assert.Equal(t, 30*time.Minute, SessionTTL) assert.Equal(t, 5*time.Minute, URLAvailabilityTTL) }