mirror of
https://github.com/lukaszraczylo/kportal.git
synced 2026-07-09 06:44:16 +00:00
@@ -0,0 +1,286 @@
|
||||
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
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user