Some checks failed
CI/CD Pipeline / Test (push) Failing after 22m19s
CI/CD Pipeline / Security Scan (push) Failing after 5m57s
CI/CD Pipeline / Build (amd64, darwin) (push) Has been skipped
CI/CD Pipeline / Build (amd64, linux) (push) Has been skipped
CI/CD Pipeline / Build (amd64, windows) (push) Has been skipped
CI/CD Pipeline / Build (arm64, darwin) (push) Has been skipped
CI/CD Pipeline / Build (arm64, linux) (push) Has been skipped
CI/CD Pipeline / Build Docker Image (push) Has been skipped
CI/CD Pipeline / Create Release (push) Has been skipped
148 lines
4.1 KiB
Go
148 lines
4.1 KiB
Go
package e2e
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestExtendedHealthEndpoints(t *testing.T) {
|
|
config := `server:
|
|
host: "127.0.0.1"
|
|
port: 26660
|
|
logging:
|
|
level: "error"
|
|
format: "text"
|
|
`
|
|
|
|
app, _, cleanup := setupTestApplicationWithConfig(t, config)
|
|
t.Cleanup(cleanup)
|
|
|
|
server := app.GetHTTPServer()
|
|
|
|
endpoints := []string{"/ready", "/live", "/metrics", "/ping"}
|
|
for _, ep := range endpoints {
|
|
ep := ep
|
|
t.Run(ep, func(t *testing.T) {
|
|
resp := doRequest(t, server, http.MethodGet, ep)
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode != http.StatusOK {
|
|
t.Fatalf("expected 200 for %s, got %d", ep, resp.StatusCode)
|
|
}
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
t.Fatalf("failed to read %s response: %v", ep, err)
|
|
}
|
|
if len(body) == 0 {
|
|
t.Fatalf("expected non-empty body for %s", ep)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVersionPlainTextMode(t *testing.T) {
|
|
config := `server:
|
|
host: "127.0.0.1"
|
|
port: 26670
|
|
logging:
|
|
level: "error"
|
|
format: "text"
|
|
`
|
|
|
|
app, _, cleanup := setupTestApplicationWithConfig(t, config)
|
|
t.Cleanup(cleanup)
|
|
server := app.GetHTTPServer()
|
|
|
|
resp := doRequest(t, server, http.MethodGet, "/version?format=plain")
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode != http.StatusOK {
|
|
t.Fatalf("expected 200 for plain version, got %d", resp.StatusCode)
|
|
}
|
|
if ct := resp.Header.Get("Content-Type"); ct != "text/plain; charset=utf-8" {
|
|
t.Fatalf("expected text/plain content type, got %q", ct)
|
|
}
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
t.Fatalf("failed to read version body: %v", err)
|
|
}
|
|
if len(body) == 0 || body[len(body)-1] != '\n' {
|
|
t.Fatalf("expected newline terminated version string, got %q", string(body))
|
|
}
|
|
}
|
|
|
|
func TestCompatibilityRouteSmoke(t *testing.T) {
|
|
config := `server:
|
|
host: "127.0.0.1"
|
|
port: 26680
|
|
logging:
|
|
level: "error"
|
|
format: "text"
|
|
security:
|
|
access_tokens:
|
|
- "legacy-token"
|
|
conversion:
|
|
cache_timeout: 60
|
|
`
|
|
|
|
app, _, cleanup := setupTestApplicationWithConfig(t, config)
|
|
t.Cleanup(cleanup)
|
|
server := app.GetHTTPServer()
|
|
|
|
token := "legacy-token"
|
|
|
|
type routeExpect struct {
|
|
method string
|
|
path string
|
|
status int
|
|
}
|
|
|
|
localFile := filepath.Join(t.TempDir(), "sample.txt")
|
|
if err := os.WriteFile(localFile, []byte("content"), 0o644); err != nil {
|
|
t.Fatalf("failed to write local file: %v", err)
|
|
}
|
|
|
|
rulesetEncoded := base64.StdEncoding.EncodeToString([]byte("ruleset," + filepath.ToSlash(filepath.Join("rules", "LocalAreaNetwork.list"))))
|
|
|
|
remoteServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
_, _ = w.Write([]byte("ok"))
|
|
}))
|
|
defer remoteServer.Close()
|
|
|
|
routes := []routeExpect{
|
|
{http.MethodGet, "/sub?target=clash&url=https://mock-subscribe.example.com", http.StatusOK},
|
|
{http.MethodGet, "/sub2clashr?sublink=https://mock-subscribe.example.com", http.StatusOK},
|
|
{http.MethodGet, "/surge2clash?link=https://mock-subscribe.example.com", http.StatusOK},
|
|
{http.MethodGet, "/getruleset?type=1&url=" + url.QueryEscape(rulesetEncoded), http.StatusOK},
|
|
{http.MethodGet, "/getprofile?name=" + url.QueryEscape(localFile) + "&token=" + token, http.StatusForbidden},
|
|
{http.MethodGet, "/refreshrules?token=" + token, http.StatusOK},
|
|
{http.MethodGet, "/readconf?token=" + token, http.StatusOK},
|
|
{http.MethodPost, "/updateconf?type=form&token=" + token, http.StatusBadRequest},
|
|
{http.MethodGet, "/flushcache?token=" + token, http.StatusOK},
|
|
{http.MethodGet, "/get?url=" + url.QueryEscape(remoteServer.URL), http.StatusOK},
|
|
{http.MethodGet, "/getlocal?path=" + url.QueryEscape(localFile), http.StatusOK},
|
|
}
|
|
|
|
for _, rt := range routes {
|
|
rt := rt
|
|
t.Run(rt.path, func(t *testing.T) {
|
|
var resp *http.Response
|
|
if rt.method == http.MethodPost {
|
|
resp = doRequestWithBody(t, server, rt.method, rt.path, strings.NewReader(""), map[string]string{"Content-Type": "text/plain"})
|
|
} else {
|
|
resp = doRequest(t, server, rt.method, rt.path)
|
|
}
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode != rt.status {
|
|
t.Fatalf("expected status %d for %s %s, got %d", rt.status, rt.method, rt.path, resp.StatusCode)
|
|
}
|
|
})
|
|
}
|
|
}
|