mirror of
https://github.com/aauren/tailscale-bind-ddns.git
synced 2026-10-25 21:29:39 +00:00
238 lines
5.3 KiB
Go
238 lines
5.3 KiB
Go
package tailscale
|
|
|
|
import (
|
|
"net"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestNewClient(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
apiKey string
|
|
tailnet string
|
|
wantErr bool
|
|
wantError string
|
|
}{
|
|
{
|
|
name: "valid client",
|
|
apiKey: "test-api-key",
|
|
tailnet: "test.example.com",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "missing API key",
|
|
apiKey: "",
|
|
tailnet: "test.example.com",
|
|
wantErr: true,
|
|
wantError: "api key is required",
|
|
},
|
|
{
|
|
name: "missing tailnet",
|
|
apiKey: "test-api-key",
|
|
tailnet: "",
|
|
wantErr: true,
|
|
wantError: "tailnet is required",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
client, err := NewClient(tt.apiKey, tt.tailnet)
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
assert.Nil(t, client)
|
|
if tt.wantError != "" {
|
|
assert.Contains(t, err.Error(), tt.wantError)
|
|
}
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, client)
|
|
assert.Equal(t, tt.tailnet, client.tailnet)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewOAuthClient(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
clientID string
|
|
clientSecret string
|
|
tailnet string
|
|
wantErr bool
|
|
wantError string
|
|
}{
|
|
{
|
|
name: "valid OAuth client",
|
|
clientID: "test-client-id",
|
|
clientSecret: "test-client-secret",
|
|
tailnet: "test.example.com",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "missing client ID",
|
|
clientID: "",
|
|
clientSecret: "test-client-secret",
|
|
tailnet: "test.example.com",
|
|
wantErr: true,
|
|
wantError: "client ID is required",
|
|
},
|
|
{
|
|
name: "missing client secret",
|
|
clientID: "test-client-id",
|
|
clientSecret: "",
|
|
tailnet: "test.example.com",
|
|
wantErr: true,
|
|
wantError: "client secret is required",
|
|
},
|
|
{
|
|
name: "missing tailnet",
|
|
clientID: "test-client-id",
|
|
clientSecret: "test-client-secret",
|
|
tailnet: "",
|
|
wantErr: true,
|
|
wantError: "tailnet is required",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
client, err := NewOAuthClient(tt.clientID, tt.clientSecret, tt.tailnet)
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
assert.Nil(t, client)
|
|
if tt.wantError != "" {
|
|
assert.Contains(t, err.Error(), tt.wantError)
|
|
}
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, client)
|
|
assert.Equal(t, tt.tailnet, client.tailnet)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetOnlineMachines(t *testing.T) {
|
|
// This test would require mocking the Tailscale client
|
|
// For now, we'll test the logic that filters online machines
|
|
|
|
client := &Client{
|
|
tailnet: "test.example.com",
|
|
}
|
|
|
|
// Test with empty machine list
|
|
machines := []Machine{}
|
|
onlineMachines := client.filterOnlineMachines(machines)
|
|
assert.Empty(t, onlineMachines)
|
|
|
|
// Test with mixed online/offline machines
|
|
machines = []Machine{
|
|
{
|
|
ID: "machine1",
|
|
Name: "machine1",
|
|
Online: true,
|
|
},
|
|
{
|
|
ID: "machine2",
|
|
Name: "machine2",
|
|
Online: false,
|
|
},
|
|
{
|
|
ID: "machine3",
|
|
Name: "machine3",
|
|
Online: true,
|
|
},
|
|
}
|
|
|
|
onlineMachines = client.filterOnlineMachines(machines)
|
|
assert.Len(t, onlineMachines, 2)
|
|
assert.Equal(t, "machine1", onlineMachines[0].Name)
|
|
assert.Equal(t, "machine3", onlineMachines[1].Name)
|
|
}
|
|
|
|
func TestStartPolling(t *testing.T) {
|
|
// This test verifies the polling mechanism
|
|
// We'll skip the actual polling test since it requires real credentials
|
|
// and would cause a panic with nil client
|
|
t.Skip("Skipping polling test - requires real Tailscale credentials")
|
|
}
|
|
|
|
// Helper method to test machine filtering logic
|
|
func (c *Client) filterOnlineMachines(machines []Machine) []Machine {
|
|
var onlineMachines []Machine
|
|
for _, machine := range machines {
|
|
if machine.Online {
|
|
onlineMachines = append(onlineMachines, machine)
|
|
}
|
|
}
|
|
return onlineMachines
|
|
}
|
|
|
|
func TestMachineConversion(t *testing.T) {
|
|
// Test the conversion from Tailscale device addresses to our Machine format
|
|
|
|
// Test IPv4 address extraction
|
|
testCases := []struct {
|
|
name string
|
|
addresses []string
|
|
expectedIPv4 string
|
|
expectedIPv6 string
|
|
}{
|
|
{
|
|
name: "IPv4 only",
|
|
addresses: []string{"100.64.1.1"},
|
|
expectedIPv4: "100.64.1.1",
|
|
expectedIPv6: "",
|
|
},
|
|
{
|
|
name: "IPv6 only",
|
|
addresses: []string{"fd7a:115c:a1e0::1"},
|
|
expectedIPv4: "",
|
|
expectedIPv6: "fd7a:115c:a1e0::1",
|
|
},
|
|
{
|
|
name: "Both IPv4 and IPv6",
|
|
addresses: []string{"100.64.1.1", "fd7a:115c:a1e0::1"},
|
|
expectedIPv4: "100.64.1.1",
|
|
expectedIPv6: "fd7a:115c:a1e0::1",
|
|
},
|
|
{
|
|
name: "No addresses",
|
|
addresses: []string{},
|
|
expectedIPv4: "",
|
|
expectedIPv6: "",
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
machine := Machine{
|
|
ID: "test-machine",
|
|
Name: "test-machine",
|
|
}
|
|
|
|
// Simulate address extraction logic
|
|
for _, addr := range tc.addresses {
|
|
// Parse IP address to check if it's IPv4 or IPv6
|
|
if net.ParseIP(addr) != nil {
|
|
if net.ParseIP(addr).To4() != nil {
|
|
// IPv4 address
|
|
machine.IPv4Address = addr
|
|
} else {
|
|
// IPv6 address
|
|
machine.IPv6Address = addr
|
|
}
|
|
}
|
|
}
|
|
|
|
assert.Equal(t, tc.expectedIPv4, machine.IPv4Address)
|
|
assert.Equal(t, tc.expectedIPv6, machine.IPv6Address)
|
|
})
|
|
}
|
|
}
|