package api import ( "encoding/json" "net/http" "net/http/httptest" "strings" "testing" "git.ipao.vip/rogee/creator-hub/internal/creator" hub "git.ipao.vip/rogee/creator-hub/internal/environment" ) func TestCompetitorSharePlatform(t *testing.T) { for _, test := range []struct { name string url string want string }{ {name: "douyin short link", url: "https://v.douyin.com/abc123/", want: creator.PlatformDouyin}, {name: "douyin content", url: "https://www.douyin.com/video/123", want: creator.PlatformDouyin}, } { t.Run(test.name, func(t *testing.T) { got, err := competitorSharePlatform(test.url) if err != nil || got != test.want { t.Fatalf("competitorSharePlatform(%q) = %q, %v; want %q", test.url, got, err, test.want) } }) } for _, url := range []string{ "http://v.douyin.com/abc123/", "https://www.douyin.com.evil/video/123", "https://v.douyin.com/abc123/#fragment", } { t.Run(url, func(t *testing.T) { if _, err := competitorSharePlatform(url); err == nil { t.Fatalf("competitorSharePlatform(%q) unexpectedly succeeded", url) } }) } } func TestRandomGatewaySelectsFromRegisteredGateways(t *testing.T) { gateways := []hub.Gateway{ {Name: "gateway-a"}, {Name: "gateway-b"}, {Name: "gateway-c"}, } allowed := map[string]bool{ "gateway-a": true, "gateway-b": true, "gateway-c": true, } for range 32 { if gateway := randomGateway(gateways); !allowed[gateway.Name] { t.Fatalf("randomGateway selected unregistered gateway %q", gateway.Name) } } } func TestAnonymousBrowserLeasePurgesRuntimeAndProfile(t *testing.T) { var requestBody map[string]any server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodDelete || r.URL.Path != "/v1/browsers/anon-test" { t.Fatalf("unexpected cleanup request: %s %s", r.Method, r.URL.Path) } if err := json.NewDecoder(r.Body).Decode(&requestBody); err != nil { t.Fatal(err) } w.WriteHeader(http.StatusNoContent) })) defer server.Close() err := (anonymousBrowserLease{ gateway: hub.Gateway{Endpoint: server.URL, Token: "test-token"}, environment: hub.EnvironmentContext{ Env: hub.Env{Alias: "anon-test"}, BindingVersion: 1, RuntimeID: strings.Repeat("a", 64), RuntimeNetworkID: "native-" + strings.Repeat("b", 32), }, }).close() if err != nil { t.Fatal(err) } if requestBody["purge_profile"] != true || requestBody["binding_version"] != float64(1) { t.Fatalf("cleanup request did not fence and purge the temporary runtime: %#v", requestBody) } if _, ok := requestBody["network_exit_id"]; ok { t.Fatalf("cleanup request must use only the runtime generation fence: %#v", requestBody) } } func TestAnonymousBrowserLeaseReleasesConcurrencySlot(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodDelete || r.URL.Path != "/v1/browsers/anon-test" { t.Fatalf("unexpected cleanup request: %s %s", r.Method, r.URL.Path) } w.WriteHeader(http.StatusNoContent) })) defer server.Close() slots := make(chan struct{}, 1) slots <- struct{}{} lease := anonymousBrowserLease{gateway: hub.Gateway{Endpoint: server.URL, Token: "test-token"}, slot: slots, environment: hub.EnvironmentContext{Env: hub.Env{Alias: "anon-test"}, BindingVersion: 1}} if err := lease.close(); err != nil { t.Fatal(err) } // 释放 = 名额回到池里(能再次非阻塞占用)。 select { case slots <- struct{}{}: default: t.Fatal("close must release the anonymous browser concurrency slot") } // 创建失败路径也必须释放名额,否则失败几次后永久占满。 failed := anonymousBrowserLease{gateway: hub.Gateway{Endpoint: "http://127.0.0.1:1", Token: "test-token"}, slot: slots} if err := failed.close(); err == nil { t.Fatal("cleanup against unreachable gateway must fail") } select { case slots <- struct{}{}: default: t.Fatal("failed close must still release the anonymous browser concurrency slot") } } func TestDouyinWorkKeyFromURL(t *testing.T) { for _, test := range []struct { url string want string }{ {url: "https://www.douyin.com/video/123", want: "123"}, {url: "https://www.douyin.com/video/123?previous_page=app_code_link", want: "123"}, } { got, err := douyinWorkKeyFromURL(test.url) if err != nil || got != test.want { t.Fatalf("douyinWorkKeyFromURL(%q) = %q, %v; want %q", test.url, got, err, test.want) } } for _, url := range []string{ "https://www.douyin.com/video/0", "https://www.douyin.com/user/123", "https://v.douyin.com/abc123", } { if _, err := douyinWorkKeyFromURL(url); err == nil { t.Fatalf("douyinWorkKeyFromURL(%q) unexpectedly succeeded", url) } } }