gocmdDaemon/cmd_daemon_test.go

346 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 gocmdDaemon
import (
"encoding/json"
"fmt"
"net"
"os"
"testing"
"time"
)
func TestWrite(t *testing.T) {
// 创建一个配对的连接
conn1, conn2 := net.Pipe()
defer conn1.Close()
defer conn2.Close()
// 要写入的数据
data := map[string]string{"test": "data"}
// 在一个goroutine中执行写操作
go func() {
err := Write(conn1, data)
if err != nil {
t.Errorf("Write failed: %v", err)
}
}()
// 读取数据并验证
var received map[string]string
err := json.NewDecoder(conn2).Decode(&received)
if err != nil {
t.Fatalf("Read failed: %v", err)
}
for k, v := range data {
if received[k] != v {
t.Errorf("Received data does not match. Expected %v:%v, Got %v:%v", k, v, received[k], received[k])
}
}
}
func TestRead(t *testing.T) {
// 创建一个配对的连接
conn1, conn2 := net.Pipe()
defer conn1.Close()
defer conn2.Close()
// 准备要读取的数据
data := map[string]string{"test": "data"}
// 在一个goroutine中执行写操作
go func() {
encoder := json.NewEncoder(conn1)
err := encoder.Encode(data)
if err != nil {
t.Errorf("Write failed: %v", err)
}
}()
// 读取数据并验证
received, err := Read[map[string]string](conn2)
if err != nil {
t.Fatalf("Read failed: %v", err)
}
for k, v := range data {
if (*received)[k] != v {
t.Errorf("Received data does not match. Expected %v:%v, Got %v:%v", k, v, (*received)[k], (*received)[k])
}
}
}
func TestCmdDaemonListen(t *testing.T) {
socketPath := "/tmp/test.sock"
daemon := &CmdDaemon{
SocketPath: socketPath,
cmds: make(map[string]CmdHandler),
}
// 注册一个简单的命令处理程序
daemon.RegisterCmd("test", &SimpleCmdHandler{})
// 启动守护进程
go func() {
err := daemon.Listen()
if err != nil {
t.Errorf("Listen failed: %v", err)
}
}()
// 等待服务器启动
time.Sleep(1 * time.Second)
// 模拟客户端连接
conn, err := net.Dial("unix", socketPath)
if err != nil {
t.Fatalf("Client connect failed: %v", err)
}
defer conn.Close()
// 发送请求
req := CmdRequest{
Id: "1",
Cmd: "test",
Args: "arg1",
IsDebug: false,
}
err = Write(conn, req)
if err != nil {
t.Errorf("Write failed: %v", err)
}
// 读取响应
resp, err := Read[CmdResponse](conn)
if err != nil {
t.Fatalf("Read failed: %v", err)
}
if resp.Data != "Handled test with args: arg1" || resp.Error != "" {
t.Errorf("Unexpected response. Data: %v, Error: %v", resp.Data, resp.Error)
}
}
func TestCmdDaemonRun(t *testing.T) {
// 这里我们假设有一个正在运行的服务器来处理请求
// 因此我们需要首先启动一个简单的服务器来测试Run方法
socketPath := "/tmp/test_run.sock"
daemon := &CmdDaemon{
SocketPath: socketPath,
cmds: make(map[string]CmdHandler),
}
// 注册一个简单的命令处理程序
daemon.RegisterCmd("test", &SimpleCmdHandler{})
// 创建一个同步通道来等待守护进程开始监听
listening := make(chan struct{})
// 启动守护进程
go startTestDaemon(daemon, listening)
// 等待直到监听开始
// for循环中检查socket文件是否存在,如果存在退出循环否则sleepeep 1秒
// 使用一个错误channel来传递错误
errChan := make(chan error)
go func() {
listened := false
for {
if listened {
break
}
if _, err := os.Stat(socketPath); err == nil {
listened = true
}
time.Sleep(1 * time.Second)
}
// 设置命令行参数
os.Args = []string{"cmd", "--debug", "test", "arg1"}
ndaemon := &CmdDaemon{
SocketPath: socketPath,
}
// 执行Run方法
err := ndaemon.Run()
if err != nil {
errChan <- err
} else {
t.Log("Run completed successfully")
close(errChan)
}
}()
err := <-errChan
if err != nil {
t.Fatal(err)
}
}
// startTestDaemon 启动守护进程并在后台运行
func startTestDaemon(daemon *CmdDaemon, ready chan struct{}) {
err := daemon.Listen()
if err != nil {
panic(fmt.Sprintf("Listen failed: %v", err))
}
}
// SimpleCmdHandler 是一个简单的CmdHandler实现用于测试
type SimpleCmdHandler struct{}
func (h *SimpleCmdHandler) Handle(conn *CmdConn, req *CmdRequest) error {
err := conn.End(fmt.Sprintf("Handled %s with args: %s", req.Cmd, req.Args))
return err
}
func (h *SimpleCmdHandler) Description() string {
return "Simple command handler for testing"
}
func (h *SimpleCmdHandler) Usage() string {
return "Usage: test [args]"
}
// EmptyCmdHandler 是一个简单的CmdHandler实现用于测试空输入
type EmptyCmdHandler struct{}
func (h *EmptyCmdHandler) Handle(conn *CmdConn, req *CmdRequest) error {
// 返回一个空响应
err := conn.End("")
return err
}
func (h *EmptyCmdHandler) Description() string {
return "Simple command handler for testing empty input"
}
func (h *EmptyCmdHandler) Usage() string {
return "Usage: empty"
}
// UnknownCmdHandler 是一个简单的CmdHandler实现用于测试未知命令
// 它会返回一个错误响应
type UnknownCmdHandler struct{}
func (h *UnknownCmdHandler) Handle(conn *CmdConn, req *CmdRequest) error {
// 返回一个错误响应
err := conn.WriteError(fmt.Errorf("unknown command"), false)
return err
}
func (h *UnknownCmdHandler) Description() string {
return "Simple command handler for testing unknown commands"
}
func (h *UnknownCmdHandler) Usage() string {
return "Usage: unknown"
}
func TestEmptyCommand(t *testing.T) {
socketPath := "/tmp/test_empty.sock"
daemon := &CmdDaemon{
SocketPath: socketPath,
cmds: make(map[string]CmdHandler),
}
// 注册一个简单的命令处理程序
daemon.RegisterCmd("empty", &EmptyCmdHandler{})
// 创建一个同步通道来等待守护进程开始监听
listening := make(chan struct{})
// 启动守护进程
go startTestDaemon(daemon, listening)
// 等待直到监听开始
// for循环中检查socket文件是否存在,如果存在退出循环否则sleepeep 1秒
// 使用一个错误channel来传递错误
errChan := make(chan error)
go func() {
listened := false
for {
if listened {
break
}
if _, err := os.Stat(socketPath); err == nil {
listened = true
}
time.Sleep(1 * time.Second)
}
// 设置命令行参数
os.Args = []string{"cmd", "empty"}
ndaemon := &CmdDaemon{
SocketPath: socketPath,
}
// 执行Run方法
err := ndaemon.Run()
if err != nil {
errChan <- err
} else {
t.Log("Run completed successfully")
close(errChan)
}
}()
err := <-errChan
if err != nil {
t.Fatal(err)
}
}
func TestUnknownCommand(t *testing.T) {
socketPath := "/tmp/test_unknown.sock"
daemon := &CmdDaemon{
SocketPath: socketPath,
cmds: make(map[string]CmdHandler),
}
// 注册一个简单的命令处理程序
daemon.RegisterCmd("unknown", &UnknownCmdHandler{})
// 启动守护进程
go func() {
err := daemon.Listen()
if err != nil {
panic(fmt.Sprintf("Listen failed: %v", err))
}
}()
// 等待 socket 文件创建
waitForSocket(t, socketPath)
// 设置命令行参数
os.Args = []string{"cmd", "unknown"}
ndaemon := &CmdDaemon{
SocketPath: socketPath,
}
// 执行Run方法
err := ndaemon.Run()
if err != nil {
t.Fatalf("Run failed: %v", err)
}
}
// waitForSocket 等待直到指定路径的 socket 文件被创建
func waitForSocket(t *testing.T, path string) {
timeout := time.After(5 * time.Second)
ticker := time.Tick(500 * time.Millisecond)
for {
select {
case <-timeout:
t.Fatal("Timed out waiting for socket")
case <-ticker:
if _, err := os.Stat(path); err == nil {
return
}
}
}
}