215 lines
5.8 KiB
Go
215 lines
5.8 KiB
Go
package testutil
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"snitch/internal/collector"
|
|
)
|
|
|
|
// TestCollector wraps MockCollector for use in tests
|
|
type TestCollector struct {
|
|
*collector.MockCollector
|
|
}
|
|
|
|
// NewTestCollector creates a new test collector with default data
|
|
func NewTestCollector() *TestCollector {
|
|
return &TestCollector{
|
|
MockCollector: collector.NewMockCollector(),
|
|
}
|
|
}
|
|
|
|
// NewTestCollectorWithFixture creates a test collector with a specific fixture
|
|
func NewTestCollectorWithFixture(fixtureName string) *TestCollector {
|
|
fixtures := collector.GetTestFixtures()
|
|
for _, fixture := range fixtures {
|
|
if fixture.Name == fixtureName {
|
|
mock := collector.NewMockCollector()
|
|
mock.SetConnections(fixture.Connections)
|
|
return &TestCollector{MockCollector: mock}
|
|
}
|
|
}
|
|
|
|
// Fallback to default if fixture not found
|
|
return NewTestCollector()
|
|
}
|
|
|
|
// SetupTestEnvironment sets up a clean test environment
|
|
func SetupTestEnvironment(t *testing.T) (string, func()) {
|
|
// Create temporary directory for test files
|
|
tempDir, err := os.MkdirTemp("", "snitch-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
|
|
// Set test environment variables
|
|
oldConfig := os.Getenv("SNITCH_CONFIG")
|
|
oldNoColor := os.Getenv("SNITCH_NO_COLOR")
|
|
|
|
os.Setenv("SNITCH_NO_COLOR", "1") // Disable colors in tests
|
|
|
|
// Cleanup function
|
|
cleanup := func() {
|
|
os.RemoveAll(tempDir)
|
|
os.Setenv("SNITCH_CONFIG", oldConfig)
|
|
os.Setenv("SNITCH_NO_COLOR", oldNoColor)
|
|
}
|
|
|
|
return tempDir, cleanup
|
|
}
|
|
|
|
// CreateFixtureFile creates a JSON fixture file with the given connections
|
|
func CreateFixtureFile(t *testing.T, dir string, name string, connections []collector.Connection) string {
|
|
mock := collector.NewMockCollector()
|
|
mock.SetConnections(connections)
|
|
|
|
filePath := filepath.Join(dir, name+".json")
|
|
if err := mock.SaveToFile(filePath); err != nil {
|
|
t.Fatalf("Failed to create fixture file %s: %v", filePath, err)
|
|
}
|
|
|
|
return filePath
|
|
}
|
|
|
|
// LoadFixtureFile loads connections from a JSON fixture file
|
|
func LoadFixtureFile(t *testing.T, filePath string) []collector.Connection {
|
|
mock, err := collector.NewMockCollectorFromFile(filePath)
|
|
if err != nil {
|
|
t.Fatalf("Failed to load fixture file %s: %v", filePath, err)
|
|
}
|
|
|
|
connections, err := mock.GetConnections()
|
|
if err != nil {
|
|
t.Fatalf("Failed to get connections from fixture: %v", err)
|
|
}
|
|
|
|
return connections
|
|
}
|
|
|
|
// AssertConnectionsEqual compares two slices of connections for equality
|
|
func AssertConnectionsEqual(t *testing.T, expected, actual []collector.Connection) {
|
|
if len(expected) != len(actual) {
|
|
t.Errorf("Connection count mismatch: expected %d, got %d", len(expected), len(actual))
|
|
return
|
|
}
|
|
|
|
for i, exp := range expected {
|
|
act := actual[i]
|
|
|
|
// Compare key fields (timestamps may vary slightly)
|
|
if exp.PID != act.PID {
|
|
t.Errorf("Connection %d PID mismatch: expected %d, got %d", i, exp.PID, act.PID)
|
|
}
|
|
if exp.Process != act.Process {
|
|
t.Errorf("Connection %d Process mismatch: expected %s, got %s", i, exp.Process, act.Process)
|
|
}
|
|
if exp.Proto != act.Proto {
|
|
t.Errorf("Connection %d Proto mismatch: expected %s, got %s", i, exp.Proto, act.Proto)
|
|
}
|
|
if exp.State != act.State {
|
|
t.Errorf("Connection %d State mismatch: expected %s, got %s", i, exp.State, act.State)
|
|
}
|
|
if exp.Laddr != act.Laddr {
|
|
t.Errorf("Connection %d Laddr mismatch: expected %s, got %s", i, exp.Laddr, act.Laddr)
|
|
}
|
|
if exp.Lport != act.Lport {
|
|
t.Errorf("Connection %d Lport mismatch: expected %d, got %d", i, exp.Lport, act.Lport)
|
|
}
|
|
}
|
|
}
|
|
|
|
// GetTestConfig returns a test configuration with safe defaults
|
|
func GetTestConfig() map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"defaults": map[string]interface{}{
|
|
"interval": "1s",
|
|
"numeric": true, // Disable resolution in tests
|
|
"fields": []string{"pid", "process", "proto", "state", "laddr", "lport"},
|
|
"theme": "mono", // Use monochrome theme in tests
|
|
"units": "auto",
|
|
"color": "never",
|
|
"resolve": false,
|
|
"ipv4": false,
|
|
"ipv6": false,
|
|
"no_headers": false,
|
|
"output_format": "table",
|
|
"sort_by": "",
|
|
},
|
|
}
|
|
}
|
|
|
|
// CaptureOutput captures stdout/stderr during test execution
|
|
type OutputCapture struct {
|
|
stdout *os.File
|
|
stderr *os.File
|
|
oldStdout *os.File
|
|
oldStderr *os.File
|
|
stdoutFile string
|
|
stderrFile string
|
|
}
|
|
|
|
// NewOutputCapture creates a new output capture
|
|
func NewOutputCapture(t *testing.T) *OutputCapture {
|
|
tempDir, err := os.MkdirTemp("", "snitch-output-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir for output capture: %v", err)
|
|
}
|
|
|
|
stdoutFile := filepath.Join(tempDir, "stdout")
|
|
stderrFile := filepath.Join(tempDir, "stderr")
|
|
|
|
stdout, err := os.Create(stdoutFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create stdout file: %v", err)
|
|
}
|
|
|
|
stderr, err := os.Create(stderrFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create stderr file: %v", err)
|
|
}
|
|
|
|
return &OutputCapture{
|
|
stdout: stdout,
|
|
stderr: stderr,
|
|
oldStdout: os.Stdout,
|
|
oldStderr: os.Stderr,
|
|
stdoutFile: stdoutFile,
|
|
stderrFile: stderrFile,
|
|
}
|
|
}
|
|
|
|
// Start begins capturing output
|
|
func (oc *OutputCapture) Start() {
|
|
os.Stdout = oc.stdout
|
|
os.Stderr = oc.stderr
|
|
}
|
|
|
|
// Stop stops capturing and returns the captured output
|
|
func (oc *OutputCapture) Stop() (string, string, error) {
|
|
// Restore original stdout/stderr
|
|
os.Stdout = oc.oldStdout
|
|
os.Stderr = oc.oldStderr
|
|
|
|
// Close files
|
|
oc.stdout.Close()
|
|
oc.stderr.Close()
|
|
|
|
// Read captured content
|
|
stdoutContent, err := os.ReadFile(oc.stdoutFile)
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
stderrContent, err := os.ReadFile(oc.stderrFile)
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
// Cleanup
|
|
os.Remove(oc.stdoutFile)
|
|
os.Remove(oc.stderrFile)
|
|
os.Remove(filepath.Dir(oc.stdoutFile))
|
|
|
|
return string(stdoutContent), string(stderrContent), nil
|
|
} |