remove tests
This commit is contained in:
@@ -1,416 +0,0 @@
|
||||
package bus
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestPidManagerBasics(t *testing.T) {
|
||||
// Create a temporary directory for testing
|
||||
tempDir := t.TempDir()
|
||||
|
||||
// Create a custom pidManager for testing
|
||||
testPidManager := &pidManager{
|
||||
path: filepath.Join(tempDir, PidName),
|
||||
}
|
||||
|
||||
t.Run("create and remove PID file", func(t *testing.T) {
|
||||
// Create PID file
|
||||
err := testPidManager.create()
|
||||
if err != nil {
|
||||
t.Fatalf("create failed: %v", err)
|
||||
}
|
||||
|
||||
// Check file exists and contains current PID
|
||||
pidData, err := os.ReadFile(testPidManager.path)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read PID file: %v", err)
|
||||
}
|
||||
|
||||
expectedPid := strconv.Itoa(os.Getpid())
|
||||
if string(pidData) != expectedPid {
|
||||
t.Errorf("PID file contains %q, expected %q", string(pidData), expectedPid)
|
||||
}
|
||||
|
||||
// Remove PID file
|
||||
err = testPidManager.remove()
|
||||
if err != nil {
|
||||
t.Fatalf("remove failed: %v", err)
|
||||
}
|
||||
|
||||
// Check file no longer exists
|
||||
if _, err := os.Stat(testPidManager.path); !os.IsNotExist(err) {
|
||||
t.Error("PID file should not exist after removal")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("checkExisting with no PID file", func(t *testing.T) {
|
||||
err := testPidManager.checkExisting()
|
||||
if err != nil {
|
||||
t.Errorf("checkExisting should not error when no PID file exists: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("checkExisting with current process", func(t *testing.T) {
|
||||
// Create PID file with current process
|
||||
err := testPidManager.create()
|
||||
if err != nil {
|
||||
t.Fatalf("create failed: %v", err)
|
||||
}
|
||||
defer testPidManager.remove()
|
||||
|
||||
// Check should fail because process is running
|
||||
err = testPidManager.checkExisting()
|
||||
if err == nil {
|
||||
t.Error("checkExisting should fail when process is running")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("checkExisting with stale PID file", func(t *testing.T) {
|
||||
// Create PID file with non-existent PID
|
||||
stalePid := "99999"
|
||||
err := os.WriteFile(testPidManager.path, []byte(stalePid), 0o600)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to write stale PID file: %v", err)
|
||||
}
|
||||
|
||||
// Check should succeed and remove stale file
|
||||
err = testPidManager.checkExisting()
|
||||
if err != nil {
|
||||
t.Errorf("checkExisting should succeed with stale PID: %v", err)
|
||||
}
|
||||
|
||||
// File should be removed
|
||||
if _, err := os.Stat(testPidManager.path); !os.IsNotExist(err) {
|
||||
t.Error("stale PID file should be removed")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("checkExisting with invalid PID file", func(t *testing.T) {
|
||||
// Create PID file with invalid content
|
||||
err := os.WriteFile(testPidManager.path, []byte("invalid"), 0o600)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to write invalid PID file: %v", err)
|
||||
}
|
||||
|
||||
// Check should succeed and remove invalid file
|
||||
err = testPidManager.checkExisting()
|
||||
if err != nil {
|
||||
t.Errorf("checkExisting should succeed with invalid PID: %v", err)
|
||||
}
|
||||
|
||||
// File should be removed
|
||||
if _, err := os.Stat(testPidManager.path); !os.IsNotExist(err) {
|
||||
t.Error("invalid PID file should be removed")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestIsProcessAlive(t *testing.T) {
|
||||
pm := &pidManager{}
|
||||
|
||||
t.Run("current process", func(t *testing.T) {
|
||||
if !pm.isProcessAlive(os.Getpid()) {
|
||||
t.Error("current process should be alive")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("non-existent process", func(t *testing.T) {
|
||||
// Use a PID that's very unlikely to exist
|
||||
if pm.isProcessAlive(99999) {
|
||||
t.Error("non-existent process should not be alive")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("init process", func(t *testing.T) {
|
||||
// PID 1 should always exist on Unix systems, but we might not have permission to signal it
|
||||
alive := pm.isProcessAlive(1)
|
||||
// Don't fail the test if we can't signal PID 1 due to permissions
|
||||
// This is expected behavior in containers or restricted environments
|
||||
_ = alive
|
||||
})
|
||||
}
|
||||
|
||||
func TestSocketManagerBasics(t *testing.T) {
|
||||
// Create a temporary directory for testing
|
||||
tempDir := t.TempDir()
|
||||
|
||||
// Create a custom socketManager for testing
|
||||
testSocketManager := &socketManager{
|
||||
path: filepath.Join(tempDir, SockName),
|
||||
}
|
||||
|
||||
t.Run("listen and dial", func(t *testing.T) {
|
||||
// Start listening
|
||||
listener, err := testSocketManager.listen()
|
||||
if err != nil {
|
||||
t.Fatalf("listen failed: %v", err)
|
||||
}
|
||||
defer listener.Close()
|
||||
|
||||
// Accept connections in background
|
||||
connCh := make(chan error, 1)
|
||||
go func() {
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
connCh <- err
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// Echo back what we receive
|
||||
buf := make([]byte, 1024)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
connCh <- err
|
||||
return
|
||||
}
|
||||
|
||||
_, err = conn.Write(buf[:n])
|
||||
connCh <- err
|
||||
}()
|
||||
|
||||
// Give listener time to start
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
// Dial and send message
|
||||
conn, err := testSocketManager.dial()
|
||||
if err != nil {
|
||||
t.Fatalf("dial failed: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
testMsg := "hello"
|
||||
_, err = conn.Write([]byte(testMsg))
|
||||
if err != nil {
|
||||
t.Fatalf("write failed: %v", err)
|
||||
}
|
||||
|
||||
// Read echo
|
||||
buf := make([]byte, 1024)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("read failed: %v", err)
|
||||
}
|
||||
|
||||
if string(buf[:n]) != testMsg {
|
||||
t.Errorf("got %q, expected %q", string(buf[:n]), testMsg)
|
||||
}
|
||||
|
||||
// Check background goroutine
|
||||
if err := <-connCh; err != nil {
|
||||
t.Errorf("background connection error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("dial without listener", func(t *testing.T) {
|
||||
_, err := testSocketManager.dial()
|
||||
if err == nil {
|
||||
t.Error("dial should fail when no listener exists")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestSendCommandIntegration(t *testing.T) {
|
||||
// Create a temporary directory for testing
|
||||
tempDir := t.TempDir()
|
||||
|
||||
// Create a custom socketManager for testing
|
||||
testSocketManager := &socketManager{
|
||||
path: filepath.Join(tempDir, SockName),
|
||||
}
|
||||
|
||||
t.Run("successful command with mock server", func(t *testing.T) {
|
||||
// Start a mock server
|
||||
listener, err := testSocketManager.listen()
|
||||
if err != nil {
|
||||
t.Fatalf("listen failed: %v", err)
|
||||
}
|
||||
defer listener.Close()
|
||||
|
||||
// Handle connections in background
|
||||
go func() {
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
go func(c net.Conn) {
|
||||
defer c.Close()
|
||||
|
||||
buf := make([]byte, 2)
|
||||
n, err := c.Read(buf)
|
||||
if err != nil || n != 2 {
|
||||
return
|
||||
}
|
||||
|
||||
cmd := buf[0]
|
||||
switch cmd {
|
||||
case 't':
|
||||
fmt.Fprint(c, "OK toggled\n")
|
||||
case 's':
|
||||
fmt.Fprint(c, "STATUS status=idle\n")
|
||||
case 'v':
|
||||
fmt.Fprintf(c, "STATUS proto=%s\n", ProtoVer)
|
||||
case 'q':
|
||||
fmt.Fprint(c, "OK quitting\n")
|
||||
default:
|
||||
fmt.Fprintf(c, "ERR unknown=%q\n", cmd)
|
||||
}
|
||||
}(conn)
|
||||
}
|
||||
}()
|
||||
|
||||
// Give server time to start
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
// Test different commands by manually creating connections
|
||||
tests := []struct {
|
||||
cmd byte
|
||||
expected string
|
||||
}{
|
||||
{'t', "OK toggled\n"},
|
||||
{'s', "STATUS status=idle\n"},
|
||||
{'v', fmt.Sprintf("STATUS proto=%s\n", ProtoVer)},
|
||||
{'q', "OK quitting\n"},
|
||||
{'x', "ERR unknown='x'\n"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
conn, err := testSocketManager.dial()
|
||||
if err != nil {
|
||||
t.Errorf("dial failed for command %c: %v", tt.cmd, err)
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = conn.Write([]byte{tt.cmd, '\n'})
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
t.Errorf("write failed for command %c: %v", tt.cmd, err)
|
||||
continue
|
||||
}
|
||||
|
||||
buf := make([]byte, 1024)
|
||||
n, err := conn.Read(buf)
|
||||
conn.Close()
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("read failed for command %c: %v", tt.cmd, err)
|
||||
continue
|
||||
}
|
||||
|
||||
resp := string(buf[:n])
|
||||
if resp != tt.expected {
|
||||
t.Errorf("command %c: got %q, expected %q", tt.cmd, resp, tt.expected)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestPathFunctions(t *testing.T) {
|
||||
t.Run("SockPath", func(t *testing.T) {
|
||||
path, err := SockPath()
|
||||
if err != nil {
|
||||
t.Fatalf("SockPath failed: %v", err)
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(path) {
|
||||
t.Error("SockPath should return absolute path")
|
||||
}
|
||||
|
||||
if filepath.Base(path) != SockName {
|
||||
t.Errorf("SockPath should end with %s, got %s", SockName, filepath.Base(path))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("getSockPath", func(t *testing.T) {
|
||||
path, err := getSockPath()
|
||||
if err != nil {
|
||||
t.Fatalf("getSockPath failed: %v", err)
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(path) {
|
||||
t.Error("getSockPath should return absolute path")
|
||||
}
|
||||
|
||||
if filepath.Base(path) != SockName {
|
||||
t.Errorf("getSockPath should end with %s, got %s", SockName, filepath.Base(path))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("getPidPath", func(t *testing.T) {
|
||||
path, err := getPidPath()
|
||||
if err != nil {
|
||||
t.Fatalf("getPidPath failed: %v", err)
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(path) {
|
||||
t.Error("getPidPath should return absolute path")
|
||||
}
|
||||
|
||||
if filepath.Base(path) != PidName {
|
||||
t.Errorf("getPidPath should end with %s, got %s", PidName, filepath.Base(path))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestConstants(t *testing.T) {
|
||||
if SockName == "" {
|
||||
t.Error("SockName should not be empty")
|
||||
}
|
||||
if PidName == "" {
|
||||
t.Error("PidName should not be empty")
|
||||
}
|
||||
if ProtoVer == "" {
|
||||
t.Error("ProtoVer should not be empty")
|
||||
}
|
||||
}
|
||||
|
||||
// Test the public API functions with temporary directories
|
||||
func TestPublicAPIWithTempDirs(t *testing.T) {
|
||||
// We can't override the internal functions, but we can test the public API
|
||||
// and clean up any files we create
|
||||
|
||||
t.Run("CheckExistingDaemon with no daemon", func(t *testing.T) {
|
||||
// This should succeed when no daemon is running
|
||||
// Clean up any existing PID file first
|
||||
pidPath, _ := getPidPath()
|
||||
os.Remove(pidPath)
|
||||
|
||||
err := CheckExistingDaemon()
|
||||
if err != nil {
|
||||
t.Errorf("CheckExistingDaemon should succeed when no daemon running: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("CreatePidFile and RemovePidFile", func(t *testing.T) {
|
||||
// Clean up first
|
||||
pidPath, _ := getPidPath()
|
||||
os.Remove(pidPath)
|
||||
|
||||
err := CreatePidFile()
|
||||
if err != nil {
|
||||
t.Fatalf("CreatePidFile failed: %v", err)
|
||||
}
|
||||
|
||||
// Check file exists
|
||||
if _, err := os.Stat(pidPath); os.IsNotExist(err) {
|
||||
t.Error("PID file should exist after CreatePidFile")
|
||||
}
|
||||
|
||||
err = RemovePidFile()
|
||||
if err != nil {
|
||||
t.Fatalf("RemovePidFile failed: %v", err)
|
||||
}
|
||||
|
||||
// Check file is removed
|
||||
if _, err := os.Stat(pidPath); !os.IsNotExist(err) {
|
||||
t.Error("PID file should not exist after RemovePidFile")
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user