package onvif import ( "context" "encoding/xml" "net/http" "net/http/httptest" "strings" "testing" ) func newMockDeviceSecurityServer() *httptest.Server { return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { decoder := xml.NewDecoder(r.Body) var envelope struct { Body struct { Content []byte `xml:",innerxml"` } `xml:"Body"` } decoder.Decode(&envelope) bodyContent := string(envelope.Body.Content) w.Header().Set("Content-Type", "application/soap+xml") switch { case strings.Contains(bodyContent, "GetRemoteUser"): w.Write([]byte(` remote_admin true `)) case strings.Contains(bodyContent, "SetRemoteUser"): w.Write([]byte(` `)) case strings.Contains(bodyContent, "GetIPAddressFilter"): w.Write([]byte(` Allow 192.168.1.0 24 `)) case strings.Contains(bodyContent, "SetIPAddressFilter"), strings.Contains(bodyContent, "AddIPAddressFilter"), strings.Contains(bodyContent, "RemoveIPAddressFilter"): w.Write([]byte(` `)) case strings.Contains(bodyContent, "GetZeroConfiguration"): w.Write([]byte(` eth0 true 169.254.1.100 `)) case strings.Contains(bodyContent, "SetZeroConfiguration"): w.Write([]byte(` `)) case strings.Contains(bodyContent, "GetPasswordComplexityConfiguration"): w.Write([]byte(` 8 1 1 1 true false `)) case strings.Contains(bodyContent, "SetPasswordComplexityConfiguration"): w.Write([]byte(` `)) case strings.Contains(bodyContent, "GetPasswordHistoryConfiguration"): w.Write([]byte(` true 5 `)) case strings.Contains(bodyContent, "SetPasswordHistoryConfiguration"): w.Write([]byte(` `)) case strings.Contains(bodyContent, "GetAuthFailureWarningConfiguration"): w.Write([]byte(` true 60 5 `)) case strings.Contains(bodyContent, "SetAuthFailureWarningConfiguration"): w.Write([]byte(` `)) default: w.WriteHeader(http.StatusNotFound) } })) } func TestGetRemoteUser(t *testing.T) { server := newMockDeviceSecurityServer() defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } ctx := context.Background() remoteUser, err := client.GetRemoteUser(ctx) if err != nil { t.Fatalf("GetRemoteUser failed: %v", err) } if remoteUser.Username != "remote_admin" { t.Errorf("Expected username 'remote_admin', got %s", remoteUser.Username) } if !remoteUser.UseDerivedPassword { t.Error("UseDerivedPassword should be true") } } func TestSetRemoteUser(t *testing.T) { server := newMockDeviceSecurityServer() defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } ctx := context.Background() remoteUser := &RemoteUser{ Username: "new_remote", Password: "password123", UseDerivedPassword: true, } err = client.SetRemoteUser(ctx, remoteUser) if err != nil { t.Fatalf("SetRemoteUser failed: %v", err) } } func TestGetIPAddressFilter(t *testing.T) { server := newMockDeviceSecurityServer() defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } ctx := context.Background() filter, err := client.GetIPAddressFilter(ctx) if err != nil { t.Fatalf("GetIPAddressFilter failed: %v", err) } if filter.Type != IPAddressFilterAllow { t.Errorf("Expected Allow filter type, got %s", filter.Type) } if len(filter.IPv4Address) != 1 { t.Fatalf("Expected 1 IPv4 address, got %d", len(filter.IPv4Address)) } if filter.IPv4Address[0].Address != "192.168.1.0" { t.Errorf("Expected address 192.168.1.0, got %s", filter.IPv4Address[0].Address) } if filter.IPv4Address[0].PrefixLength != 24 { t.Errorf("Expected prefix length 24, got %d", filter.IPv4Address[0].PrefixLength) } } func TestSetIPAddressFilter(t *testing.T) { server := newMockDeviceSecurityServer() defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } ctx := context.Background() filter := &IPAddressFilter{ Type: IPAddressFilterAllow, IPv4Address: []PrefixedIPv4Address{ {Address: "10.0.0.0", PrefixLength: 8}, }, } err = client.SetIPAddressFilter(ctx, filter) if err != nil { t.Fatalf("SetIPAddressFilter failed: %v", err) } } func TestAddIPAddressFilter(t *testing.T) { server := newMockDeviceSecurityServer() defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } ctx := context.Background() filter := &IPAddressFilter{ Type: IPAddressFilterAllow, IPv4Address: []PrefixedIPv4Address{ {Address: "172.16.0.0", PrefixLength: 12}, }, } err = client.AddIPAddressFilter(ctx, filter) if err != nil { t.Fatalf("AddIPAddressFilter failed: %v", err) } } func TestRemoveIPAddressFilter(t *testing.T) { server := newMockDeviceSecurityServer() defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } ctx := context.Background() filter := &IPAddressFilter{ Type: IPAddressFilterAllow, IPv4Address: []PrefixedIPv4Address{ {Address: "172.16.0.0", PrefixLength: 12}, }, } err = client.RemoveIPAddressFilter(ctx, filter) if err != nil { t.Fatalf("RemoveIPAddressFilter failed: %v", err) } } func TestGetZeroConfiguration(t *testing.T) { server := newMockDeviceSecurityServer() defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } ctx := context.Background() zeroConf, err := client.GetZeroConfiguration(ctx) if err != nil { t.Fatalf("GetZeroConfiguration failed: %v", err) } if zeroConf.InterfaceToken != "eth0" { t.Errorf("Expected interface token 'eth0', got %s", zeroConf.InterfaceToken) } if !zeroConf.Enabled { t.Error("Zero configuration should be enabled") } if len(zeroConf.Addresses) != 1 || zeroConf.Addresses[0] != "169.254.1.100" { t.Errorf("Expected address 169.254.1.100, got %v", zeroConf.Addresses) } } func TestSetZeroConfiguration(t *testing.T) { server := newMockDeviceSecurityServer() defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } ctx := context.Background() err = client.SetZeroConfiguration(ctx, "eth0", true) if err != nil { t.Fatalf("SetZeroConfiguration failed: %v", err) } } func TestGetPasswordComplexityConfiguration(t *testing.T) { server := newMockDeviceSecurityServer() defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } ctx := context.Background() config, err := client.GetPasswordComplexityConfiguration(ctx) if err != nil { t.Fatalf("GetPasswordComplexityConfiguration failed: %v", err) } if config.MinLen != 8 { t.Errorf("Expected MinLen 8, got %d", config.MinLen) } if config.Uppercase != 1 { t.Errorf("Expected Uppercase 1, got %d", config.Uppercase) } if config.Number != 1 { t.Errorf("Expected Number 1, got %d", config.Number) } if config.SpecialChars != 1 { t.Errorf("Expected SpecialChars 1, got %d", config.SpecialChars) } if !config.BlockUsernameOccurrence { t.Error("BlockUsernameOccurrence should be true") } if config.PolicyConfigurationLocked { t.Error("PolicyConfigurationLocked should be false") } } func TestSetPasswordComplexityConfiguration(t *testing.T) { server := newMockDeviceSecurityServer() defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } ctx := context.Background() config := &PasswordComplexityConfiguration{ MinLen: 10, Uppercase: 2, Number: 2, SpecialChars: 1, BlockUsernameOccurrence: true, PolicyConfigurationLocked: false, } err = client.SetPasswordComplexityConfiguration(ctx, config) if err != nil { t.Fatalf("SetPasswordComplexityConfiguration failed: %v", err) } } func TestGetPasswordHistoryConfiguration(t *testing.T) { server := newMockDeviceSecurityServer() defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } ctx := context.Background() config, err := client.GetPasswordHistoryConfiguration(ctx) if err != nil { t.Fatalf("GetPasswordHistoryConfiguration failed: %v", err) } if !config.Enabled { t.Error("Password history should be enabled") } if config.Length != 5 { t.Errorf("Expected Length 5, got %d", config.Length) } } func TestSetPasswordHistoryConfiguration(t *testing.T) { server := newMockDeviceSecurityServer() defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } ctx := context.Background() config := &PasswordHistoryConfiguration{ Enabled: true, Length: 10, } err = client.SetPasswordHistoryConfiguration(ctx, config) if err != nil { t.Fatalf("SetPasswordHistoryConfiguration failed: %v", err) } } func TestGetAuthFailureWarningConfiguration(t *testing.T) { server := newMockDeviceSecurityServer() defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } ctx := context.Background() config, err := client.GetAuthFailureWarningConfiguration(ctx) if err != nil { t.Fatalf("GetAuthFailureWarningConfiguration failed: %v", err) } if !config.Enabled { t.Error("Auth failure warning should be enabled") } if config.MonitorPeriod != 60 { t.Errorf("Expected MonitorPeriod 60, got %d", config.MonitorPeriod) } if config.MaxAuthFailures != 5 { t.Errorf("Expected MaxAuthFailures 5, got %d", config.MaxAuthFailures) } } func TestSetAuthFailureWarningConfiguration(t *testing.T) { server := newMockDeviceSecurityServer() defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } ctx := context.Background() config := &AuthFailureWarningConfiguration{ Enabled: true, MonitorPeriod: 120, MaxAuthFailures: 3, } err = client.SetAuthFailureWarningConfiguration(ctx, config) if err != nil { t.Fatalf("SetAuthFailureWarningConfiguration failed: %v", err) } } func TestIPAddressFilterTypeConstants(t *testing.T) { if IPAddressFilterAllow != "Allow" { t.Errorf("IPAddressFilterAllow should be 'Allow', got %s", IPAddressFilterAllow) } if IPAddressFilterDeny != "Deny" { t.Errorf("IPAddressFilterDeny should be 'Deny', got %s", IPAddressFilterDeny) } }