Files
at-container-registry/pkg/hold/pds/did_test.go
T

275 lines
7.9 KiB
Go

package pds
import (
"context"
"encoding/json"
"path/filepath"
"testing"
)
// TestGenerateDIDFromURL tests DID generation from various URL formats
func TestGenerateDIDFromURL(t *testing.T) {
tests := []struct {
name string
publicURL string
expectedDID string
}{
{
name: "standard HTTP with standard port",
publicURL: "http://hold.example.com",
expectedDID: "did:web:hold.example.com",
},
{
name: "standard HTTPS with standard port",
publicURL: "https://hold.example.com",
expectedDID: "did:web:hold.example.com",
},
{
name: "HTTP with non-standard port",
publicURL: "http://hold.example.com:8080",
expectedDID: "did:web:hold.example.com:8080",
},
{
name: "HTTPS with non-standard port",
publicURL: "https://hold.example.com:8443",
expectedDID: "did:web:hold.example.com:8443",
},
{
name: "localhost with port",
publicURL: "http://localhost:8080",
expectedDID: "did:web:localhost:8080",
},
{
name: "HTTP with explicit port 80",
publicURL: "http://hold.example.com:80",
expectedDID: "did:web:hold.example.com",
},
{
name: "HTTPS with explicit port 443",
publicURL: "https://hold.example.com:443",
expectedDID: "did:web:hold.example.com",
},
{
name: "subdomain",
publicURL: "https://hold1.atcr.io",
expectedDID: "did:web:hold1.atcr.io",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
did := GenerateDIDFromURL(tt.publicURL)
if did != tt.expectedDID {
t.Errorf("Expected DID %s, got %s", tt.expectedDID, did)
}
})
}
}
// TestGenerateDIDFromURL_InvalidURL tests handling of invalid URLs
func TestGenerateDIDFromURL_InvalidURL(t *testing.T) {
// Invalid URLs get parsed with empty hostname, which defaults to localhost
did := GenerateDIDFromURL("not a url")
if did != "did:web:localhost" {
t.Errorf("Expected did:web:localhost for invalid URL, got %s", did)
}
}
// TestGenerateDIDDocument tests DID document generation
func TestGenerateDIDDocument(t *testing.T) {
ctx := context.Background()
tmpDir := t.TempDir()
dbPath := filepath.Join(tmpDir, "pds.db")
keyPath := filepath.Join(tmpDir, "signing-key")
publicURL := "https://hold.example.com"
pds, err := NewHoldPDS(ctx, "did:web:hold.example.com", publicURL, dbPath, keyPath, false)
if err != nil {
t.Fatalf("Failed to create PDS: %v", err)
}
doc, err := pds.GenerateDIDDocument(publicURL)
if err != nil {
t.Fatalf("Failed to generate DID document: %v", err)
}
// Verify required fields
if doc.ID != "did:web:hold.example.com" {
t.Errorf("Expected DID did:web:hold.example.com, got %s", doc.ID)
}
// Verify context
if len(doc.Context) != 3 {
t.Errorf("Expected 3 context entries, got %d", len(doc.Context))
}
expectedContexts := []string{
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/multikey/v1",
"https://w3id.org/security/suites/secp256k1-2019/v1",
}
for i, expected := range expectedContexts {
if doc.Context[i] != expected {
t.Errorf("Expected context[%d] = %s, got %s", i, expected, doc.Context[i])
}
}
// Verify alsoKnownAs
if len(doc.AlsoKnownAs) != 1 || doc.AlsoKnownAs[0] != "at://hold.example.com" {
t.Errorf("Expected alsoKnownAs=['at://hold.example.com'], got %v", doc.AlsoKnownAs)
}
// Verify verification method
if len(doc.VerificationMethod) != 1 {
t.Fatalf("Expected 1 verification method, got %d", len(doc.VerificationMethod))
}
vm := doc.VerificationMethod[0]
if vm.ID != "did:web:hold.example.com#atproto" {
t.Errorf("Expected verification method ID did:web:hold.example.com#atproto, got %s", vm.ID)
}
if vm.Type != "Multikey" {
t.Errorf("Expected type Multikey, got %s", vm.Type)
}
if vm.Controller != "did:web:hold.example.com" {
t.Errorf("Expected controller did:web:hold.example.com, got %s", vm.Controller)
}
if vm.PublicKeyMultibase == "" {
t.Error("Expected non-empty publicKeyMultibase")
}
// Verify authentication
if len(doc.Authentication) != 1 || doc.Authentication[0] != "did:web:hold.example.com#atproto" {
t.Errorf("Expected authentication=['did:web:hold.example.com#atproto'], got %v", doc.Authentication)
}
// Verify services
if len(doc.Service) != 2 {
t.Fatalf("Expected 2 services, got %d", len(doc.Service))
}
// Check PDS service
pdsService := doc.Service[0]
if pdsService.ID != "#atproto_pds" {
t.Errorf("Expected service ID #atproto_pds, got %s", pdsService.ID)
}
if pdsService.Type != "AtprotoPersonalDataServer" {
t.Errorf("Expected service type AtprotoPersonalDataServer, got %s", pdsService.Type)
}
if pdsService.ServiceEndpoint != publicURL {
t.Errorf("Expected service endpoint %s, got %s", publicURL, pdsService.ServiceEndpoint)
}
// Check hold service
holdService := doc.Service[1]
if holdService.ID != "#atcr_hold" {
t.Errorf("Expected service ID #atcr_hold, got %s", holdService.ID)
}
if holdService.Type != "AtcrHoldService" {
t.Errorf("Expected service type AtcrHoldService, got %s", holdService.Type)
}
if holdService.ServiceEndpoint != publicURL {
t.Errorf("Expected service endpoint %s, got %s", publicURL, holdService.ServiceEndpoint)
}
}
// TestGenerateDIDDocument_WithPort tests DID document with non-standard port
func TestGenerateDIDDocument_WithPort(t *testing.T) {
ctx := context.Background()
tmpDir := t.TempDir()
dbPath := filepath.Join(tmpDir, "pds.db")
keyPath := filepath.Join(tmpDir, "signing-key")
publicURL := "https://hold.example.com:8443"
pds, err := NewHoldPDS(ctx, "did:web:hold.example.com:8443", publicURL, dbPath, keyPath, false)
if err != nil {
t.Fatalf("Failed to create PDS: %v", err)
}
doc, err := pds.GenerateDIDDocument(publicURL)
if err != nil {
t.Fatalf("Failed to generate DID document: %v", err)
}
// Verify DID includes port
if doc.ID != "did:web:hold.example.com:8443" {
t.Errorf("Expected DID did:web:hold.example.com:8443, got %s", doc.ID)
}
// Verify alsoKnownAs includes port
if doc.AlsoKnownAs[0] != "at://hold.example.com:8443" {
t.Errorf("Expected alsoKnownAs with port, got %s", doc.AlsoKnownAs[0])
}
}
// TestMarshalDIDDocument tests DID document JSON marshaling
func TestMarshalDIDDocument(t *testing.T) {
ctx := context.Background()
tmpDir := t.TempDir()
dbPath := filepath.Join(tmpDir, "pds.db")
keyPath := filepath.Join(tmpDir, "signing-key")
publicURL := "https://hold.example.com"
pds, err := NewHoldPDS(ctx, "did:web:hold.example.com", publicURL, dbPath, keyPath, false)
if err != nil {
t.Fatalf("Failed to create PDS: %v", err)
}
jsonBytes, err := pds.MarshalDIDDocument()
if err != nil {
t.Fatalf("Failed to marshal DID document: %v", err)
}
// Verify it's valid JSON
var doc map[string]any
if err := json.Unmarshal(jsonBytes, &doc); err != nil {
t.Fatalf("Failed to unmarshal DID document JSON: %v", err)
}
// Verify required fields
if id, ok := doc["id"].(string); !ok || id != "did:web:hold.example.com" {
t.Errorf("Expected id='did:web:hold.example.com', got %v", doc["id"])
}
if _, ok := doc["@context"]; !ok {
t.Error("Expected @context field in JSON")
}
if _, ok := doc["verificationMethod"]; !ok {
t.Error("Expected verificationMethod field in JSON")
}
if _, ok := doc["service"]; !ok {
t.Error("Expected service field in JSON")
}
// Verify pretty-printed (has indentation)
if len(jsonBytes) < 100 {
t.Error("Expected pretty-printed JSON to be reasonably sized")
}
}
// TestGenerateDIDDocument_InvalidURL tests error handling
func TestGenerateDIDDocument_InvalidURL(t *testing.T) {
ctx := context.Background()
tmpDir := t.TempDir()
dbPath := filepath.Join(tmpDir, "pds.db")
keyPath := filepath.Join(tmpDir, "signing-key")
publicURL := "https://hold.example.com"
pds, err := NewHoldPDS(ctx, "did:web:hold.example.com", publicURL, dbPath, keyPath, false)
if err != nil {
t.Fatalf("Failed to create PDS: %v", err)
}
// Try to generate DID document with invalid URL
_, err = pds.GenerateDIDDocument("ht!tp://invalid url")
if err == nil {
t.Error("Expected error for invalid URL, got nil")
}
}