mirror of
https://gitcode.com/JianFeeeee/webui4frpc.git
synced 2026-09-20 08:57:55 +00:00
155 lines
4.2 KiB
Go
155 lines
4.2 KiB
Go
package cluster
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
// writeFakeFrpc writes an executable file pretending to be frpc (any bytes
|
|
// work for tests that don't run --version).
|
|
func writeFakeFrpc(t *testing.T, dir, version string) string {
|
|
t.Helper()
|
|
binDir := filepath.Join(dir, "frpc-"+version)
|
|
if err := os.MkdirAll(binDir, 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
bin := filepath.Join(binDir, "frpc")
|
|
if err := os.WriteFile(bin, []byte("#!/bin/sh\necho frpc "+version+"\n"), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return bin
|
|
}
|
|
|
|
func TestCachedVersionsAndProvide(t *testing.T) {
|
|
dir := t.TempDir()
|
|
writeFakeFrpc(t, dir, "0.71.0")
|
|
reg := NewRegistry(dir)
|
|
vs := reg.CachedVersions()
|
|
if len(vs) != 1 || vs[0] != "0.71.0" {
|
|
t.Fatalf("cached versions = %+v", vs)
|
|
}
|
|
if !reg.HasVersion("0.71.0") || reg.HasVersion("0.99.0") {
|
|
t.Fatalf("HasVersion wrong")
|
|
}
|
|
p, sum, err := reg.Provide("0.71.0")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if p == "" || len(sum) != 64 {
|
|
t.Fatalf("provide p=%s sum=%s", p, sum)
|
|
}
|
|
}
|
|
|
|
func TestEnsureVersionPrefersLocalAndPeer(t *testing.T) {
|
|
dir := t.TempDir()
|
|
reg := NewRegistry(dir)
|
|
|
|
peerBin := []byte("#!/bin/sh\necho fake-frpc\n")
|
|
sum := sha256.Sum256(peerBin)
|
|
peerSum := hex.EncodeToString(sum[:])
|
|
|
|
peerSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path == "/frpc/0.71.0" {
|
|
w.Header().Set("X-Frpc-SHA256", peerSum)
|
|
_, _ = w.Write(peerBin)
|
|
return
|
|
}
|
|
http.NotFound(w, r)
|
|
}))
|
|
defer peerSrv.Close()
|
|
host := peerSrv.Listener.Addr().String()
|
|
|
|
reg.RegisterPeer("peer1", host, "u", "p")
|
|
if reg.HasVersion("0.71.0") {
|
|
t.Fatal("should not be cached yet")
|
|
}
|
|
binPath, err := reg.EnsureVersion(context.Background(), "0.71.0")
|
|
if err != nil {
|
|
t.Fatalf("EnsureVersion: %v", err)
|
|
}
|
|
if !reg.HasVersion("0.71.0") {
|
|
t.Fatal("EnsureVersion should have stored binary")
|
|
}
|
|
got, err := reg.EnsureVersion(context.Background(), "0.71.0")
|
|
if err != nil || got != binPath {
|
|
t.Fatalf("local hit = %q err=%v", got, err)
|
|
}
|
|
}
|
|
|
|
func TestFetchFromPeerChecksumMismatch(t *testing.T) {
|
|
peerSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
_, _ = w.Write([]byte("corrupted"))
|
|
}))
|
|
defer peerSrv.Close()
|
|
_, err := fetchFromPeer(context.Background(), &PeerTarget{Addr: peerSrv.Listener.Addr().String()}, "1.2.3", "0000000000000000000000000000000000000000000000000000000000000000")
|
|
if err == nil {
|
|
t.Fatal("expected checksum mismatch error")
|
|
}
|
|
}
|
|
|
|
func TestRegisterAndDiscover(t *testing.T) {
|
|
dir := t.TempDir()
|
|
writeFakeFrpc(t, dir, "0.70.0")
|
|
reg := NewRegistry(dir)
|
|
|
|
peerSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path == "/api/manager/cluster/nodes" {
|
|
_, _ = w.Write([]byte(`{"nodes":[{"addr":"10.0.0.9:7500","cache":["0.71.0"],"version":"0.71.0"}]}`))
|
|
return
|
|
}
|
|
http.NotFound(w, r)
|
|
}))
|
|
defer peerSrv.Close()
|
|
|
|
reg.RegisterPeer("peerX", peerSrv.Listener.Addr().String(), "u", "p")
|
|
ni, err := reg.queryNode(context.Background(), reg.PeerList()[0])
|
|
if err != nil {
|
|
t.Fatalf("queryNode: %v", err)
|
|
}
|
|
if ni.Version != "0.71.0" || len(ni.Cache) != 1 {
|
|
t.Fatalf("node info = %+v", ni)
|
|
}
|
|
reg.UpdateNodeInfo(ni)
|
|
if got := reg.NodeList(); len(got) != 1 || got[0].Addr != "10.0.0.9:7500" {
|
|
t.Fatalf("node list = %+v", got)
|
|
}
|
|
}
|
|
|
|
func TestCacheInfoAndPrune(t *testing.T) {
|
|
dir := t.TempDir()
|
|
writeFakeFrpc(t, dir, "0.70.0")
|
|
writeFakeFrpc(t, dir, "0.71.0")
|
|
reg := NewRegistry(dir)
|
|
infos := reg.CacheInfo()
|
|
if len(infos) != 2 {
|
|
t.Fatalf("cache info = %+v", infos)
|
|
}
|
|
// prune keep=1 -> removes oldest by modtime (0.70.0 likely older)
|
|
removed := reg.PruneCache(1)
|
|
_ = removed
|
|
if len(reg.CacheInfo()) != 1 {
|
|
t.Fatalf("after prune keep=1: %+v", reg.CacheInfo())
|
|
}
|
|
}
|
|
|
|
func TestPathSafeVersion(t *testing.T) {
|
|
good := []string{"0.71.0", "v0.71.0", "1.2.3-beta", "0.71.0-rc1_amd64"}
|
|
for _, v := range good {
|
|
if _, ok := pathSafeVersion(v); !ok {
|
|
t.Fatalf("expected safe: %q", v)
|
|
}
|
|
}
|
|
bad := []string{"", "../evil", "a/b", "..", `x\y`, "0.7 1.0"}
|
|
for _, v := range bad {
|
|
if _, ok := pathSafeVersion(v); ok {
|
|
t.Fatalf("expected unsafe: %q", v)
|
|
}
|
|
}
|
|
}
|