返回 DeepSeek-Reasonix
remote_model_ownership_test.go
根目录 / desktop / remote_model_ownership_test.go
1 package main
2
3 import (
4 "net/http"
5 "net/http/httptest"
6 "testing"
7
8 "reasonix/internal/config"
9 )
10
11 func TestRemoteOwnershipRejectsOvertakenReceipts(t *testing.T) {
12 for _, scenario := range []string{"old status", "old install", "old incarnation", "unversioned"} {
13 t.Run(scenario, func(t *testing.T) {
14 scope := credentialProxyScope("h", "w")
15 up := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) }))
16 defer up.Close()
17 p := &credentialProxy{routes: map[string]*credProxyRoute{}}
18 app := &App{credProxy: p}
19 _, err := p.resolveAndSetRoute("new-token", "p/m", func() (proxyUpstream, error) {
20 return proxyUpstream{url: mustParseURL(t, up.URL), scope: scope, revision: "new", offerID: "candidate"}, nil
21 })
22 if err != nil {
23 t.Fatal(err)
24 }
25 old := remoteModelSettingsStatus{Version: 1, ModelSettingsOwnership: config.ModelSettingsOwnership{OwnershipIncarnation: "instance", OwnershipSeq: 1}, OwnedRevisions: []string{"old"}}
26 if !app.pinCredentialProxyOwnership("h", "w", old) {
27 t.Fatal("pin failed")
28 }
29 fresh := old
30 fresh.OwnershipSeq = 3
31 fresh.OwnedRevisions = []string{"new"}
32 if scenario == "old incarnation" {
33 fresh.OwnershipIncarnation = "replacement"
34 app.pinCredentialProxyOwnership("h", "w", fresh)
35 }
36 if scenario == "unversioned" {
37 fresh.UnversionedOwners = true
38 }
39 if !app.reconcileCredentialProxyGenerations("h", "w", fresh, "candidate") {
40 t.Fatal("fresh receipt rejected")
41 }
42 var released []string
43 if scenario == "old install" {
44 p.routes["new-token"].holds["old-install"] = true
45 released = []string{"old-install"}
46 }
47 if app.reconcileCredentialProxyGenerations("h", "w", old, released...) {
48 t.Fatal("stale receipt accepted")
49 }
50 if p.routes["new-token"].holds["old-install"] {
51 t.Fatal("confirmed stale install retained its reservation")
52 }
53 req := httptest.NewRequest(http.MethodPost, "http://proxy/v1/chat/completions", nil)
54 req.Header.Set("Authorization", "Bearer new-token")
55 res := httptest.NewRecorder()
56 p.ServeHTTP(res, req)
57 if res.Code != 204 {
58 t.Fatalf("live runtime route revoked: %d %s", res.Code, res.Body)
59 }
60 })
61 }
62 }
63
64 func TestRemoteIncarnationReclaimsOldReservationsAndRejectsLateBuilders(t *testing.T) {
65 scope := credentialProxyScope("h", "w")
66 p := &credentialProxy{routes: map[string]*credProxyRoute{"token": {scope: scope, revision: "old", holds: map[string]bool{"old-offer": true}}}}
67 app := &App{credProxy: p}
68 status := remoteModelSettingsStatus{Version: 1, ModelSettingsOwnership: config.ModelSettingsOwnership{OwnershipIncarnation: "old", OwnershipSeq: 1}}
69 app.pinCredentialProxyOwnership("h", "w", status)
70 app.reserveCredentialProxyInstall("h", "w", "old-offer", "old", "old")
71 status.OwnershipIncarnation = "new"
72 app.pinCredentialProxyOwnership("h", "w", status)
73 if len(p.routes["token"].holds) != 0 {
74 t.Fatal("old incarnation leaked reservations")
75 }
76 if app.reserveCredentialProxyInstall("h", "w", "late-offer", "old", "old") {
77 t.Fatal("late old builder registered a reservation")
78 }
79 app.reconcileCredentialProxyGenerations("h", "w", status)
80 if p.routes["token"] != nil {
81 t.Fatal("dead process route was not retired")
82 }
83 }
84
85 func TestRemoteReplacedConnectionCannotPinOwnership(t *testing.T) {
86 p := &credentialProxy{routes: map[string]*credProxyRoute{}}
87 app := &App{credProxy: p}
88 old, current := &managedHost{}, &managedHost{}
89 m := &desktopRemoteManager{hosts: map[string]*managedHost{"h": old}}
90 status := remoteModelSettingsStatus{Version: 1, ModelSettingsOwnership: config.ModelSettingsOwnership{OwnershipIncarnation: "new", OwnershipSeq: 1}}
91 // The old operation has already captured its managed pointer and GET. A
92 // replacement publishes and pins before that old operation resumes.
93 m.mu.Lock()
94 m.hosts["h"] = current
95 m.mu.Unlock()
96 if !m.pinModelSettingsOwnership(app, "h", "w", current, status) {
97 t.Fatal("current pin failed")
98 }
99 status.OwnershipIncarnation = "old"
100 if m.pinModelSettingsOwnership(app, "h", "w", old, status) {
101 t.Fatal("replaced connection regained authority")
102 }
103 if p.ownership[credentialProxyScope("h", "w")].OwnershipIncarnation != "new" {
104 t.Fatal("incarnation rolled back")
105 }
106 }
107
108 func TestRemoteUnknownInstallRetainsOfferUntilOwned(t *testing.T) {
109 scope := credentialProxyScope("h", "w")
110 p := &credentialProxy{routes: map[string]*credProxyRoute{"token": {scope: scope, revision: "candidate", holds: map[string]bool{"offer": true}}}}
111 app := &App{credProxy: p}
112 status := remoteModelSettingsStatus{Version: 1, ModelSettingsOwnership: config.ModelSettingsOwnership{OwnershipIncarnation: "serve", OwnershipSeq: 1}, OwnedRevisions: []string{"old"}}
113 app.pinCredentialProxyOwnership("h", "w", status)
114 app.reserveCredentialProxyInstall("h", "w", "offer", "candidate", "serve")
115 app.reconcileCredentialProxyGenerations("h", "w", status)
116 if p.routes["token"] == nil || !p.routes["token"].holds["offer"] {
117 t.Fatal("uncertain installation lost reservation")
118 }
119 status.OwnershipSeq++
120 status.OwnedRevisions = []string{"candidate"}
121 app.reconcileCredentialProxyGenerations("h", "w", status)
122 if p.routes["token"] == nil || len(p.routes["token"].holds) != 0 {
123 t.Fatal("owned installation did not release reservation")
124 }
125 status.OwnershipSeq++
126 status.OwnedRevisions = []string{"next"}
127 app.reconcileCredentialProxyGenerations("h", "w", status)
128 if p.routes["token"] != nil {
129 t.Fatal("superseded installation route leaked")
130 }
131 }
132
132 lines GO