153 lines
6.1 KiB
Go
153 lines
6.1 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"git.ipao.vip/rogee/creator-hub/internal/creator"
|
|
"git.ipao.vip/rogee/creator-hub/internal/hub"
|
|
)
|
|
|
|
func TestCreateStoppedGatewayRuntimeValidatesGatewayResponses(t *testing.T) {
|
|
environment := hub.EnvironmentContext{Env: hub.Env{Alias: "account-1", Name: "账号一", BrowserVersion: "148.0.7778.215"}, BindingVersion: 1}
|
|
cases := []struct {
|
|
name string
|
|
status int
|
|
body string
|
|
wantErr bool
|
|
}{
|
|
{name: "success", status: http.StatusCreated, body: `{"id":"runtime-1","state":"stopped"}`},
|
|
{name: "invalid body", status: http.StatusCreated, body: `{`, wantErr: true},
|
|
{name: "rejected", status: http.StatusBadRequest, body: `{"error":"invalid"}`, wantErr: true},
|
|
}
|
|
for _, testCase := range cases {
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost || r.URL.Path != "/v1/browsers" {
|
|
t.Fatalf("gateway request = %s %s", r.Method, r.URL.Path)
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(testCase.status)
|
|
_, _ = w.Write([]byte(testCase.body))
|
|
}))
|
|
defer server.Close()
|
|
err := createStoppedGatewayRuntime(context.Background(), hub.Gateway{Endpoint: server.URL}, environment, "/opt/chrome")
|
|
if (err != nil) != testCase.wantErr {
|
|
t.Fatalf("create stopped runtime error = %v, wantErr=%v", err, testCase.wantErr)
|
|
}
|
|
})
|
|
}
|
|
|
|
server := httptest.NewServer(http.NotFoundHandler())
|
|
endpoint := server.URL
|
|
server.Close()
|
|
if err := createStoppedGatewayRuntime(context.Background(), hub.Gateway{Endpoint: endpoint}, environment, "/opt/chrome"); err == nil {
|
|
t.Fatal("unreachable gateway was reported as successful")
|
|
}
|
|
}
|
|
|
|
func TestRuntimeCreateSpecMatchesCurrentEnvironment(t *testing.T) {
|
|
store := newMemoryStore()
|
|
store.images["148.0.7778.215"] = hub.BrowserVersion{Version: "148.0.7778.215", BrowserPath: "/opt/chrome", Enabled: true}
|
|
current := hub.EnvironmentContext{Env: hub.Env{BrowserVersion: "148.0.7778.215"}, Exit: hub.NetworkExit{ID: "exit-1"}, BindingVersion: 2}
|
|
previous := current
|
|
prepared := &runtimeCreateSpec{browserPath: "/opt/chrome"}
|
|
if !runtimeCreateSpecMatches(context.Background(), store, current, previous, prepared) {
|
|
t.Fatal("matching runtime specification was rejected")
|
|
}
|
|
for name, mutate := range map[string]func(*hub.EnvironmentContext){
|
|
"binding": func(value *hub.EnvironmentContext) { value.BindingVersion++ },
|
|
"browser version": func(value *hub.EnvironmentContext) { value.BrowserVersion = "149.0.0.0" },
|
|
"network exit": func(value *hub.EnvironmentContext) { value.Exit.ID = "exit-2" },
|
|
} {
|
|
t.Run(name, func(t *testing.T) {
|
|
candidate := current
|
|
mutate(&candidate)
|
|
if runtimeCreateSpecMatches(context.Background(), store, candidate, previous, prepared) {
|
|
t.Fatal("mismatched runtime specification was accepted")
|
|
}
|
|
})
|
|
}
|
|
if runtimeCreateSpecMatches(context.Background(), store, current, previous, &runtimeCreateSpec{browserPath: "/other/chrome"}) {
|
|
t.Fatal("mismatched browser path was accepted")
|
|
}
|
|
if runtimeCreateSpecMatches(context.Background(), store, current, previous, nil) {
|
|
t.Fatal("nil runtime specification was accepted")
|
|
}
|
|
}
|
|
|
|
func TestCreatorGatewayBrowserResolveAndSharePlatformValidation(t *testing.T) {
|
|
environment := hub.EnvironmentContext{Env: hub.Env{Alias: "account-1"}, RuntimeID: "runtime-1", RuntimeNetworkID: "network-1", BindingVersion: 3}
|
|
cases := []struct {
|
|
name string
|
|
status int
|
|
body string
|
|
wantURL string
|
|
wantErr bool
|
|
}{
|
|
{name: "success", status: http.StatusOK, body: `{"url":"https://www.douyin.com/video/1"}`, wantURL: "https://www.douyin.com/video/1"},
|
|
{name: "invalid json", status: http.StatusOK, body: `{`, wantErr: true},
|
|
{name: "empty url", status: http.StatusOK, body: `{"url":""}`, wantErr: true},
|
|
{name: "rejected", status: http.StatusBadGateway, body: `gateway down`, wantErr: true},
|
|
}
|
|
for _, testCase := range cases {
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/v1/browsers/account-1/douyin/resolve" {
|
|
t.Fatalf("resolve path = %q", r.URL.Path)
|
|
}
|
|
w.WriteHeader(testCase.status)
|
|
_, _ = w.Write([]byte(testCase.body))
|
|
}))
|
|
defer server.Close()
|
|
got, err := (creatorGatewayBrowser{gateway: hub.Gateway{Endpoint: server.URL}, environment: environment}).Resolve(context.Background(), "https://www.douyin.com/video/1")
|
|
if (err != nil) != testCase.wantErr || got != testCase.wantURL {
|
|
t.Fatalf("resolve = %q, err = %v", got, err)
|
|
}
|
|
})
|
|
}
|
|
|
|
for _, testCase := range []struct {
|
|
value string
|
|
platform string
|
|
wantErr bool
|
|
}{
|
|
{value: "https://www.douyin.com/video/1", platform: creator.PlatformDouyin},
|
|
{value: "https://v.douyin.com/abc", platform: creator.PlatformDouyin},
|
|
{value: "https://www.xiaohongshu.com/explore/1", platform: creator.PlatformXiaohongshu},
|
|
{value: "https://xhslink.com/abc", platform: creator.PlatformXiaohongshu},
|
|
{value: "http://www.douyin.com/video/1", wantErr: true},
|
|
{value: "https://user@www.douyin.com/video/1", wantErr: true},
|
|
{value: "https://www.douyin.com:443/video/1", wantErr: true},
|
|
{value: "https://www.douyin.com/video/1#part", wantErr: true},
|
|
{value: "https://example.com/video/1", wantErr: true},
|
|
} {
|
|
platform, err := competitorSharePlatform(testCase.value)
|
|
if testCase.wantErr {
|
|
if !errors.Is(err, creator.ErrInvalid) {
|
|
t.Errorf("competitorSharePlatform(%q) error = %v", testCase.value, err)
|
|
}
|
|
continue
|
|
}
|
|
if err != nil || platform != testCase.platform {
|
|
t.Errorf("competitorSharePlatform(%q) = %q, %v", testCase.value, platform, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRebindRecoveryErrorPreservesFailureStates(t *testing.T) {
|
|
sentinel := errors.New("rebind failed")
|
|
if got := rebindRecoveryError(true, sentinel); !errors.Is(got, sentinel) {
|
|
t.Fatalf("existing error = %v", got)
|
|
}
|
|
if got := rebindRecoveryError(false, nil); got == nil {
|
|
t.Fatal("incomplete recovery was reported as successful")
|
|
}
|
|
if got := rebindRecoveryError(true, nil); got != nil {
|
|
t.Fatalf("complete recovery error = %v", got)
|
|
}
|
|
}
|