Files
cmautobuy/admin/handler/integration/auth_test.go
T

115 lines
4.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package integration
import (
"bytes"
"database/sql"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/gin-gonic/gin"
"cmautobuy/admin/config"
"cmautobuy/admin/model"
"cmautobuy/admin/repository"
_ "modernc.org/sqlite"
)
func TestRequireCatalogToken(t *testing.T) {
gin.SetMode(gin.TestMode)
const token = "0123456789abcdef0123456789abcdef"
for _, tc := range []struct {
name, header string
cfg config.CatalogIntegrationConfig
want int
}{
{"未启用", "", config.CatalogIntegrationConfig{}, http.StatusServiceUnavailable},
{"缺少", "", config.CatalogIntegrationConfig{Source: "script", Token: token}, http.StatusUnauthorized},
{"错误", "Bearer wrong", config.CatalogIntegrationConfig{Source: "script", Token: token}, http.StatusUnauthorized},
{"正确", "Bearer " + token, config.CatalogIntegrationConfig{Source: "script", Token: token}, http.StatusNoContent},
} {
t.Run(tc.name, func(t *testing.T) {
r := gin.New()
r.GET("/protected", RequireCatalogToken(tc.cfg), func(c *gin.Context) {
if integrationSource(c) != tc.cfg.Source {
t.Fatalf("source=%q", integrationSource(c))
}
c.Status(http.StatusNoContent)
})
req := httptest.NewRequest(http.MethodGet, "/protected", nil)
req.Header.Set("Authorization", tc.header)
resp := httptest.NewRecorder()
r.ServeHTTP(resp, req)
if resp.Code != tc.want {
t.Fatalf("status=%d body=%s", resp.Code, resp.Body.String())
}
if strings.Contains(resp.Body.String(), token) || strings.Contains(resp.Body.String(), "wrong") {
t.Fatal("响应泄露接口凭据")
}
})
}
}
func TestCatalogBatchAPI_按批次查询摘要(t *testing.T) {
db, err := sql.Open("sqlite", ":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
_, err = db.Exec(`CREATE TABLE catalog_import_runs(source TEXT,batch_id TEXT,request_hash TEXT,status TEXT,request_count INTEGER,conflict_count INTEGER,observed_at TEXT,update_policy TEXT DEFAULT 'fill_missing',last_request_at TEXT,last_conflict_at TEXT,shopee_created INTEGER DEFAULT 0,shopee_updated INTEGER DEFAULT 0,sku_created INTEGER DEFAULT 0,sku_updated INTEGER DEFAULT 0,sku_filled INTEGER DEFAULT 0,sku_same_source_updated INTEGER DEFAULT 0,sku_skipped INTEGER DEFAULT 0,sku_manual_skipped INTEGER DEFAULT 0,sku_stale_skipped INTEGER DEFAULT 0,pdd_created INTEGER DEFAULT 0,pdd_updated INTEGER DEFAULT 0,association_created INTEGER DEFAULT 0,association_unchanged INTEGER DEFAULT 0,failure_count INTEGER DEFAULT 0,error_summary TEXT,response_body TEXT,created_at TEXT,finished_at TEXT,PRIMARY KEY(source,batch_id))`)
if err != nil {
t.Fatal(err)
}
run := model.CatalogImportRun{Source: "script", BatchID: "B-1", RequestHash: "abc", Status: model.CatalogImportSucceeded, LastRequestAt: model.NowISO(), CreatedAt: model.NowISO()}
if err := repository.InsertCatalogImportRun(db, run); err != nil {
t.Fatal(err)
}
const token = "0123456789abcdef0123456789abcdef"
r := gin.New()
Register(r, db, config.CatalogIntegrationConfig{Source: "script", Token: token})
req := httptest.NewRequest(http.MethodGet, "/api/v1/integrations/catalog/batches/B-1", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp := httptest.NewRecorder()
r.ServeHTTP(resp, req)
if resp.Code != 200 || !strings.Contains(resp.Body.String(), `"batch_id":"B-1"`) {
t.Fatalf("status=%d body=%s", resp.Code, resp.Body.String())
}
if !strings.Contains(resp.Body.String(), `"sku_filled":0`) || !strings.Contains(resp.Body.String(), `"update_policy"`) {
t.Fatal("批次摘要缺少更新策略统计")
}
if strings.Contains(resp.Body.String(), "request_hash") {
t.Fatal("查询响应不应暴露请求哈希")
}
}
func TestCatalogBatchAPI_鉴权JSON与体积限制(t *testing.T) {
gin.SetMode(gin.TestMode)
const token = "0123456789abcdef0123456789abcdef"
r := gin.New()
Register(r, nil, config.CatalogIntegrationConfig{Source: "script", Token: token})
for _, tc := range []struct {
name, auth string
body []byte
want int
}{
{"无鉴权", "", []byte(`{}`), http.StatusUnauthorized},
{"坏JSON", "Bearer " + token, []byte(`{"schema_version":`), http.StatusBadRequest},
{"超限", "Bearer " + token, bytes.Repeat([]byte("x"), catalogMaxBody+1), http.StatusRequestEntityTooLarge},
} {
t.Run(tc.name, func(t *testing.T) {
req := httptest.NewRequest(http.MethodPost, "/api/v1/integrations/catalog/batches", bytes.NewReader(tc.body))
req.Header.Set("Authorization", tc.auth)
resp := httptest.NewRecorder()
r.ServeHTTP(resp, req)
if resp.Code != tc.want {
t.Fatalf("status=%d body=%s", resp.Code, resp.Body.String())
}
if !strings.Contains(resp.Header().Get("Content-Type"), "application/json") {
t.Fatalf("错误响应必须是 JSON:%s", resp.Header())
}
})
}
}