106 lines
2.5 KiB
Go
106 lines
2.5 KiB
Go
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")
|
|
}
|
|
}
|