package onvif import ( "context" "encoding/xml" "net/http" "net/http/httptest" "testing" ) func TestGetDeviceInformation(t *testing.T) { tests := []struct { name string handler http.HandlerFunc wantErr bool }{ { name: "successful device information retrieval", handler: func(w http.ResponseWriter, r *http.Request) { response := ` Test Manufacturer Test Model 1.0.0 12345 HW-001 ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) }, wantErr: false, }, { name: "SOAP fault response", handler: func(w http.ResponseWriter, r *http.Request) { response := ` s:Receiver Internal error ` w.WriteHeader(http.StatusInternalServerError) _, _ = w.Write([]byte(response)) }, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { server := httptest.NewServer(tt.handler) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } deviceInfo, err := client.GetDeviceInformation(context.Background()) if (err != nil) != tt.wantErr { t.Errorf("GetDeviceInformation() error = %v, wantErr %v", err, tt.wantErr) return } if !tt.wantErr && deviceInfo == nil { t.Error("Expected device information, got nil") } if !tt.wantErr && deviceInfo != nil { if deviceInfo.Manufacturer != "Test Manufacturer" { t.Errorf("Expected manufacturer 'Test Manufacturer', got '%s'", deviceInfo.Manufacturer) } } }) } } func TestGetCapabilities(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` http://example.com/onvif/device_service http://example.com/onvif/media_service ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } capabilities, err := client.GetCapabilities(context.Background()) if err != nil { t.Fatalf("GetCapabilities() error = %v", err) } if capabilities == nil { t.Fatal("Expected capabilities, got nil") } if capabilities.Device == nil || capabilities.Device.XAddr == "" { t.Error("Expected Device capabilities with XAddr") } } func TestGetHostname(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` false test-camera ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } hostname, err := client.GetHostname(context.Background()) if err != nil { t.Fatalf("GetHostname() error = %v", err) } if hostname == nil { t.Fatal("Expected hostname information, got nil") } if hostname.Name != "test-camera" { t.Errorf("Expected hostname 'test-camera', got '%s'", hostname.Name) } } func TestSetHostname(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Verify the request body contains the new hostname var envelope struct { Body struct { SetHostname struct { XMLName xml.Name `xml:"SetHostname"` Name string `xml:"Name"` } `xml:"SetHostname"` } `xml:"Body"` } if err := xml.NewDecoder(r.Body).Decode(&envelope); err != nil { t.Errorf("Failed to decode request: %v", err) } if envelope.Body.SetHostname.Name != "new-hostname" { t.Errorf("Expected hostname 'new-hostname', got '%s'", envelope.Body.SetHostname.Name) } response := ` ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } err = client.SetHostname(context.Background(), "new-hostname") if err != nil { t.Fatalf("SetHostname() error = %v", err) } } func TestGetDNS(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` true example.com IPv4 8.8.8.8 ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } dns, err := client.GetDNS(context.Background()) if err != nil { t.Fatalf("GetDNS() error = %v", err) } if dns == nil { t.Fatal("Expected DNS information, got nil") } if !dns.FromDHCP { t.Error("Expected DNS from DHCP") } } func TestGetUsers(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` admin Administrator user User ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } users, err := client.GetUsers(context.Background()) if err != nil { t.Fatalf("GetUsers() error = %v", err) } if len(users) != 2 { t.Errorf("Expected 2 users, got %d", len(users)) } if users[0].Username != "admin" { t.Errorf("Expected first user to be 'admin', got '%s'", users[0].Username) } } func TestCreateUsers(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } users := []*User{ { Username: "newuser", Password: "password123", UserLevel: "User", }, } err = client.CreateUsers(context.Background(), users) if err != nil { t.Fatalf("CreateUsers() error = %v", err) } } func TestDeleteUsers(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } err = client.DeleteUsers(context.Background(), []string{"testuser"}) if err != nil { t.Fatalf("DeleteUsers() error = %v", err) } } func TestGetNetworkInterfaces(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` true eth0 00:11:22:33:44:55 1500 true false 192.168.1.100 24 ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } interfaces, err := client.GetNetworkInterfaces(context.Background()) if err != nil { t.Fatalf("GetNetworkInterfaces() error = %v", err) } if len(interfaces) != 1 { t.Errorf("Expected 1 interface, got %d", len(interfaces)) } if interfaces[0].Info.Name != "eth0" { t.Errorf("Expected interface name 'eth0', got '%s'", interfaces[0].Info.Name) } } func TestGetServices(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` http://www.onvif.org/ver10/device/wsdl http://192.168.1.100/onvif/device_service 2 6 ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } services, err := client.GetServices(context.Background(), true) if err != nil { t.Fatalf("GetServices() error = %v", err) } if len(services) != 1 { t.Errorf("Expected 1 service, got %d", len(services)) } if services[0].Namespace != "http://www.onvif.org/ver10/device/wsdl" { t.Errorf("Expected device namespace, got %s", services[0].Namespace) } } func TestGetServiceCapabilities(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } caps, err := client.GetServiceCapabilities(context.Background()) if err != nil { t.Fatalf("GetServiceCapabilities() error = %v", err) } if caps.Network == nil || !caps.Network.IPFilter { t.Error("Expected Network.IPFilter to be true") } } func TestGetDiscoveryMode(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` Discoverable ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } mode, err := client.GetDiscoveryMode(context.Background()) if err != nil { t.Fatalf("GetDiscoveryMode() error = %v", err) } if mode != DiscoveryModeDiscoverable { t.Errorf("Expected Discoverable mode, got %s", mode) } } func TestSetDiscoveryMode(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } err = client.SetDiscoveryMode(context.Background(), DiscoveryModeDiscoverable) if err != nil { t.Fatalf("SetDiscoveryMode() error = %v", err) } } func TestGetEndpointReference(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` urn:uuid:12345678-1234-1234-1234-123456789abc ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } guid, err := client.GetEndpointReference(context.Background()) if err != nil { t.Fatalf("GetEndpointReference() error = %v", err) } expected := "urn:uuid:12345678-1234-1234-1234-123456789abc" if guid != expected { t.Errorf("Expected GUID %s, got %s", expected, guid) } } func TestGetNetworkProtocols(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` HTTP true 80 RTSP true 554 ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } protocols, err := client.GetNetworkProtocols(context.Background()) if err != nil { t.Fatalf("GetNetworkProtocols() error = %v", err) } if len(protocols) != 2 { t.Fatalf("Expected 2 protocols, got %d", len(protocols)) } if protocols[0].Name != NetworkProtocolHTTP { t.Errorf("Expected HTTP protocol, got %s", protocols[0].Name) } } func TestSetNetworkProtocols(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } protocols := []*NetworkProtocol{ {Name: NetworkProtocolHTTP, Enabled: true, Port: []int{8080}}, } err = client.SetNetworkProtocols(context.Background(), protocols) if err != nil { t.Fatalf("SetNetworkProtocols() error = %v", err) } } func TestGetNetworkDefaultGateway(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` 192.168.1.1 ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } gateway, err := client.GetNetworkDefaultGateway(context.Background()) if err != nil { t.Fatalf("GetNetworkDefaultGateway() error = %v", err) } if len(gateway.IPv4Address) != 1 || gateway.IPv4Address[0] != "192.168.1.1" { t.Errorf("Expected gateway 192.168.1.1, got %v", gateway.IPv4Address) } } func TestSetNetworkDefaultGateway(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, err := NewClient(server.URL) if err != nil { t.Fatalf("Failed to create client: %v", err) } gateway := &NetworkGateway{ IPv4Address: []string{"192.168.1.1"}, } err = client.SetNetworkDefaultGateway(context.Background(), gateway) if err != nil { t.Fatalf("SetNetworkDefaultGateway() error = %v", err) } } func BenchmarkDeviceGetDeviceInformation(b *testing.B) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := ` Test Model 1.0 123 HW1 ` w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(response)) })) defer server.Close() client, _ := NewClient(server.URL) ctx := context.Background() b.ResetTimer() for i := 0; i < b.N; i++ { _, _ = client.GetDeviceInformation(ctx) } }