Delta getState by rev, pause when hidden, cancellable background loops, hostCache bounds, unlock PollUI around engine status, corebin singleflight, PingAll worker pool. Co-authored-by: Cursor <cursoragent@cursor.com>
96 lines
2.5 KiB
Go
96 lines
2.5 KiB
Go
package apphost
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"vpnclient/internal/config"
|
|
"vpnclient/internal/core"
|
|
"vpnclient/internal/logbuf"
|
|
)
|
|
|
|
func TestHTTPBridgeGetState(t *testing.T) {
|
|
cfg := &config.Config{
|
|
Active: "demo",
|
|
Profiles: []config.Profile{
|
|
{Name: "demo", Protocol: config.ProtocolNaive, Proxy: "https://u:p@example.com"},
|
|
},
|
|
}
|
|
mgr, err := core.NewManager("", cfg, logbuf.New(0))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a := New(mgr, "", logbuf.New(0))
|
|
a.APIToken = "test-token"
|
|
|
|
body, _ := json.Marshal(map[string]any{"args": []any{}})
|
|
req := httptest.NewRequest(http.MethodPost, "/api/getState", bytes.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("X-Navis-Token", "test-token")
|
|
rr := httptest.NewRecorder()
|
|
a.Handler().ServeHTTP(rr, req)
|
|
if rr.Code != http.StatusOK {
|
|
t.Fatalf("status %d body %s", rr.Code, rr.Body.String())
|
|
}
|
|
var resp struct {
|
|
Result UIState `json:"result"`
|
|
Error string `json:"error"`
|
|
}
|
|
if err := json.Unmarshal(rr.Body.Bytes(), &resp); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resp.Error != "" {
|
|
t.Fatalf("api error: %s", resp.Error)
|
|
}
|
|
if resp.Result.ActiveProfile != "demo" {
|
|
t.Fatalf("active_profile=%q", resp.Result.ActiveProfile)
|
|
}
|
|
}
|
|
|
|
func TestHTTPBridgeGetStateUnchanged(t *testing.T) {
|
|
cfg := &config.Config{
|
|
Active: "demo",
|
|
Profiles: []config.Profile{
|
|
{Name: "demo", Protocol: config.ProtocolNaive, Proxy: "https://u:p@example.com"},
|
|
},
|
|
}
|
|
mgr, err := core.NewManager("", cfg, logbuf.New(0))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a := New(mgr, "", logbuf.New(0))
|
|
a.APIToken = "test-token"
|
|
|
|
full, err := a.GetStateSince("")
|
|
if err != nil || full.Unchanged || full.Rev == "" {
|
|
t.Fatalf("full: unchanged=%v rev=%q err=%v", full.Unchanged, full.Rev, err)
|
|
}
|
|
again, err := a.GetStateSince(full.Rev)
|
|
if err != nil || !again.Unchanged || again.Rev != full.Rev {
|
|
t.Fatalf("delta: %+v err=%v", again, err)
|
|
}
|
|
if len(again.Profiles) != 0 {
|
|
t.Fatalf("unchanged payload should omit profiles, got %d", len(again.Profiles))
|
|
}
|
|
}
|
|
|
|
func TestHTTPBridgeRejectsBadToken(t *testing.T) {
|
|
cfg := &config.Config{}
|
|
mgr, err := core.NewManager("", cfg, logbuf.New(0))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a := New(mgr, "", logbuf.New(0))
|
|
a.APIToken = "secret"
|
|
req := httptest.NewRequest(http.MethodPost, "/api/getState", bytes.NewReader([]byte(`{"args":[]}`)))
|
|
req.Header.Set("X-Navis-Token", "wrong")
|
|
rr := httptest.NewRecorder()
|
|
a.Handler().ServeHTTP(rr, req)
|
|
if rr.Code != http.StatusUnauthorized {
|
|
t.Fatalf("want 401, got %d", rr.Code)
|
|
}
|
|
}
|