108 lines
3.1 KiB
Go
108 lines
3.1 KiB
Go
|
|
package globals
|
||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/json"
|
||
|
|
"net/http"
|
||
|
|
"net/http/httptest"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestGostClientChainOperations(t *testing.T) {
|
||
|
|
var (
|
||
|
|
created *GostChainConfig
|
||
|
|
deleted []string
|
||
|
|
saved bool
|
||
|
|
)
|
||
|
|
|
||
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
username, password, ok := r.BasicAuth()
|
||
|
|
if !ok || username != "user" || password != "pass" {
|
||
|
|
t.Errorf("unexpected auth: ok=%v username=%q password=%q", ok, username, password)
|
||
|
|
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
switch {
|
||
|
|
case r.Method == http.MethodGet && r.URL.Path == "/api/config/chains":
|
||
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
||
|
|
"count": 2,
|
||
|
|
"list": []map[string]any{
|
||
|
|
{"name": "old-a"},
|
||
|
|
{"name": "old-b"},
|
||
|
|
},
|
||
|
|
})
|
||
|
|
case r.Method == http.MethodPost && r.URL.Path == "/api/config/chains":
|
||
|
|
if err := json.NewDecoder(r.Body).Decode(&created); err != nil {
|
||
|
|
t.Errorf("Decode chain failed: %v", err)
|
||
|
|
http.Error(w, "bad request", http.StatusBadRequest)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
_, _ = w.Write([]byte(`{}`))
|
||
|
|
case r.Method == http.MethodDelete && r.URL.Path == "/api/config/chains/old-a":
|
||
|
|
deleted = append(deleted, "old-a")
|
||
|
|
_, _ = w.Write([]byte(`{}`))
|
||
|
|
case r.Method == http.MethodDelete && r.URL.Path == "/api/config/chains/old-b":
|
||
|
|
deleted = append(deleted, "old-b")
|
||
|
|
_, _ = w.Write([]byte(`{}`))
|
||
|
|
case r.Method == http.MethodPost && r.URL.Path == "/api/config":
|
||
|
|
saved = true
|
||
|
|
_, _ = w.Write([]byte(`{}`))
|
||
|
|
default:
|
||
|
|
t.Errorf("unexpected request: %s %s", r.Method, r.URL.Path)
|
||
|
|
http.NotFound(w, r)
|
||
|
|
}
|
||
|
|
}))
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
client := NewGost(server.URL, 9700, "/api", "user", "pass")
|
||
|
|
|
||
|
|
chains, err := client.ListChains()
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("ListChains returned error: %v", err)
|
||
|
|
}
|
||
|
|
if len(chains) != 2 || chains[0].Name != "old-a" || chains[1].Name != "old-b" {
|
||
|
|
t.Fatalf("unexpected chains: %#v", chains)
|
||
|
|
}
|
||
|
|
|
||
|
|
if err := client.DeleteChain(chains[0].Name); err != nil {
|
||
|
|
t.Fatalf("DeleteChain old-a returned error: %v", err)
|
||
|
|
}
|
||
|
|
if err := client.DeleteChain(chains[1].Name); err != nil {
|
||
|
|
t.Fatalf("DeleteChain old-b returned error: %v", err)
|
||
|
|
}
|
||
|
|
if len(deleted) != 2 {
|
||
|
|
t.Fatalf("unexpected deleted chains: %#v", deleted)
|
||
|
|
}
|
||
|
|
|
||
|
|
err = client.CreateChain(&GostChainConfig{
|
||
|
|
Name: "edge-a",
|
||
|
|
Hops: []GostHopConfig{{
|
||
|
|
Nodes: []GostNodeConfig{{
|
||
|
|
Addr: "192.0.2.1:1080",
|
||
|
|
Connector: GostConnectorConfig{Type: "socks5"},
|
||
|
|
Dialer: GostDialerConfig{Type: "tcp"},
|
||
|
|
}},
|
||
|
|
}},
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("CreateChain returned error: %v", err)
|
||
|
|
}
|
||
|
|
if created == nil || created.Name != "edge-a" {
|
||
|
|
t.Fatalf("unexpected created chain: %#v", created)
|
||
|
|
}
|
||
|
|
if len(created.Hops) != 1 || len(created.Hops[0].Nodes) != 1 {
|
||
|
|
t.Fatalf("unexpected created chain hops: %#v", created.Hops)
|
||
|
|
}
|
||
|
|
node := created.Hops[0].Nodes[0]
|
||
|
|
if node.Addr != "192.0.2.1:1080" || node.Connector.Type != "socks5" || node.Dialer.Type != "tcp" {
|
||
|
|
t.Fatalf("unexpected created node: %#v", node)
|
||
|
|
}
|
||
|
|
|
||
|
|
if err := client.SaveConfig(); err != nil {
|
||
|
|
t.Fatalf("SaveConfig returned error: %v", err)
|
||
|
|
}
|
||
|
|
if !saved {
|
||
|
|
t.Fatal("expected SaveConfig request")
|
||
|
|
}
|
||
|
|
}
|