Files
onvif-go/device_additional_test.go
T
0x524a 96ac509c24 refactor: update HTTP request handling and improve documentation
- Replaced http.NewRequest with http.NewRequestWithContext in client tests for better context management.
- Updated method names and comments for clarity, including renaming GetWsdlUrl to GetWsdlURL and StorageUri to StorageURI for consistency.
- Enhanced comments across various files to provide clearer descriptions of functionality and ONVIF specifications.
2025-12-02 08:41:37 -05:00

337 lines
8.7 KiB
Go

package onvif
import (
"context"
"encoding/xml"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func newMockDeviceAdditionalServer() *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, "GetGeoLocation"):
_, _ = w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:tt="http://www.onvif.org/ver10/schema">
<s:Body>
<tds:GetGeoLocationResponse xmlns:tds="http://www.onvif.org/ver10/device/wsdl">
<tds:Location Lon="-122.4194" Lat="37.7749" Elevation="10.5">
<tt:Entity>Building A</tt:Entity>
<tt:Token>location1</tt:Token>
<tt:Fixed>true</tt:Fixed>
</tds:Location>
</tds:GetGeoLocationResponse>
</s:Body>
</s:Envelope>`))
case strings.Contains(bodyContent, "SetGeoLocation"):
_, _ = w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body>
<tds:SetGeoLocationResponse xmlns:tds="http://www.onvif.org/ver10/device/wsdl"/>
</s:Body>
</s:Envelope>`))
case strings.Contains(bodyContent, "DeleteGeoLocation"):
_, _ = w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body>
<tds:DeleteGeoLocationResponse xmlns:tds="http://www.onvif.org/ver10/device/wsdl"/>
</s:Body>
</s:Envelope>`))
case strings.Contains(bodyContent, "GetDPAddresses"):
_, _ = w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body>
<tds:GetDPAddressesResponse xmlns:tds="http://www.onvif.org/ver10/device/wsdl">
<tds:DPAddress>
<tt:Type>IPv4</tt:Type>
<tt:IPv4Address>239.255.255.250</tt:IPv4Address>
</tds:DPAddress>
<tds:DPAddress>
<tt:Type>IPv6</tt:Type>
<tt:IPv6Address>ff02::c</tt:IPv6Address>
</tds:DPAddress>
</tds:GetDPAddressesResponse>
</s:Body>
</s:Envelope>`))
case strings.Contains(bodyContent, "SetDPAddresses"):
_, _ = w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body>
<tds:SetDPAddressesResponse xmlns:tds="http://www.onvif.org/ver10/device/wsdl"/>
</s:Body>
</s:Envelope>`))
case strings.Contains(bodyContent, "GetAccessPolicy"):
_, _ = w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body>
<tds:GetAccessPolicyResponse xmlns:tds="http://www.onvif.org/ver10/device/wsdl">
<tds:PolicyFile>
<tt:Data>cG9saWN5IGRhdGE=</tt:Data>
<tt:ContentType>application/xml</tt:ContentType>
</tds:PolicyFile>
</tds:GetAccessPolicyResponse>
</s:Body>
</s:Envelope>`))
case strings.Contains(bodyContent, "SetAccessPolicy"):
_, _ = w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body>
<tds:SetAccessPolicyResponse xmlns:tds="http://www.onvif.org/ver10/device/wsdl"/>
</s:Body>
</s:Envelope>`))
case strings.Contains(bodyContent, "GetWsdlUrl"):
_, _ = w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body>
<tds:GetWsdlUrlResponse xmlns:tds="http://www.onvif.org/ver10/device/wsdl">
<tds:WsdlUrl>http://192.168.1.100/onvif/device.wsdl</tds:WsdlUrl>
</tds:GetWsdlUrlResponse>
</s:Body>
</s:Envelope>`))
default:
w.WriteHeader(http.StatusNotFound)
}
}))
}
func TestGetGeoLocation(t *testing.T) {
server := newMockDeviceAdditionalServer()
defer server.Close()
client, err := NewClient(server.URL)
if err != nil {
t.Fatalf("Failed to create client: %v", err)
}
ctx := context.Background()
locations, err := client.GetGeoLocation(ctx)
if err != nil {
t.Fatalf("GetGeoLocation failed: %v", err)
}
if len(locations) != 1 {
t.Fatalf("Expected 1 location, got %d", len(locations))
}
loc := locations[0]
if loc.Entity != "Building A" {
t.Errorf("Expected entity 'Building A', got %s", loc.Entity)
}
if loc.Token != "location1" {
t.Errorf("Expected token 'location1', got %s", loc.Token)
}
if !loc.Fixed {
t.Error("Expected Fixed to be true")
}
// Check coordinates (approximate comparison due to float precision)
if loc.Lon < -122.42 || loc.Lon > -122.41 {
t.Errorf("Expected longitude around -122.4194, got %f", loc.Lon)
}
if loc.Lat < 37.77 || loc.Lat > 37.78 {
t.Errorf("Expected latitude around 37.7749, got %f", loc.Lat)
}
if loc.Elevation < 10.0 || loc.Elevation > 11.0 {
t.Errorf("Expected elevation around 10.5, got %f", loc.Elevation)
}
}
func TestSetGeoLocation(t *testing.T) {
server := newMockDeviceAdditionalServer()
defer server.Close()
client, err := NewClient(server.URL)
if err != nil {
t.Fatalf("Failed to create client: %v", err)
}
ctx := context.Background()
locations := []LocationEntity{
{
Entity: "Main Office",
Token: "loc1",
Fixed: true,
Lon: -122.4194,
Lat: 37.7749,
Elevation: 15.0,
},
}
err = client.SetGeoLocation(ctx, locations)
if err != nil {
t.Fatalf("SetGeoLocation failed: %v", err)
}
}
func TestDeleteGeoLocation(t *testing.T) {
server := newMockDeviceAdditionalServer()
defer server.Close()
client, err := NewClient(server.URL)
if err != nil {
t.Fatalf("Failed to create client: %v", err)
}
ctx := context.Background()
locations := []LocationEntity{
{Token: "location1"},
}
err = client.DeleteGeoLocation(ctx, locations)
if err != nil {
t.Fatalf("DeleteGeoLocation failed: %v", err)
}
}
func TestGetDPAddresses(t *testing.T) {
server := newMockDeviceAdditionalServer()
defer server.Close()
client, err := NewClient(server.URL)
if err != nil {
t.Fatalf("Failed to create client: %v", err)
}
ctx := context.Background()
addresses, err := client.GetDPAddresses(ctx)
if err != nil {
t.Fatalf("GetDPAddresses failed: %v", err)
}
if len(addresses) != 2 {
t.Fatalf("Expected 2 addresses, got %d", len(addresses))
}
// Check IPv4 address
if addresses[0].Type != "IPv4" {
t.Errorf("Expected Type 'IPv4', got %s", addresses[0].Type)
}
if addresses[0].IPv4Address != "239.255.255.250" {
t.Errorf("Expected IPv4 address '239.255.255.250', got %s", addresses[0].IPv4Address)
}
// Check IPv6 address
if addresses[1].Type != "IPv6" {
t.Errorf("Expected Type 'IPv6', got %s", addresses[1].Type)
}
if addresses[1].IPv6Address != "ff02::c" {
t.Errorf("Expected IPv6 address 'ff02::c', got %s", addresses[1].IPv6Address)
}
}
func TestSetDPAddresses(t *testing.T) {
server := newMockDeviceAdditionalServer()
defer server.Close()
client, err := NewClient(server.URL)
if err != nil {
t.Fatalf("Failed to create client: %v", err)
}
ctx := context.Background()
addresses := []NetworkHost{
{
Type: "IPv4",
IPv4Address: "239.255.255.250",
},
}
err = client.SetDPAddresses(ctx, addresses)
if err != nil {
t.Fatalf("SetDPAddresses failed: %v", err)
}
}
func TestGetAccessPolicy(t *testing.T) {
server := newMockDeviceAdditionalServer()
defer server.Close()
client, err := NewClient(server.URL)
if err != nil {
t.Fatalf("Failed to create client: %v", err)
}
ctx := context.Background()
policy, err := client.GetAccessPolicy(ctx)
if err != nil {
t.Fatalf("GetAccessPolicy failed: %v", err)
}
if policy == nil || policy.PolicyFile == nil {
t.Fatal("Expected policy file, got nil")
}
if policy.PolicyFile.ContentType != "application/xml" {
t.Errorf("Expected content type 'application/xml', got %s", policy.PolicyFile.ContentType)
}
}
func TestSetAccessPolicy(t *testing.T) {
server := newMockDeviceAdditionalServer()
defer server.Close()
client, err := NewClient(server.URL)
if err != nil {
t.Fatalf("Failed to create client: %v", err)
}
ctx := context.Background()
policy := &AccessPolicy{
PolicyFile: &BinaryData{
Data: []byte("policy data"),
ContentType: "application/xml",
},
}
err = client.SetAccessPolicy(ctx, policy)
if err != nil {
t.Fatalf("SetAccessPolicy failed: %v", err)
}
}
func TestGetWsdlUrl(t *testing.T) {
server := newMockDeviceAdditionalServer()
defer server.Close()
client, err := NewClient(server.URL)
if err != nil {
t.Fatalf("Failed to create client: %v", err)
}
ctx := context.Background()
url, err := client.GetWsdlURL(ctx)
if err != nil {
t.Fatalf("GetWsdlURL failed: %v", err)
}
expected := "http://192.168.1.100/onvif/device.wsdl"
if url != expected {
t.Errorf("Expected URL %s, got %s", expected, url)
}
}