This commit is contained in:
105
pkg/toughswitch/client_test.go
Normal file
105
pkg/toughswitch/client_test.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package toughswitch
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type mockTransport struct {
|
||||
RoundTripFunc func(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
func (m *mockTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
if m.RoundTripFunc != nil {
|
||||
return m.RoundTripFunc(req)
|
||||
}
|
||||
// Default mock response
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: io.NopCloser(bytes.NewBufferString("{}")),
|
||||
Header: make(http.Header),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TestClient_ThreadSafety(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
client := MustNew(ctx, []Config{})
|
||||
|
||||
var wg sync.WaitGroup
|
||||
start := make(chan struct{})
|
||||
|
||||
// Writer: Adds and deletes hosts
|
||||
wg.Go(func() {
|
||||
<-start
|
||||
for i := range 100 {
|
||||
host := fmt.Sprintf("host-%d", i)
|
||||
cfg := &Config{
|
||||
Host: host,
|
||||
Transport: &mockTransport{},
|
||||
}
|
||||
if err := client.Add(cfg); err != nil {
|
||||
// verify we don't error on valid add
|
||||
t.Logf("Add error: %v", err)
|
||||
}
|
||||
|
||||
// We invoke Del immediately.
|
||||
if err := client.Del(host); err != nil {
|
||||
t.Logf("Del error: %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Reader: Iterates hosts
|
||||
wg.Go(func() {
|
||||
<-start
|
||||
for range 10 {
|
||||
// GetAllInterfaces iterates keys.
|
||||
// With mock transport, this will succeed (returning empty structs)
|
||||
// checking for race conditions.
|
||||
_, _ = client.GetAllInterfaces(ctx)
|
||||
}
|
||||
})
|
||||
|
||||
close(start)
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestClient_AddDel(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
client := MustNew(ctx, []Config{})
|
||||
|
||||
cfg := &Config{
|
||||
Host: "test-host",
|
||||
Transport: &mockTransport{},
|
||||
}
|
||||
if err := client.Add(cfg); err != nil {
|
||||
t.Fatalf("Add failed: %v", err)
|
||||
}
|
||||
|
||||
if err := client.Add(cfg); err == nil {
|
||||
t.Fatal("Expected error adding duplicate host, got nil")
|
||||
}
|
||||
|
||||
// Verify we can retrieve it
|
||||
// Mock transport returns 200 OK with empty body, so GetInterfaces should return empty slice (or error decoding if empty body is not valid JSON array? actually "{}" is valid object, but GetInterfaces expects array for /interfaces?)
|
||||
// Let's check api.go: GetInterfaces calls /interfaces.
|
||||
// We can customize the mock if we want to test success return.
|
||||
// For this test, we just care that it doesn't return "device not found".
|
||||
_, err := client.GetInterfaces(ctx, "test-host")
|
||||
if err != nil && err.Error() == "device not found: test-host" {
|
||||
t.Fatal("Device should exist")
|
||||
}
|
||||
|
||||
if err := client.Del("test-host"); err != nil {
|
||||
t.Fatalf("Del failed: %v", err)
|
||||
}
|
||||
|
||||
if err := client.Del("test-host"); err == nil {
|
||||
t.Fatal("Expected error deleting non-existent host, got nil")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user