Initial commit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 13:57:10 +08:00
co-authored by Claude Opus 5
commit 8679200f41
1897 changed files with 257900 additions and 0 deletions
+120
View File
@@ -0,0 +1,120 @@
package versionser
import (
"encoding/json"
"net/http"
"net/http/httptest"
"sync"
"sync/atomic"
"testing"
"time"
"91porn-server/app/appg"
"91porn-server/common/localcache"
)
func TestAdvVersionAnnounThreeServerCoalescesConcurrentMisses(t *testing.T) {
var calls atomic.Int32
var badRequest atomic.Bool
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
calls.Add(1)
if r.Method != http.MethodPost || r.URL.Path != "/api/stat/all/app" {
badRequest.Store(true)
w.WriteHeader(http.StatusBadRequest)
_, _ = w.Write([]byte(`{}`))
return
}
time.Sleep(50 * time.Millisecond)
_ = json.NewEncoder(w).Encode(AppAllResp{
VersionInfo: VersionInfo{ServerVersion: "9.9.9"},
AnnouList: []AnnouInfo{{ID: "announcement-1"}},
IosUrl: "ios-url",
AndroidUrl: "android-url",
ShopIosLink: "shop-ios-url",
})
}))
defer server.Close()
setVersionTestConfig(t, server.URL)
version := "singleflight-test"
deleteVersionTestCache(t, "VerAnnInfo:"+version)
const concurrency = 20
start := make(chan struct{})
errs := make(chan error, concurrency)
var wg sync.WaitGroup
for i := 0; i < concurrency; i++ {
wg.Add(1)
go func() {
defer wg.Done()
<-start
ver, _, annou, iosURL, androidURL, shopURL, err := AdvVersionAnnounThreeServer(version, "android")
if err == nil && (ver.ServerVersion != "9.9.9" || len(annou) != 1 || iosURL != "ios-url" || androidURL != "android-url" || shopURL != "shop-ios-url") {
err = &unexpectedVersionResponseError{}
}
errs <- err
}()
}
close(start)
wg.Wait()
close(errs)
for err := range errs {
if err != nil {
t.Fatalf("unexpected result: %v", err)
}
}
if got := calls.Load(); got != 1 {
t.Fatalf("downstream calls = %d, want 1", got)
}
if badRequest.Load() {
t.Fatal("downstream request used an unexpected method or path")
}
}
func TestAdvVersionAnnounThreeServerCachesFailureFallback(t *testing.T) {
var calls atomic.Int32
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
calls.Add(1)
w.WriteHeader(http.StatusMethodNotAllowed)
_, _ = w.Write([]byte(`{}`))
}))
defer server.Close()
setVersionTestConfig(t, server.URL)
version := "failure-cache-test"
deleteVersionTestCache(t, "VerAnnInfo:"+version)
if _, _, _, _, _, _, err := AdvVersionAnnounThreeServer(version, "android"); err == nil {
t.Fatal("first request error = nil, want downstream status error")
}
if _, _, _, _, _, _, err := AdvVersionAnnounThreeServer(version, "android"); err != nil {
t.Fatalf("cached fallback error = %v, want nil", err)
}
if got := calls.Load(); got != 1 {
t.Fatalf("downstream calls = %d, want 1", got)
}
}
type unexpectedVersionResponseError struct{}
func (*unexpectedVersionResponseError) Error() string { return "unexpected version response" }
func setVersionTestConfig(t *testing.T, productURL string) {
t.Helper()
previous := appg.Conf
conf := &appg.GlobalConfig{}
conf.URL.ProductUrl = productURL
appg.Conf = conf
t.Cleanup(func() { appg.Conf = previous })
}
func deleteVersionTestCache(t *testing.T, key string) {
t.Helper()
localcache.C.Delete(key)
localcache.C.Delete(key + ":lastSuccess")
t.Cleanup(func() {
localcache.C.Delete(key)
localcache.C.Delete(key + ":lastSuccess")
})
}