mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
* fix(client): 3 defect(s) (OC-0037, OC-0063, OC-0116) Route the tray Status submenu through saveUserStatus() (mapping the legacy "offline" to "invisible") so notifications, autoIdle, and reconnect presence restore all agree with the tray's choice; build the connected overlay from the auth_ok payload instead of a pre-dispatch authStore snapshot; keep the TOTP overlay open across a rejected verify (totpPending latch) and retain the partial token for the retry instead of clearing it in finally. Hand-applied combined cluster preserved from the previous fix run's overlap-guard block (both clusters edit main.ts). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(voice): 2 defect(s) (OC-0010, OC-0011) * fix(ws): 1 defect(s) (OC-0050) * fix(db): 1 defect(s) (OC-0052) * fix(client): 1 defect(s) (OC-0054) * fix(client): 1 defect(s) (OC-0059) * fix(auth): 1 defect(s) (OC-0061) * fix(ws): 1 defect(s) (OC-0062) * fix(client): 1 defect(s) (OC-0064) * fix(service): 1 defect(s) (OC-0070) * fix(ws): 1 defect(s) (OC-0073) * fix(service): 2 defect(s) (OC-0075, OC-0120) * fix(admin): 1 defect(s) (OC-0076) * fix(voice): 1 defect(s) (OC-0084) * fix(client): 2 defect(s) (OC-0085, OC-0094) Scope collapsed-category persistence to the connected host instead of the server display name, and stop the DM back button from jumping to the first text channel when DM mode was entered without recording channelBeforeDm. * fix(service): 1 defect(s) (OC-0087) * fix(client): 1 defect(s) (OC-0089) * fix(ws): 1 defect(s) (OC-0091) * fix(api): 1 defect(s) (OC-0093) * fix(identity): 1 defect(s) (OC-0118) * fix(dm): 1 defect(s) (OC-0119) * fix(voice): 1 defect(s) (OC-0135) * fix(api): 1 defect(s) (OC-0137) * fix(client): 1 defect(s) (OC-0142) * fix(client): 1 defect(s) (OC-0144) * fix(admin): 1 defect(s) (OC-0145) * fix(updater): 1 defect(s) (OC-0146) * fix(client): 1 defect(s) (OC-0150) * fix(mentions): 1 defect(s) (OC-0131) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
59 lines
1.5 KiB
Go
59 lines
1.5 KiB
Go
package updater
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"sync"
|
|
"sync/atomic"
|
|
"testing"
|
|
)
|
|
|
|
// A burst of concurrent CheckForUpdate calls against an expired/cold release
|
|
// cache must collapse into a single outbound GitHub fetch. Without
|
|
// singleflight, every caller that observes the cache as expired issues its
|
|
// own outbound request (OC-0146).
|
|
func TestCheckForUpdateCoalescesConcurrentMisses(t *testing.T) {
|
|
var hits atomic.Int64
|
|
release := newTestRelease("v2.0.0", "Major update", "https://github.com/J3vb/OwnCord/releases/tag/v2.0.0",
|
|
"https://github.com/J3vb/OwnCord/releases/download/v2.0.0")
|
|
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("/repos/J3vb/OwnCord/releases/latest", func(w http.ResponseWriter, r *http.Request) {
|
|
hits.Add(1)
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if err := json.NewEncoder(w).Encode(release); err != nil {
|
|
t.Fatalf("encoding release: %v", err)
|
|
}
|
|
})
|
|
srv := httptest.NewServer(mux)
|
|
defer srv.Close()
|
|
|
|
u := newTestUpdater(srv.URL, "1.0.0")
|
|
|
|
const callers = 25
|
|
var wg sync.WaitGroup
|
|
errs := make([]error, callers)
|
|
start := make(chan struct{})
|
|
|
|
for i := range callers {
|
|
wg.Go(func() {
|
|
<-start // release all goroutines together to force a real burst
|
|
_, errs[i] = u.CheckForUpdate(context.Background())
|
|
})
|
|
}
|
|
close(start)
|
|
wg.Wait()
|
|
|
|
for i := range callers {
|
|
if errs[i] != nil {
|
|
t.Fatalf("caller %d: unexpected error: %v", i, errs[i])
|
|
}
|
|
}
|
|
|
|
if got := hits.Load(); got != 1 {
|
|
t.Fatalf("outbound fetches = %d, want exactly 1 (singleflight should coalesce)", got)
|
|
}
|
|
}
|