first commit
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
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
This commit is contained in:
258
tests/conversion/engine_test.go
Normal file
258
tests/conversion/engine_test.go
Normal file
@@ -0,0 +1,258 @@
|
||||
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)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user