|
|
package integration
|
|
|
|
|
|
import (
|
|
|
"fmt"
|
|
|
"net"
|
|
|
"testing"
|
|
|
"time"
|
|
|
|
|
|
"github.com/noahlann/nnet/pkg/nnet"
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
"github.com/stretchr/testify/require"
|
|
|
)
|
|
|
|
|
|
// TestBasicServerClient 测试基本服务器-客户端通信
|
|
|
func TestBasicServerClient(t *testing.T) {
|
|
|
// 创建服务器配置(使用StartTestServer会自动处理随机端口)
|
|
|
cfg := &nnet.Config{
|
|
|
Addr: "tcp://:0",
|
|
|
Codec: &nnet.CodecConfig{
|
|
|
DefaultCodec: "json",
|
|
|
EnableProtocolEncode: false, // 明确禁用协议编码
|
|
|
},
|
|
|
Logger: &nnet.LoggerConfig{
|
|
|
Level: "debug", // 使用debug级别查看详细日志
|
|
|
Format: "text",
|
|
|
Output: "stdout",
|
|
|
},
|
|
|
}
|
|
|
|
|
|
// 先获取随机端口
|
|
|
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
|
|
require.NoError(t, err)
|
|
|
port := listener.Addr().(*net.TCPAddr).Port
|
|
|
listener.Close()
|
|
|
cfg.Addr = fmt.Sprintf("tcp://127.0.0.1:%d", port)
|
|
|
|
|
|
// 创建服务器(不启动)
|
|
|
server, err := nnet.NewServer(cfg)
|
|
|
require.NoError(t, err, "Failed to create server")
|
|
|
|
|
|
// 在启动前注册路由
|
|
|
server.Router().RegisterString("hello", func(ctx nnet.Context) error {
|
|
|
return ctx.Response().WriteString("Hello, nnet!\n")
|
|
|
})
|
|
|
|
|
|
server.Router().RegisterString("ping", func(ctx nnet.Context) error {
|
|
|
return ctx.Response().WriteString("pong\n")
|
|
|
})
|
|
|
|
|
|
// 启动服务器
|
|
|
ts := &TestServer{
|
|
|
Server: server,
|
|
|
Addr: cfg.Addr,
|
|
|
stopCh: make(chan struct{}),
|
|
|
}
|
|
|
|
|
|
ts.wg.Add(1)
|
|
|
go func() {
|
|
|
defer ts.wg.Done()
|
|
|
if err := server.Start(); err != nil {
|
|
|
t.Logf("Server error: %v", err)
|
|
|
}
|
|
|
}()
|
|
|
|
|
|
// 等待服务器启动
|
|
|
require.Eventually(t, func() bool {
|
|
|
return server.Started()
|
|
|
}, 3*time.Second, 50*time.Millisecond, "Server should start within 3 seconds")
|
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
|
|
defer CleanupTestServer(t, ts)
|
|
|
|
|
|
// 创建客户端
|
|
|
client := NewTestClient(t, ts.Addr, nil)
|
|
|
defer CleanupTestClient(t, client)
|
|
|
|
|
|
// 连接客户端
|
|
|
ConnectTestClient(t, client)
|
|
|
|
|
|
// 等待一下,确保服务器完全启动
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
// 测试 hello 路由
|
|
|
resp := RequestWithTimeout(t, client, []byte("hello"), 3*time.Second)
|
|
|
t.Logf("Response for 'hello': %q", string(resp))
|
|
|
assert.Contains(t, string(resp), "Hello", "Response should contain 'Hello'")
|
|
|
|
|
|
// 测试 ping 路由
|
|
|
resp = RequestWithTimeout(t, client, []byte("ping"), 3*time.Second)
|
|
|
t.Logf("Response for 'ping': %q", string(resp))
|
|
|
assert.Contains(t, string(resp), "pong", "Response should contain 'pong'")
|
|
|
}
|
|
|
|
|
|
// TestEchoRoute 测试 Echo 路由
|
|
|
func TestEchoRoute(t *testing.T) {
|
|
|
cfg := &nnet.Config{
|
|
|
Addr: "tcp://:0",
|
|
|
}
|
|
|
|
|
|
// 获取随机端口
|
|
|
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
|
|
require.NoError(t, err)
|
|
|
port := listener.Addr().(*net.TCPAddr).Port
|
|
|
listener.Close()
|
|
|
cfg.Addr = fmt.Sprintf("tcp://127.0.0.1:%d", port)
|
|
|
|
|
|
// 创建服务器并在启动前注册路由
|
|
|
server, err := nnet.NewServer(cfg)
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
server.Router().RegisterString("echo*", func(ctx nnet.Context) error {
|
|
|
request := string(ctx.Request().Raw())
|
|
|
return ctx.Response().WriteString("Echo: " + request + "\n")
|
|
|
})
|
|
|
|
|
|
// 启动服务器
|
|
|
ts := &TestServer{
|
|
|
Server: server,
|
|
|
Addr: cfg.Addr,
|
|
|
stopCh: make(chan struct{}),
|
|
|
}
|
|
|
|
|
|
ts.wg.Add(1)
|
|
|
go func() {
|
|
|
defer ts.wg.Done()
|
|
|
if err := server.Start(); err != nil {
|
|
|
t.Logf("Server error: %v", err)
|
|
|
}
|
|
|
}()
|
|
|
|
|
|
require.Eventually(t, func() bool {
|
|
|
return server.Started()
|
|
|
}, 3*time.Second, 50*time.Millisecond, "Server should start within 3 seconds")
|
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
|
|
defer CleanupTestServer(t, ts)
|
|
|
|
|
|
client := NewTestClient(t, ts.Addr, nil)
|
|
|
defer CleanupTestClient(t, client)
|
|
|
|
|
|
ConnectTestClient(t, client)
|
|
|
|
|
|
// 等待一下,确保服务器完全启动
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
// 发送 echo 请求
|
|
|
testData := "echo test message"
|
|
|
resp := RequestWithTimeout(t, client, []byte(testData), 3*time.Second)
|
|
|
t.Logf("Response for 'echo': %q", string(resp))
|
|
|
assert.Contains(t, string(resp), "test message", "Response should echo the message")
|
|
|
}
|
|
|
|
|
|
// TestMultipleClients 测试多个客户端连接
|
|
|
func TestMultipleClients(t *testing.T) {
|
|
|
cfg := &nnet.Config{
|
|
|
Addr: "tcp://:0",
|
|
|
}
|
|
|
|
|
|
// 获取随机端口
|
|
|
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
|
|
require.NoError(t, err)
|
|
|
port := listener.Addr().(*net.TCPAddr).Port
|
|
|
listener.Close()
|
|
|
cfg.Addr = fmt.Sprintf("tcp://127.0.0.1:%d", port)
|
|
|
|
|
|
// 创建服务器并在启动前注册路由
|
|
|
server, err := nnet.NewServer(cfg)
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
server.Router().RegisterString("test", func(ctx nnet.Context) error {
|
|
|
return ctx.Response().WriteString("OK\n")
|
|
|
})
|
|
|
|
|
|
// 启动服务器
|
|
|
ts := &TestServer{
|
|
|
Server: server,
|
|
|
Addr: cfg.Addr,
|
|
|
stopCh: make(chan struct{}),
|
|
|
}
|
|
|
|
|
|
ts.wg.Add(1)
|
|
|
go func() {
|
|
|
defer ts.wg.Done()
|
|
|
if err := server.Start(); err != nil {
|
|
|
t.Logf("Server error: %v", err)
|
|
|
}
|
|
|
}()
|
|
|
|
|
|
require.Eventually(t, func() bool {
|
|
|
return server.Started()
|
|
|
}, 3*time.Second, 50*time.Millisecond, "Server should start within 3 seconds")
|
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
|
|
defer CleanupTestServer(t, ts)
|
|
|
|
|
|
// 创建多个客户端
|
|
|
clients := make([]nnet.Client, 3)
|
|
|
for i := 0; i < 3; i++ {
|
|
|
client := NewTestClient(t, ts.Addr, nil)
|
|
|
ConnectTestClient(t, client)
|
|
|
clients[i] = client
|
|
|
}
|
|
|
|
|
|
// 等待一下,确保服务器完全启动
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
// 所有客户端都应该能够发送请求
|
|
|
for i, client := range clients {
|
|
|
resp := RequestWithTimeout(t, client, []byte("test"), 3*time.Second)
|
|
|
t.Logf("Response for client %d: %q", i, string(resp))
|
|
|
assert.Contains(t, string(resp), "OK", "Response should contain 'OK'")
|
|
|
}
|
|
|
|
|
|
// 清理所有客户端
|
|
|
for _, client := range clients {
|
|
|
CleanupTestClient(t, client)
|
|
|
}
|
|
|
}
|
|
|
|