Files
kportal/internal/forward/worker_unit_test.go
T
lukaszraczylo f41c316b2b Add configuration wizard. (#2)
* Add configuration wizard.
2025-11-24 02:28:08 +00:00

287 lines
6.7 KiB
Go

package forward
import (
"testing"
"github.com/nvm/kportal/internal/config"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestLogWriter_Write(t *testing.T) {
tests := []struct {
name string
prefix string
input string
expectedInLog string
description string
}{
{
name: "write simple message",
prefix: "[worker] ",
input: "test message",
expectedInLog: "[worker] test message",
description: "Should write message with prefix to log",
},
{
name: "write empty message",
prefix: "[test] ",
input: "",
expectedInLog: "[test] ",
description: "Should handle empty message",
},
{
name: "write multiline message",
prefix: "[fwd] ",
input: "line1\nline2",
expectedInLog: "[fwd] line1\nline2",
description: "Should handle multiline messages",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Test logWriter
originalWriter := &logWriter{prefix: tt.prefix}
n, err := originalWriter.Write([]byte(tt.input))
require.NoError(t, err, "Write should not return error")
assert.Equal(t, len(tt.input), n, "Write should return number of bytes written")
})
}
}
func TestForwardWorker_GetForward(t *testing.T) {
tests := []struct {
name string
forward config.Forward
description string
}{
{
name: "get pod forward",
forward: config.Forward{
Resource: "pod/my-app",
LocalPort: 8080,
Port: 80,
Protocol: "tcp",
},
description: "Should return the forward configuration",
},
{
name: "get service forward",
forward: config.Forward{
Resource: "service/postgres",
LocalPort: 5432,
Port: 5432,
Protocol: "tcp",
},
description: "Should return service forward configuration",
},
{
name: "get forward with selector",
forward: config.Forward{
Resource: "pod",
Selector: "app=nginx,env=prod",
LocalPort: 8080,
Port: 80,
Protocol: "tcp",
},
description: "Should return forward with label selector",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Note: We can't easily test the full worker lifecycle without mocks,
// but we can test the constructor and simple getters
// This test would require proper mocking setup
// For now, we'll test the Forward struct directly
id := tt.forward.ID()
assert.NotEmpty(t, id, "Forward should have an ID")
forwardStr := tt.forward.String()
assert.NotEmpty(t, forwardStr, "Forward should have a string representation")
assert.Contains(t, forwardStr, tt.forward.Resource, "String should contain resource")
})
}
}
func TestForwardWorker_IsRunning(t *testing.T) {
// This is a basic test of the goroutine state tracking
// Full integration tests would require mock dependencies
t.Run("worker state tracking", func(t *testing.T) {
// Test the concept of the done channel
doneChan := make(chan struct{})
// Initially, channel is open (worker would be running)
select {
case <-doneChan:
t.Fatal("doneChan should be open initially")
default:
// Expected: channel is open
}
// Close the channel (simulating worker done)
close(doneChan)
// Now channel should be closed
select {
case <-doneChan:
// Expected: channel is closed
default:
t.Fatal("doneChan should be closed after close")
}
})
}
func TestForwardID(t *testing.T) {
tests := []struct {
name string
forward config.Forward
expectUnique bool
description string
}{
{
name: "unique IDs for different forwards",
forward: config.Forward{
Resource: "pod/app1",
LocalPort: 8080,
Port: 80,
},
expectUnique: true,
description: "Different forwards should have different IDs",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
id1 := tt.forward.ID()
// Create a different forward
fwd2 := config.Forward{
Resource: "pod/app2",
LocalPort: 8081,
Port: 80,
}
id2 := fwd2.ID()
if tt.expectUnique {
assert.NotEqual(t, id1, id2, "Different forwards should have different IDs")
}
// Same forward should produce same ID
id3 := tt.forward.ID()
assert.Equal(t, id1, id3, "Same forward should produce same ID")
})
}
}
func TestForwardString(t *testing.T) {
tests := []struct {
name string
forward config.Forward
expectedContains []string
description string
}{
{
name: "pod forward string",
forward: config.Forward{
Resource: "pod/my-app",
LocalPort: 8080,
Port: 80,
},
expectedContains: []string{"pod/my-app", "8080", "80"},
description: "Should contain resource and ports",
},
{
name: "service forward string",
forward: config.Forward{
Resource: "service/postgres",
LocalPort: 5432,
Port: 5432,
},
expectedContains: []string{"service/postgres", "5432"},
description: "Should contain service and port",
},
{
name: "selector forward string",
forward: config.Forward{
Resource: "pod",
Selector: "app=nginx",
LocalPort: 8080,
Port: 80,
},
expectedContains: []string{"app=nginx", "8080", "80"},
description: "Should contain selector and ports",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := tt.forward.String()
assert.NotEmpty(t, result, "String representation should not be empty")
for _, expected := range tt.expectedContains {
assert.Contains(t, result, expected,
"String should contain %s", expected)
}
})
}
}
func TestSleepWithBackoffConcept(t *testing.T) {
// Test the backoff concept without actually running a worker
t.Run("backoff delay increases", func(t *testing.T) {
// This tests the retry backoff behavior conceptually
delays := []int{1, 2, 4, 8, 10, 10, 10}
for i, expected := range delays {
// Simulate backoff calculation
delay := 1
for j := 0; j < i; j++ {
delay *= 2
if delay > 10 {
delay = 10
}
}
assert.Equal(t, expected, delay,
"Backoff at attempt %d should be %d", i, expected)
}
})
}
func TestWorkerVerboseMode(t *testing.T) {
tests := []struct {
name string
verbose bool
description string
}{
{
name: "verbose mode enabled",
verbose: true,
description: "Worker should respect verbose flag",
},
{
name: "verbose mode disabled",
verbose: false,
description: "Worker should respect non-verbose flag",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Test that verbose flag is a boolean
assert.IsType(t, bool(true), tt.verbose)
// In a real worker, this would control logging
// For now, we just verify the type
})
}
}