183 lines
4.4 KiB
Go
183 lines
4.4 KiB
Go
package render
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
|
|
"github.com/peterqiu0516/sub-store/internal/model"
|
|
)
|
|
|
|
func makeTestNodes() []model.ProxyNode {
|
|
return []model.ProxyNode{
|
|
{
|
|
"type": "ss",
|
|
"name": "TestSS",
|
|
"server": "1.2.3.4",
|
|
"port": 8388,
|
|
"cipher": "aes-256-gcm",
|
|
"password": "pass123",
|
|
},
|
|
{
|
|
"type": "vmess",
|
|
"name": "TestVMess",
|
|
"server": "5.6.7.8",
|
|
"port": 443,
|
|
"uuid": "test-uuid",
|
|
"alterId": 0,
|
|
"cipher": "auto",
|
|
"network": "ws",
|
|
"tls": true,
|
|
"ws-opts": map[string]any{
|
|
"path": "/path",
|
|
"headers": map[string]any{"Host": "example.com"},
|
|
},
|
|
},
|
|
{
|
|
"type": "trojan",
|
|
"name": "TestTrojan",
|
|
"server": "9.10.11.12",
|
|
"port": 443,
|
|
"password": "trojan-pass",
|
|
"sni": "example.com",
|
|
},
|
|
}
|
|
}
|
|
|
|
func TestRenderMihomo(t *testing.T) {
|
|
nodes := makeTestNodes()
|
|
output, err := RenderTarget(nodes, "mihomo", nil)
|
|
if err != nil {
|
|
t.Fatalf("render mihomo failed: %v", err)
|
|
}
|
|
// Should be valid YAML
|
|
var parsed map[string]any
|
|
if err := yaml.Unmarshal([]byte(output), &parsed); err != nil {
|
|
t.Fatalf("output is not valid YAML: %v", err)
|
|
}
|
|
proxies, ok := parsed["proxies"].([]any)
|
|
if !ok {
|
|
t.Fatal("expected proxies array in YAML")
|
|
}
|
|
if len(proxies) != 3 {
|
|
t.Errorf("expected 3 proxies, got %d", len(proxies))
|
|
}
|
|
}
|
|
|
|
func TestRenderJSON(t *testing.T) {
|
|
nodes := makeTestNodes()
|
|
output, err := RenderTarget(nodes, "json", nil)
|
|
if err != nil {
|
|
t.Fatalf("render json failed: %v", err)
|
|
}
|
|
var parsed map[string]any
|
|
if err := json.Unmarshal([]byte(output), &parsed); err != nil {
|
|
t.Fatalf("output is not valid JSON: %v", err)
|
|
}
|
|
proxies, ok := parsed["proxies"].([]any)
|
|
if !ok {
|
|
t.Fatal("expected proxies array in JSON output")
|
|
}
|
|
if len(proxies) != 3 {
|
|
t.Errorf("expected 3 nodes, got %d", len(proxies))
|
|
}
|
|
}
|
|
|
|
func TestRenderURI(t *testing.T) {
|
|
nodes := makeTestNodes()
|
|
output, err := RenderTarget(nodes, "uri", nil)
|
|
if err != nil {
|
|
t.Fatalf("render uri failed: %v", err)
|
|
}
|
|
lines := strings.Split(strings.TrimSpace(output), "\n")
|
|
if len(lines) != 3 {
|
|
t.Errorf("expected 3 lines, got %d", len(lines))
|
|
}
|
|
// Each line should start with a protocol
|
|
for _, line := range lines {
|
|
line = strings.TrimSpace(line)
|
|
if !strings.Contains(line, "://") {
|
|
t.Errorf("expected URI format, got: %s", line)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRenderSurge(t *testing.T) {
|
|
nodes := makeTestNodes()[:2] // ss + vmess
|
|
output, err := RenderTarget(nodes, "surge", nil)
|
|
if err != nil {
|
|
t.Fatalf("render surge failed: %v", err)
|
|
}
|
|
if !strings.Contains(output, "TestSS") {
|
|
t.Error("expected TestSS in surge output")
|
|
}
|
|
}
|
|
|
|
func TestRenderSingBox(t *testing.T) {
|
|
nodes := makeTestNodes()[:1]
|
|
output, err := RenderTarget(nodes, "sing-box", nil)
|
|
if err != nil {
|
|
t.Fatalf("render sing-box failed: %v", err)
|
|
}
|
|
var parsed map[string]any
|
|
if err := json.Unmarshal([]byte(output), &parsed); err != nil {
|
|
t.Fatalf("sing-box output is not valid JSON: %v", err)
|
|
}
|
|
// Per review-resolution #42: should have log, inbounds, outbounds, route
|
|
if _, ok := parsed["outbounds"]; !ok {
|
|
t.Error("expected outbounds in sing-box output")
|
|
}
|
|
}
|
|
|
|
func TestRenderEmpty(t *testing.T) {
|
|
nodes := []model.ProxyNode{}
|
|
_, err := RenderTarget(nodes, "json", nil)
|
|
if err == nil {
|
|
// Some renderers may handle empty gracefully
|
|
}
|
|
}
|
|
|
|
func TestRenderUnsupportedTarget(t *testing.T) {
|
|
nodes := makeTestNodes()
|
|
// Unsupported targets fall back to mihomo per dispatch default
|
|
output, err := RenderTarget(nodes, "unsupported-target", nil)
|
|
if err != nil {
|
|
// Error is acceptable for unsupported targets
|
|
return
|
|
}
|
|
// If no error, output should be valid YAML
|
|
if output == "" {
|
|
t.Error("expected non-empty output")
|
|
}
|
|
}
|
|
|
|
func TestRenderMihomoWithTemplate(t *testing.T) {
|
|
nodes := makeTestNodes()
|
|
tmplConfig := map[string]any{
|
|
"proxy-groups": []any{
|
|
map[string]any{
|
|
"name": "PROXY",
|
|
"type": "select",
|
|
"proxies": []any{"TestSS", "TestVMess", "TestTrojan"},
|
|
},
|
|
},
|
|
}
|
|
output, err := RenderBuildTarget(nodes, "mihomo", "", tmplConfig)
|
|
if err != nil {
|
|
t.Fatalf("render mihomo with template failed: %v", err)
|
|
}
|
|
var parsed map[string]any
|
|
if err := yaml.Unmarshal([]byte(output), &parsed); err != nil {
|
|
t.Fatalf("output is not valid YAML: %v", err)
|
|
}
|
|
groups, ok := parsed["proxy-groups"].([]any)
|
|
if !ok {
|
|
t.Fatal("expected proxy-groups in YAML")
|
|
}
|
|
if len(groups) != 1 {
|
|
t.Errorf("expected 1 proxy group, got %d", len(groups))
|
|
}
|
|
}
|