mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 08:14:55 +08:00
fix(bat-api): 完成 issue #19 同机 live 联调
This commit is contained in:
@@ -66,6 +66,29 @@ func TestLoadIndexFromResourceRoot(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestReleaseSummaryRequiresCompleteManifest(t *testing.T) {
|
||||
idx := &ReleaseIndex{
|
||||
ResourceRoot: "/tmp/release",
|
||||
Entries: []ResourceEntry{
|
||||
{RelativePath: "host/ready.bin", Present: true, SizeMatch: true},
|
||||
{RelativePath: "host/missing.bin", Present: false, SizeMatch: false},
|
||||
},
|
||||
MissingOnDisk: []string{"host/missing.bin"},
|
||||
byRel: map[string]int{},
|
||||
}
|
||||
summary := idx.Summary()
|
||||
if summary.PresentCount != 1 || summary.MissingCount != 1 || summary.Ready {
|
||||
t.Fatalf("partial release summary=%+v", summary)
|
||||
}
|
||||
|
||||
idx.Entries[1] = ResourceEntry{RelativePath: "host/missing.bin", Present: true, SizeMatch: false}
|
||||
idx.MissingOnDisk = []string{"host/missing.bin#size_mismatch"}
|
||||
summary = idx.Summary()
|
||||
if summary.Ready {
|
||||
t.Fatalf("size-mismatched release summary=%+v", summary)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitCDNPathRejectsEscape(t *testing.T) {
|
||||
if _, _, err := SplitCDNPath("/prod-clientpatch.bluearchiveyostar.com/../etc/passwd"); err == nil {
|
||||
t.Fatal("expected error")
|
||||
@@ -124,6 +147,17 @@ func TestCDNServesIndexedFile(t *testing.T) {
|
||||
if rr.Code != http.StatusNotFound {
|
||||
t.Fatalf("missing status=%d", rr.Code)
|
||||
}
|
||||
|
||||
req = httptest.NewRequest(
|
||||
http.MethodGet,
|
||||
"/prod-clientpatch.bluearchiveyostar.com/%2e%2e/yostar-serverinfo.bluearchiveyostar.com/r93_fixture.json",
|
||||
nil,
|
||||
)
|
||||
rr = httptest.NewRecorder()
|
||||
s.Handler().ServeHTTP(rr, req)
|
||||
if rr.Code != http.StatusNotFound {
|
||||
t.Fatalf("dot-segment status=%d body=%s", rr.Code, rr.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCDNSupportsRangeHeadAndConditionalRequests(t *testing.T) {
|
||||
@@ -524,6 +558,7 @@ type fakeBackend struct {
|
||||
status *backendrpc.DaemonStatusReport
|
||||
doctor *backendrpc.DoctorReport
|
||||
catalog json.RawMessage
|
||||
resource *backendrpc.ResourceState
|
||||
manifest *backendrpc.ResourceManifestPage
|
||||
}
|
||||
|
||||
@@ -539,6 +574,9 @@ func (f *fakeBackend) DaemonDoctor(ctx context.Context) (*backendrpc.DoctorRepor
|
||||
return f.doctor, nil
|
||||
}
|
||||
func (f *fakeBackend) ResourceState(ctx context.Context) (*backendrpc.ResourceState, error) {
|
||||
if f.resource != nil {
|
||||
return f.resource, nil
|
||||
}
|
||||
return &backendrpc.ResourceState{}, nil
|
||||
}
|
||||
func (f *fakeBackend) CatalogStatus(ctx context.Context) (json.RawMessage, error) {
|
||||
@@ -780,6 +818,112 @@ func TestDiscoverCallsStatusBeforeDoctor(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRefreshClearsPublishedIndexWhenCurrentReleaseDisappears(t *testing.T) {
|
||||
root := fixtureRoot(t)
|
||||
info, err := os.Stat(filepath.Join(root, "prod-clientpatch.bluearchiveyostar.com/r93_fixture/TableBundles/TableCatalog.bytes"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
size := uint64(info.Size())
|
||||
catalogRaw, err := json.Marshal(map[string]any{
|
||||
"available": true,
|
||||
"status": "published",
|
||||
"version": map[string]any{
|
||||
"id": "v1",
|
||||
"resource_root": root,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
backend := &fakeBackend{
|
||||
status: &backendrpc.DaemonStatusReport{Status: "ok", Running: true, RPCAvailable: true},
|
||||
doctor: &backendrpc.DoctorReport{Healthy: true, Status: "ok"},
|
||||
catalog: catalogRaw,
|
||||
manifest: &backendrpc.ResourceManifestPage{
|
||||
Available: true,
|
||||
ResourceRoot: root,
|
||||
ManifestVersion: 1,
|
||||
TotalEntries: 1,
|
||||
Entries: []backendrpc.ResourceManifestEntry{{
|
||||
URL: "https://prod-clientpatch.bluearchiveyostar.com/r93_fixture/TableBundles/TableCatalog.bytes",
|
||||
Destination: "prod-clientpatch.bluearchiveyostar.com/r93_fixture/TableBundles/TableCatalog.bytes",
|
||||
Bytes: &size,
|
||||
BLAKE3: strings.Repeat("0", 64),
|
||||
}},
|
||||
},
|
||||
}
|
||||
cfg := DefaultConfig()
|
||||
cfg.RefreshInterval = 0
|
||||
if err := cfg.Normalize(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s := NewServer(cfg, backend, log.New(io.Discard, "", 0))
|
||||
if err := s.Refresh(context.Background()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
initial := s.index()
|
||||
if initial == nil {
|
||||
t.Fatal("initial index missing")
|
||||
}
|
||||
if summary := initial.Summary(); !summary.Ready || summary.ResourceRoot != root {
|
||||
t.Fatalf("initial summary=%+v", summary)
|
||||
}
|
||||
|
||||
backend.catalog = json.RawMessage(`{"available":false,"status":"waiting"}`)
|
||||
outputRoot := filepath.Join(t.TempDir(), "official")
|
||||
backend.resource = &backendrpc.ResourceState{ResourceOutputRoot: &outputRoot}
|
||||
if err := s.Refresh(context.Background()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
current := s.index()
|
||||
if current == nil {
|
||||
t.Fatal("current index missing")
|
||||
}
|
||||
summary := current.Summary()
|
||||
if summary.Ready || summary.ResourceRoot != "" {
|
||||
t.Fatalf("stale summary=%+v", summary)
|
||||
}
|
||||
if len(s.meta.Warnings) == 0 {
|
||||
t.Fatal("missing disappearance warning")
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
s.Handler().ServeHTTP(rr, httptest.NewRequest(http.MethodGet, "/readyz", nil))
|
||||
if rr.Code != http.StatusServiceUnavailable {
|
||||
t.Fatalf("readyz status=%d body=%s", rr.Code, rr.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiscoverTreatsCatalogUnavailableAsNoRelease(t *testing.T) {
|
||||
fixture := fixtureRoot(t)
|
||||
outputRoot := t.TempDir()
|
||||
if err := os.Symlink(fixture, filepath.Join(outputRoot, "current")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
backend := &fakeBackend{
|
||||
status: &backendrpc.DaemonStatusReport{Status: "ok", Running: true, RPCAvailable: true},
|
||||
doctor: &backendrpc.DoctorReport{Healthy: true, Status: "ok"},
|
||||
catalog: json.RawMessage(`{"available":false,"status":"unavailable"}`),
|
||||
resource: &backendrpc.ResourceState{ResourceOutputRoot: &outputRoot},
|
||||
}
|
||||
|
||||
result, err := DiscoverAndIndex(context.Background(), backend, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if result.Index == nil {
|
||||
t.Fatal("index missing")
|
||||
}
|
||||
summary := result.Index.Summary()
|
||||
if summary.Ready || summary.ResourceRoot != "" || summary.EntryCount != 0 {
|
||||
t.Fatalf("catalog unavailable summary=%+v", summary)
|
||||
}
|
||||
if len(result.Warnings) == 0 {
|
||||
t.Fatal("missing catalog unavailable warning")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadEnvFileDoesNotOverride(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, ".env")
|
||||
|
||||
Reference in New Issue
Block a user