mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 03:52:26 +08:00
141 lines
6.0 KiB
Go
141 lines
6.0 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"sync/atomic"
|
|
"testing"
|
|
|
|
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
|
|
"github.com/Wei-Shaw/sub2api/internal/service"
|
|
"github.com/imroc/req/v3"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func referralTestClient(t *testing.T, handler http.HandlerFunc) *openAIReferralClient {
|
|
t.Helper()
|
|
srv := httptest.NewServer(handler)
|
|
t.Cleanup(srv.Close)
|
|
adapter := NewOpenAIReferralClient(func(proxy string) (*req.Client, error) {
|
|
require.Equal(t, "test-proxy", proxy)
|
|
// A shared factory may have retries; the adapter must override them.
|
|
return req.C().SetCommonRetryCount(2).SetCommonRetryCondition(func(_ *req.Response, _ error) bool { return true }), nil
|
|
})
|
|
client, ok := adapter.(*openAIReferralClient)
|
|
require.True(t, ok)
|
|
client.baseURL = srv.URL + "/backend-api/referrals/invite"
|
|
return client
|
|
}
|
|
|
|
func referralTestCall() service.OpenAIReferralCall {
|
|
return service.OpenAIReferralCall{ProxyURL: "test-proxy", ProgramID: "codex_referral_consumer",
|
|
Headers: map[string]string{"Authorization": "Bearer test-token", "ChatGPT-Account-ID": "workspace-test"}}
|
|
}
|
|
|
|
func TestOpenAIReferralClientProtocol(t *testing.T) {
|
|
var gets, posts atomic.Int32
|
|
client := referralTestClient(t, func(w http.ResponseWriter, r *http.Request) {
|
|
require.Equal(t, "Bearer test-token", r.Header.Get("Authorization"))
|
|
require.Equal(t, "workspace-test", r.Header.Get("ChatGPT-Account-ID"))
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.Method == http.MethodGet {
|
|
gets.Add(1)
|
|
require.Equal(t, "/backend-api/referrals/invite/eligibility", r.URL.Path)
|
|
require.Equal(t, "codex_referral_consumer", r.URL.Query().Get("program_id"))
|
|
require.Equal(t, "persistent", r.URL.Query().Get("entrypoint"))
|
|
_, _ = w.Write([]byte(`{"should_show":true,"remaining_send_capacity":8,"remaining_reward_capacity":3,"grants":[{"grant_type":"rate_limit_reset_credit","amount":1,"recipient":"referrer"}],"rules":["Offer rule"]}`))
|
|
return
|
|
}
|
|
posts.Add(1)
|
|
require.Equal(t, http.MethodPost, r.Method)
|
|
require.Equal(t, "/backend-api/referrals/invite", r.URL.Path)
|
|
var body map[string]any
|
|
require.NoError(t, json.NewDecoder(r.Body).Decode(&body))
|
|
require.Equal(t, map[string]any{"program_id": "codex_referral_consumer", "entrypoint": "persistent", "emails": []any{"friend@example.com"}}, body)
|
|
_, _ = w.Write([]byte(`{"invites":[{"referral_id":"test-invite"}]}`))
|
|
})
|
|
result, err := client.QueryEligibility(context.Background(), referralTestCall())
|
|
require.NoError(t, err)
|
|
require.True(t, result.ShouldShow)
|
|
require.Equal(t, 8, *result.RemainingSendCapacity)
|
|
require.Equal(t, 3, *result.RemainingRewardCapacity)
|
|
require.Equal(t, "rate_limit_reset_credit", result.Grants[0].GrantType)
|
|
require.Equal(t, []string{"Offer rule"}, result.Rules)
|
|
require.NoError(t, client.SendInvite(context.Background(), referralTestCall(), "friend@example.com"))
|
|
require.EqualValues(t, 1, gets.Load())
|
|
require.EqualValues(t, 1, posts.Load())
|
|
}
|
|
|
|
func TestOpenAIReferralClientSanitizesErrorsWithoutRetry(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
status int
|
|
reason string
|
|
}{
|
|
{400, "OPENAI_REFERRAL_REJECTED"}, {422, "OPENAI_REFERRAL_REJECTED"},
|
|
{401, "OPENAI_REFERRAL_AUTH_ERROR"}, {403, "OPENAI_REFERRAL_FORBIDDEN"},
|
|
{409, "OPENAI_REFERRAL_ALREADY_EXISTS"}, {429, "OPENAI_REFERRAL_RATE_LIMITED"},
|
|
{500, "OPENAI_REFERRAL_UPSTREAM_ERROR"},
|
|
} {
|
|
t.Run(http.StatusText(tc.status), func(t *testing.T) {
|
|
var requests atomic.Int32
|
|
client := referralTestClient(t, func(w http.ResponseWriter, _ *http.Request) {
|
|
requests.Add(1)
|
|
w.WriteHeader(tc.status)
|
|
_, _ = w.Write([]byte(`{"detail":"secret-token someone@example.com"}`))
|
|
})
|
|
_, queryErr := client.QueryEligibility(context.Background(), referralTestCall())
|
|
sendErr := client.SendInvite(context.Background(), referralTestCall(), "friend@example.com")
|
|
for _, err := range []error{queryErr, sendErr} {
|
|
require.Equal(t, tc.reason, infraerrors.Reason(err))
|
|
require.NotContains(t, err.Error(), "secret-token")
|
|
require.NotContains(t, err.Error(), "someone@example.com")
|
|
}
|
|
require.EqualValues(t, 2, requests.Load(), "one query and one send, no retries")
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOpenAIReferralClientInvalidResponses(t *testing.T) {
|
|
for _, body := range []string{"null", "invalid json", `{"invites":[]}`, `{"invites":[null]}`, `{"invites":[{},{}]}`} {
|
|
t.Run(body, func(t *testing.T) {
|
|
var requests atomic.Int32
|
|
client := referralTestClient(t, func(w http.ResponseWriter, _ *http.Request) {
|
|
requests.Add(1)
|
|
_, _ = w.Write([]byte(body))
|
|
})
|
|
err := client.SendInvite(context.Background(), referralTestCall(), "friend@example.com")
|
|
require.Equal(t, "OPENAI_REFERRAL_SEND_UNKNOWN", infraerrors.Reason(err))
|
|
require.EqualValues(t, 1, requests.Load())
|
|
if body == "null" || body == "invalid json" {
|
|
_, err := client.QueryEligibility(context.Background(), referralTestCall())
|
|
require.Equal(t, "OPENAI_REFERRAL_INVALID_RESPONSE", infraerrors.Reason(err))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOpenAIReferralClientLostResponseIsUnknownWithoutRetry(t *testing.T) {
|
|
var requests atomic.Int32
|
|
client := referralTestClient(t, func(w http.ResponseWriter, _ *http.Request) {
|
|
requests.Add(1)
|
|
hijacker, ok := w.(http.Hijacker)
|
|
require.True(t, ok)
|
|
conn, _, err := hijacker.Hijack()
|
|
require.NoError(t, err)
|
|
_ = conn.Close() // Upstream received the request but its response was lost.
|
|
})
|
|
err := client.SendInvite(context.Background(), referralTestCall(), "friend@example.com")
|
|
require.Equal(t, "OPENAI_REFERRAL_SEND_UNKNOWN", infraerrors.Reason(err))
|
|
require.EqualValues(t, 1, requests.Load())
|
|
}
|
|
|
|
func TestOpenAIReferralClientFactoryErrorIsSanitized(t *testing.T) {
|
|
client := NewOpenAIReferralClient(func(string) (*req.Client, error) { return nil, errors.New("secret proxy credentials") })
|
|
err := client.SendInvite(context.Background(), referralTestCall(), "friend@example.com")
|
|
require.Equal(t, "OPENAI_REFERRAL_CLIENT_ERROR", infraerrors.Reason(err))
|
|
require.NotContains(t, err.Error(), "secret")
|
|
}
|