Files
subconverter-go/tests/conversion/engine_test.go
Rogee 7fcabe0225
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
first commit
2025-09-28 10:05:07 +08:00

259 lines
7.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package conversion_test
import (
"io"
"net/http"
"strings"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
"github.com/subconverter-go/internal/config"
"github.com/subconverter-go/internal/conversion"
"github.com/subconverter-go/internal/generator"
"github.com/subconverter-go/internal/logging"
"github.com/subconverter-go/internal/parser"
)
type roundTripFunc func(*http.Request) (*http.Response, error)
func (f roundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) {
return f(req)
}
func newMockHTTPClient() *http.Client {
return &http.Client{
Timeout: 5 * time.Second,
Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) {
body := sampleSubscriptionForURL(req.URL.String())
status := http.StatusOK
if body == "" {
status = http.StatusNotFound
}
resp := &http.Response{
StatusCode: status,
Header: make(http.Header),
Body: io.NopCloser(strings.NewReader(body)),
}
resp.Header.Set("Content-Type", "text/plain; charset=utf-8")
return resp, nil
}),
}
}
func sampleSubscriptionForURL(u string) string {
switch {
case strings.Contains(u, "ss-subscribe"):
return "ss://aes-256-cfb:password@192.168.1.1:8388"
case strings.Contains(u, "vmess-subscribe"):
return "vmess://eyJhZGQiOiIxOTIuMTY4LjEuMiIsICJwcyI6IlRlc3QgVk1lc3MiLCAicG9ydCI6NDQzLCAiaWQiOiI2YjZkZTQ3Zi1kZjQ1LTQ1M2ItODI1MS1hZjM0ZTM0ODc1Y2UifQ=="
case strings.Contains(u, "subscribe"):
return "ss://aes-256-cfb:password@192.168.1.1:8388\nvmess://eyJhZGQiOiIxOTIuMTY4LjEuMiIsICJwcyI6IlRlc3QgVk1lc3MiLCAicG9ydCI6NDQzLCAiaWQiOiI2YjZkZTQ3Zi1kZjQ1LTQ1M2ItODI1MS1hZjM0ZTM0ODc1Y2UifQ==\ntrojan://password@192.168.1.3:443"
default:
return ""
}
}
func TestConversionEngine(t *testing.T) {
Convey("ConversionEngine", t, func() {
// 创建日志记录器
logger, err := logging.NewLogger(&logging.LoggingConfig{
Level: "info",
Format: "text",
Output: "stdout",
})
So(err, ShouldBeNil)
// 创建配置管理器
configMgr, err := config.NewConfigManager("")
So(err, ShouldBeNil)
// 创建解析器管理器
parserMgr := parser.NewParserManager(logger, configMgr)
// 创建生成器管理器
generatorMgr := generator.NewGeneratorManager(logger)
// 创建转换引擎
engine := conversion.NewConversionEngine(logger, parserMgr, generatorMgr)
engine.SetHTTPClient(newMockHTTPClient())
Convey("应该能验证转换请求", func() {
// 测试有效请求
validRequest := &conversion.ConversionRequest{
Target: "clash",
URL: "https://example.com/subscribe", // 使用URL而不是InputText
}
response, err := engine.Convert(validRequest)
So(err, ShouldBeNil)
So(response, ShouldNotBeNil)
// 测试无效请求 - 缺少URL
invalidRequest1 := &conversion.ConversionRequest{
Target: "clash",
}
response, err = engine.Convert(invalidRequest1)
So(err, ShouldBeNil)
So(response.Success, ShouldBeFalse)
So(response.Error, ShouldContainSubstring, "source URL cannot be empty")
// 测试无效请求 - 不支持的目标格式
invalidRequest2 := &conversion.ConversionRequest{
Target: "unsupported",
URL: "https://example.com/subscribe",
}
response, err = engine.Convert(invalidRequest2)
So(err, ShouldBeNil)
So(response.Success, ShouldBeFalse)
So(response.Error, ShouldContainSubstring, "unsupported target format")
})
Convey("应该能解析Shadowsocks配置", func() {
request := &conversion.ConversionRequest{
Target: "clash",
URL: "https://example.com/ss-subscribe",
Group: "Test SS",
UDP: true,
}
response, err := engine.Convert(request)
So(err, ShouldBeNil)
So(response.Success, ShouldBeTrue)
So(response.NodeCount, ShouldBeGreaterThan, 0)
So(response.Content, ShouldNotBeNil)
// Check if content contains the cipher or if it's in JSON format
contentContainsCipher := strings.Contains(response.Content, "aes-256-cfb")
contentIsJSON := strings.Contains(response.Content, `"cipher":"aes-256-cfb"`)
So(contentContainsCipher || contentIsJSON, ShouldBeTrue)
})
Convey("应该能解析VMess配置", func() {
request := &conversion.ConversionRequest{
Target: "clash",
URL: "https://example.com/vmess-subscribe",
Group: "Test VMess",
UDP: true,
}
response, err := engine.Convert(request)
So(err, ShouldBeNil)
So(response.Success, ShouldBeTrue)
So(response.NodeCount, ShouldBeGreaterThan, 0)
So(response.Content, ShouldNotBeNil)
})
Convey("应该能处理无效URL", func() {
request := &conversion.ConversionRequest{
Target: "clash",
URL: "invalid-url",
Group: "Test Invalid",
}
response, err := engine.Convert(request)
So(err, ShouldBeNil)
So(response.Success, ShouldBeFalse)
So(response.Error, ShouldNotBeNil)
})
Convey("应该能生成多种目标格式", func() {
formats := []string{"clash", "surge", "quantumultx", "loon", "surfboard", "v2ray"}
for _, format := range formats {
request := &conversion.ConversionRequest{
Target: format,
URL: "https://example.com/subscribe",
Group: "Test Multi " + format,
UDP: true,
}
response, err := engine.Convert(request)
So(err, ShouldBeNil)
So(response.Success, ShouldBeTrue)
So(response.NodeCount, ShouldBeGreaterThan, 0)
So(response.TargetFormat, ShouldEqual, format)
}
})
Convey("应该能处理URL获取请求", func() {
request := &conversion.ConversionRequest{
Target: "clash",
URL: "https://example.com/subscribe",
Group: "Test URL",
}
response, err := engine.Convert(request)
So(err, ShouldBeNil)
// 由于URL获取尚未实现这里会使用默认配置
So(response.Success, ShouldBeTrue)
})
Convey("应该能提供调试信息", func() {
request := &conversion.ConversionRequest{
Target: "clash",
URL: "https://example.com/subscribe",
Group: "Test Debug",
}
response, err := engine.Convert(request)
So(err, ShouldBeNil)
So(response.Success, ShouldBeTrue)
So(response.DebugInfo, ShouldNotBeNil)
})
Convey("应该能使用基本配置", func() {
request := &conversion.ConversionRequest{
Target: "clash",
URL: "https://example.com/subscribe",
Group: "Test Basic",
}
response, err := engine.Convert(request)
So(err, ShouldBeNil)
So(response.Success, ShouldBeTrue)
So(response.NodeCount, ShouldBeGreaterThan, 0)
})
})
}
func TestConversionEngineProtocolDetection(t *testing.T) {
Convey("Basic Protocol Support", t, func() {
// 创建日志记录器
logger, err := logging.NewLogger(&logging.LoggingConfig{
Level: "info",
Format: "text",
Output: "stdout",
})
So(err, ShouldBeNil)
// 创建配置管理器
configMgr, err := config.NewConfigManager("")
So(err, ShouldBeNil)
// 创建解析器管理器
parserMgr := parser.NewParserManager(logger, configMgr)
// 创建生成器管理器
generatorMgr := generator.NewGeneratorManager(logger)
// 创建转换引擎
engine := conversion.NewConversionEngine(logger, parserMgr, generatorMgr)
engine.SetHTTPClient(newMockHTTPClient())
// 测试基本的功能验证
request := &conversion.ConversionRequest{
Target: "clash",
URL: "https://example.com/subscribe",
Group: "Test Protocol",
}
response, err := engine.Convert(request)
So(err, ShouldBeNil)
So(response.Success, ShouldBeTrue)
So(response.NodeCount, ShouldBeGreaterThan, 0)
})
}