 543ab216f9
			
		
	
	543ab216f9
	
	
	
		
			
			🎭 CHORUS now contains full BZZZ functionality adapted for containers Core systems ported: - P2P networking (libp2p with DHT and PubSub) - Task coordination (COOEE protocol) - HMMM collaborative reasoning - SHHH encryption and security - SLURP admin election system - UCXL content addressing - UCXI server integration - Hypercore logging system - Health monitoring and graceful shutdown - License validation with KACHING Container adaptations: - Environment variable configuration (no YAML files) - Container-optimized logging to stdout/stderr - Auto-generated agent IDs for container deployments - Docker-first architecture All proven BZZZ P2P protocols, AI integration, and collaboration features are now available in containerized form. Next: Build and test container deployment. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			726 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			726 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package ucxi
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"io/ioutil"
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 	"strings"
 | |
| 	"testing"
 | |
| 	"time"
 | |
| )
 | |
| 
 | |
| func createTempStorageDir(t *testing.T) string {
 | |
| 	dir, err := ioutil.TempDir("", "ucxi-storage-test-*")
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create temp directory: %v", err)
 | |
| 	}
 | |
| 	return dir
 | |
| }
 | |
| 
 | |
| func TestNewBasicContentStorage(t *testing.T) {
 | |
| 	tempDir := createTempStorageDir(t)
 | |
| 	defer os.RemoveAll(tempDir)
 | |
| 	
 | |
| 	storage, err := NewBasicContentStorage(tempDir)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("NewBasicContentStorage failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	if storage == nil {
 | |
| 		t.Error("NewBasicContentStorage should not return nil")
 | |
| 	}
 | |
| 	
 | |
| 	if storage.basePath != tempDir {
 | |
| 		t.Errorf("Base path = %s, want %s", storage.basePath, tempDir)
 | |
| 	}
 | |
| 	
 | |
| 	// Verify directory was created
 | |
| 	if _, err := os.Stat(tempDir); os.IsNotExist(err) {
 | |
| 		t.Error("Storage directory should be created")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestNewBasicContentStorageWithInvalidPath(t *testing.T) {
 | |
| 	// Try to create storage with invalid path (e.g., a file instead of directory)
 | |
| 	tempDir := createTempStorageDir(t)
 | |
| 	defer os.RemoveAll(tempDir)
 | |
| 	
 | |
| 	// Create a file at the path
 | |
| 	invalidPath := filepath.Join(tempDir, "file-not-dir")
 | |
| 	if err := ioutil.WriteFile(invalidPath, []byte("test"), 0644); err != nil {
 | |
| 		t.Fatalf("Failed to create test file: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	// This should fail because the path exists as a file, not a directory
 | |
| 	_, err := NewBasicContentStorage(invalidPath)
 | |
| 	if err == nil {
 | |
| 		t.Error("NewBasicContentStorage should fail with invalid path")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestStorageStoreAndRetrieve(t *testing.T) {
 | |
| 	tempDir := createTempStorageDir(t)
 | |
| 	defer os.RemoveAll(tempDir)
 | |
| 	
 | |
| 	storage, err := NewBasicContentStorage(tempDir)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create storage: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	ctx := context.Background()
 | |
| 	key := "test-key"
 | |
| 	content := &Content{
 | |
| 		Data:        []byte("test content data"),
 | |
| 		ContentType: "text/plain",
 | |
| 		Metadata: map[string]string{
 | |
| 			"author":  "test-author",
 | |
| 			"version": "1.0",
 | |
| 		},
 | |
| 		Version:   1,
 | |
| 		CreatedAt: time.Now(),
 | |
| 		UpdatedAt: time.Now(),
 | |
| 		Author:    "test-user",
 | |
| 	}
 | |
| 	
 | |
| 	// Test store
 | |
| 	err = storage.Store(ctx, key, content)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Store failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	// Test retrieve
 | |
| 	retrieved, err := storage.Retrieve(ctx, key)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Retrieve failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	if retrieved == nil {
 | |
| 		t.Error("Retrieved content should not be nil")
 | |
| 	}
 | |
| 	
 | |
| 	// Verify content matches
 | |
| 	if string(retrieved.Data) != string(content.Data) {
 | |
| 		t.Errorf("Data mismatch: got %s, want %s", string(retrieved.Data), string(content.Data))
 | |
| 	}
 | |
| 	
 | |
| 	if retrieved.ContentType != content.ContentType {
 | |
| 		t.Errorf("ContentType mismatch: got %s, want %s", retrieved.ContentType, content.ContentType)
 | |
| 	}
 | |
| 	
 | |
| 	if retrieved.Author != content.Author {
 | |
| 		t.Errorf("Author mismatch: got %s, want %s", retrieved.Author, content.Author)
 | |
| 	}
 | |
| 	
 | |
| 	if retrieved.Version != content.Version {
 | |
| 		t.Errorf("Version mismatch: got %d, want %d", retrieved.Version, content.Version)
 | |
| 	}
 | |
| 	
 | |
| 	// Verify metadata
 | |
| 	if len(retrieved.Metadata) != len(content.Metadata) {
 | |
| 		t.Errorf("Metadata length mismatch: got %d, want %d", len(retrieved.Metadata), len(content.Metadata))
 | |
| 	}
 | |
| 	
 | |
| 	for key, value := range content.Metadata {
 | |
| 		if retrieved.Metadata[key] != value {
 | |
| 			t.Errorf("Metadata[%s] mismatch: got %s, want %s", key, retrieved.Metadata[key], value)
 | |
| 		}
 | |
| 	}
 | |
| 	
 | |
| 	// Verify checksum is calculated
 | |
| 	if retrieved.Checksum == "" {
 | |
| 		t.Error("Checksum should be calculated and stored")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestStorageChecksumValidation(t *testing.T) {
 | |
| 	tempDir := createTempStorageDir(t)
 | |
| 	defer os.RemoveAll(tempDir)
 | |
| 	
 | |
| 	storage, err := NewBasicContentStorage(tempDir)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create storage: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	ctx := context.Background()
 | |
| 	key := "checksum-test"
 | |
| 	content := &Content{
 | |
| 		Data:        []byte("test content for checksum"),
 | |
| 		ContentType: "text/plain",
 | |
| 	}
 | |
| 	
 | |
| 	// Store content (checksum will be calculated automatically)
 | |
| 	err = storage.Store(ctx, key, content)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Store failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	// Retrieve and verify checksum validation works
 | |
| 	retrieved, err := storage.Retrieve(ctx, key)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Retrieve failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	if retrieved.Checksum == "" {
 | |
| 		t.Error("Checksum should be set after storing")
 | |
| 	}
 | |
| 	
 | |
| 	// Manually corrupt the file to test checksum validation
 | |
| 	filePath := storage.getFilePath(key)
 | |
| 	originalData, err := ioutil.ReadFile(filePath)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to read file: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	// Corrupt the data in the JSON by changing base64 encoded data
 | |
| 	// The content is base64 encoded in JSON, so we'll replace some characters
 | |
| 	corruptedData := strings.Replace(string(originalData), "dGVzdCBjb250ZW50IGZvciBjaGVja3N1bQ==", "Y29ycnVwdGVkIGNvbnRlbnQ=", 1)
 | |
| 	if corruptedData == string(originalData) {
 | |
| 		// If the base64 replacement didn't work, try a simpler corruption
 | |
| 		corruptedData = strings.Replace(string(originalData), "\"", "'", 1)
 | |
| 		if corruptedData == string(originalData) {
 | |
| 			t.Fatalf("Failed to corrupt data - no changes made")
 | |
| 		}
 | |
| 	}
 | |
| 	
 | |
| 	err = ioutil.WriteFile(filePath, []byte(corruptedData), 0644)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to write corrupted file: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	// Retrieve should fail due to checksum mismatch
 | |
| 	_, err = storage.Retrieve(ctx, key)
 | |
| 	if err == nil {
 | |
| 		t.Error("Retrieve should fail with corrupted content")
 | |
| 	}
 | |
| 	
 | |
| 	if !strings.Contains(err.Error(), "checksum mismatch") {
 | |
| 		t.Errorf("Error should mention checksum mismatch, got: %v", err)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestStorageDelete(t *testing.T) {
 | |
| 	tempDir := createTempStorageDir(t)
 | |
| 	defer os.RemoveAll(tempDir)
 | |
| 	
 | |
| 	storage, err := NewBasicContentStorage(tempDir)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create storage: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	ctx := context.Background()
 | |
| 	key := "delete-test"
 | |
| 	content := &Content{Data: []byte("content to delete")}
 | |
| 	
 | |
| 	// Store content
 | |
| 	err = storage.Store(ctx, key, content)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Store failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	// Verify it exists
 | |
| 	exists, err := storage.Exists(ctx, key)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Exists check failed: %v", err)
 | |
| 	}
 | |
| 	if !exists {
 | |
| 		t.Error("Content should exist after storing")
 | |
| 	}
 | |
| 	
 | |
| 	// Delete content
 | |
| 	err = storage.Delete(ctx, key)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Delete failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	// Verify it no longer exists
 | |
| 	exists, err = storage.Exists(ctx, key)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Exists check after delete failed: %v", err)
 | |
| 	}
 | |
| 	if exists {
 | |
| 		t.Error("Content should not exist after deletion")
 | |
| 	}
 | |
| 	
 | |
| 	// Verify retrieve fails
 | |
| 	_, err = storage.Retrieve(ctx, key)
 | |
| 	if err == nil {
 | |
| 		t.Error("Retrieve should fail for deleted content")
 | |
| 	}
 | |
| 	
 | |
| 	// Delete non-existent key should fail
 | |
| 	err = storage.Delete(ctx, "non-existent-key")
 | |
| 	if err == nil {
 | |
| 		t.Error("Delete should fail for non-existent key")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestStorageList(t *testing.T) {
 | |
| 	tempDir := createTempStorageDir(t)
 | |
| 	defer os.RemoveAll(tempDir)
 | |
| 	
 | |
| 	storage, err := NewBasicContentStorage(tempDir)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create storage: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	ctx := context.Background()
 | |
| 	
 | |
| 	// Store multiple pieces of content
 | |
| 	testKeys := []string{
 | |
| 		"prefix1/key1",
 | |
| 		"prefix1/key2", 
 | |
| 		"prefix2/key1",
 | |
| 		"prefix2/key2",
 | |
| 		"different-prefix/key1",
 | |
| 	}
 | |
| 	
 | |
| 	for i, key := range testKeys {
 | |
| 		content := &Content{Data: []byte(fmt.Sprintf("content-%d", i))}
 | |
| 		err = storage.Store(ctx, key, content)
 | |
| 		if err != nil {
 | |
| 			t.Errorf("Store failed for key %s: %v", key, err)
 | |
| 		}
 | |
| 	}
 | |
| 	
 | |
| 	// Test list all
 | |
| 	allKeys, err := storage.List(ctx, "")
 | |
| 	if err != nil {
 | |
| 		t.Errorf("List all failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	if len(allKeys) != len(testKeys) {
 | |
| 		t.Errorf("List all returned %d keys, want %d", len(allKeys), len(testKeys))
 | |
| 	}
 | |
| 	
 | |
| 	// Test list with prefix
 | |
| 	prefix1Keys, err := storage.List(ctx, "prefix1/")
 | |
| 	if err != nil {
 | |
| 		t.Errorf("List with prefix failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	if len(prefix1Keys) != 2 {
 | |
| 		t.Errorf("List prefix1/ returned %d keys, want 2", len(prefix1Keys))
 | |
| 	}
 | |
| 	
 | |
| 	// Verify the keys match the prefix
 | |
| 	for _, key := range prefix1Keys {
 | |
| 		if !strings.HasPrefix(key, "prefix1/") {
 | |
| 			t.Errorf("Key %s should have prefix 'prefix1/'", key)
 | |
| 		}
 | |
| 	}
 | |
| 	
 | |
| 	// Test list with non-existent prefix
 | |
| 	noKeys, err := storage.List(ctx, "nonexistent/")
 | |
| 	if err != nil {
 | |
| 		t.Errorf("List non-existent prefix failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	if len(noKeys) != 0 {
 | |
| 		t.Errorf("List non-existent prefix returned %d keys, want 0", len(noKeys))
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestStorageExists(t *testing.T) {
 | |
| 	tempDir := createTempStorageDir(t)
 | |
| 	defer os.RemoveAll(tempDir)
 | |
| 	
 | |
| 	storage, err := NewBasicContentStorage(tempDir)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create storage: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	ctx := context.Background()
 | |
| 	key := "exists-test"
 | |
| 	
 | |
| 	// Initially should not exist
 | |
| 	exists, err := storage.Exists(ctx, key)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Exists check failed: %v", err)
 | |
| 	}
 | |
| 	if exists {
 | |
| 		t.Error("Key should not exist initially")
 | |
| 	}
 | |
| 	
 | |
| 	// Store content
 | |
| 	content := &Content{Data: []byte("test")}
 | |
| 	err = storage.Store(ctx, key, content)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Store failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	// Should exist now
 | |
| 	exists, err = storage.Exists(ctx, key)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Exists check after store failed: %v", err)
 | |
| 	}
 | |
| 	if !exists {
 | |
| 		t.Error("Key should exist after storing")
 | |
| 	}
 | |
| 	
 | |
| 	// Delete content
 | |
| 	err = storage.Delete(ctx, key)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Delete failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	// Should not exist anymore
 | |
| 	exists, err = storage.Exists(ctx, key)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Exists check after delete failed: %v", err)
 | |
| 	}
 | |
| 	if exists {
 | |
| 		t.Error("Key should not exist after deletion")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestStorageClear(t *testing.T) {
 | |
| 	tempDir := createTempStorageDir(t)
 | |
| 	defer os.RemoveAll(tempDir)
 | |
| 	
 | |
| 	storage, err := NewBasicContentStorage(tempDir)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create storage: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	ctx := context.Background()
 | |
| 	
 | |
| 	// Store multiple pieces of content
 | |
| 	for i := 0; i < 5; i++ {
 | |
| 		key := fmt.Sprintf("key-%d", i)
 | |
| 		content := &Content{Data: []byte(fmt.Sprintf("content-%d", i))}
 | |
| 		err = storage.Store(ctx, key, content)
 | |
| 		if err != nil {
 | |
| 			t.Errorf("Store failed for key %s: %v", key, err)
 | |
| 		}
 | |
| 	}
 | |
| 	
 | |
| 	// Verify content exists
 | |
| 	keys, err := storage.List(ctx, "")
 | |
| 	if err != nil {
 | |
| 		t.Errorf("List failed: %v", err)
 | |
| 	}
 | |
| 	if len(keys) != 5 {
 | |
| 		t.Errorf("Expected 5 keys before clear, got %d", len(keys))
 | |
| 	}
 | |
| 	
 | |
| 	// Clear all content
 | |
| 	err = storage.Clear(ctx)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Clear failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	// Verify all content is gone
 | |
| 	keys, err = storage.List(ctx, "")
 | |
| 	if err != nil {
 | |
| 		t.Errorf("List after clear failed: %v", err)
 | |
| 	}
 | |
| 	if len(keys) != 0 {
 | |
| 		t.Errorf("Expected 0 keys after clear, got %d", len(keys))
 | |
| 	}
 | |
| 	
 | |
| 	// Verify directory still exists but is empty
 | |
| 	if _, err := os.Stat(tempDir); os.IsNotExist(err) {
 | |
| 		t.Error("Base directory should still exist after clear")
 | |
| 	}
 | |
| 	
 | |
| 	entries, err := ioutil.ReadDir(tempDir)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Failed to read directory after clear: %v", err)
 | |
| 	}
 | |
| 	if len(entries) != 0 {
 | |
| 		t.Errorf("Directory should be empty after clear, found %d entries", len(entries))
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestStorageGetStorageStats(t *testing.T) {
 | |
| 	tempDir := createTempStorageDir(t)
 | |
| 	defer os.RemoveAll(tempDir)
 | |
| 	
 | |
| 	storage, err := NewBasicContentStorage(tempDir)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create storage: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	ctx := context.Background()
 | |
| 	
 | |
| 	// Initially should have no files
 | |
| 	stats, err := storage.GetStorageStats()
 | |
| 	if err != nil {
 | |
| 		t.Errorf("GetStorageStats failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	if stats["file_count"].(int) != 0 {
 | |
| 		t.Errorf("Initial file count = %d, want 0", stats["file_count"])
 | |
| 	}
 | |
| 	
 | |
| 	if stats["total_size"].(int64) != 0 {
 | |
| 		t.Errorf("Initial total size = %d, want 0", stats["total_size"])
 | |
| 	}
 | |
| 	
 | |
| 	if stats["base_path"].(string) != tempDir {
 | |
| 		t.Errorf("Base path = %s, want %s", stats["base_path"], tempDir)
 | |
| 	}
 | |
| 	
 | |
| 	// Store some content
 | |
| 	for i := 0; i < 3; i++ {
 | |
| 		key := fmt.Sprintf("stats-key-%d", i)
 | |
| 		content := &Content{Data: []byte(fmt.Sprintf("test content %d", i))}
 | |
| 		err = storage.Store(ctx, key, content)
 | |
| 		if err != nil {
 | |
| 			t.Errorf("Store failed: %v", err)
 | |
| 		}
 | |
| 	}
 | |
| 	
 | |
| 	// Check stats again
 | |
| 	stats, err = storage.GetStorageStats()
 | |
| 	if err != nil {
 | |
| 		t.Errorf("GetStorageStats after store failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	if stats["file_count"].(int) != 3 {
 | |
| 		t.Errorf("File count after storing = %d, want 3", stats["file_count"])
 | |
| 	}
 | |
| 	
 | |
| 	if stats["total_size"].(int64) <= 0 {
 | |
| 		t.Error("Total size should be greater than 0 after storing content")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestStorageGetFilePath(t *testing.T) {
 | |
| 	tempDir := createTempStorageDir(t)
 | |
| 	defer os.RemoveAll(tempDir)
 | |
| 	
 | |
| 	storage, err := NewBasicContentStorage(tempDir)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create storage: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	tests := []struct {
 | |
| 		name         string
 | |
| 		key          string
 | |
| 		shouldContain []string
 | |
| 		shouldNotContain []string
 | |
| 	}{
 | |
| 		{
 | |
| 			name: "simple key",
 | |
| 			key:  "simple-key",
 | |
| 			shouldContain: []string{"simple-key.json"},
 | |
| 			shouldNotContain: []string{":"},
 | |
| 		},
 | |
| 		{
 | |
| 			name: "key with colons",
 | |
| 			key:  "agent:role",
 | |
| 			shouldContain: []string{"agent_role.json"},
 | |
| 			shouldNotContain: []string{":"},
 | |
| 		},
 | |
| 		{
 | |
| 			name: "key with at symbol",
 | |
| 			key:  "agent@project",
 | |
| 			shouldContain: []string{"agent_at_project.json"},
 | |
| 			shouldNotContain: []string{"@"},
 | |
| 		},
 | |
| 		{
 | |
| 			name: "key with slashes",
 | |
| 			key:  "path/to/resource",
 | |
| 			shouldContain: []string{".json"},
 | |
| 			// Should not contain the original slash as literal
 | |
| 		},
 | |
| 	}
 | |
| 	
 | |
| 	for _, tt := range tests {
 | |
| 		t.Run(tt.name, func(t *testing.T) {
 | |
| 			filePath := storage.getFilePath(tt.key)
 | |
| 			
 | |
| 			// Should always start with base path
 | |
| 			if !strings.HasPrefix(filePath, tempDir) {
 | |
| 				t.Errorf("File path should start with base path")
 | |
| 			}
 | |
| 			
 | |
| 			// Should always end with .json
 | |
| 			if !strings.HasSuffix(filePath, ".json") {
 | |
| 				t.Errorf("File path should end with .json")
 | |
| 			}
 | |
| 			
 | |
| 			// Check required substrings
 | |
| 			for _, required := range tt.shouldContain {
 | |
| 				if !strings.Contains(filePath, required) {
 | |
| 					t.Errorf("File path should contain '%s', got: %s", required, filePath)
 | |
| 				}
 | |
| 			}
 | |
| 			
 | |
| 			// Check forbidden substrings
 | |
| 			for _, forbidden := range tt.shouldNotContain {
 | |
| 				if strings.Contains(filePath, forbidden) {
 | |
| 					t.Errorf("File path should not contain '%s', got: %s", forbidden, filePath)
 | |
| 				}
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestStorageErrorCases(t *testing.T) {
 | |
| 	tempDir := createTempStorageDir(t)
 | |
| 	defer os.RemoveAll(tempDir)
 | |
| 	
 | |
| 	storage, err := NewBasicContentStorage(tempDir)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create storage: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	ctx := context.Background()
 | |
| 	
 | |
| 	// Test empty key
 | |
| 	content := &Content{Data: []byte("test")}
 | |
| 	
 | |
| 	err = storage.Store(ctx, "", content)
 | |
| 	if err == nil {
 | |
| 		t.Error("Store with empty key should fail")
 | |
| 	}
 | |
| 	
 | |
| 	_, err = storage.Retrieve(ctx, "")
 | |
| 	if err == nil {
 | |
| 		t.Error("Retrieve with empty key should fail")
 | |
| 	}
 | |
| 	
 | |
| 	err = storage.Delete(ctx, "")
 | |
| 	if err == nil {
 | |
| 		t.Error("Delete with empty key should fail")
 | |
| 	}
 | |
| 	
 | |
| 	_, err = storage.Exists(ctx, "")
 | |
| 	if err == nil {
 | |
| 		t.Error("Exists with empty key should fail")
 | |
| 	}
 | |
| 	
 | |
| 	// Test nil content
 | |
| 	err = storage.Store(ctx, "test-key", nil)
 | |
| 	if err == nil {
 | |
| 		t.Error("Store with nil content should fail")
 | |
| 	}
 | |
| 	
 | |
| 	// Test retrieve non-existent key
 | |
| 	_, err = storage.Retrieve(ctx, "non-existent-key")
 | |
| 	if err == nil {
 | |
| 		t.Error("Retrieve non-existent key should fail")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Test concurrent access to storage
 | |
| func TestStorageConcurrency(t *testing.T) {
 | |
| 	tempDir := createTempStorageDir(t)
 | |
| 	defer os.RemoveAll(tempDir)
 | |
| 	
 | |
| 	storage, err := NewBasicContentStorage(tempDir)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create storage: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	ctx := context.Background()
 | |
| 	done := make(chan bool, 10)
 | |
| 	
 | |
| 	// Run multiple goroutines that store, retrieve, and delete content
 | |
| 	for i := 0; i < 10; i++ {
 | |
| 		go func(id int) {
 | |
| 			defer func() { done <- true }()
 | |
| 			
 | |
| 			key := fmt.Sprintf("concurrent-key-%d", id)
 | |
| 			content := &Content{Data: []byte(fmt.Sprintf("content-%d", id))}
 | |
| 			
 | |
| 			// Store
 | |
| 			if err := storage.Store(ctx, key, content); err != nil {
 | |
| 				t.Errorf("Goroutine %d store failed: %v", id, err)
 | |
| 				return
 | |
| 			}
 | |
| 			
 | |
| 			// Retrieve
 | |
| 			if _, err := storage.Retrieve(ctx, key); err != nil {
 | |
| 				t.Errorf("Goroutine %d retrieve failed: %v", id, err)
 | |
| 				return
 | |
| 			}
 | |
| 			
 | |
| 			// Delete
 | |
| 			if err := storage.Delete(ctx, key); err != nil {
 | |
| 				t.Errorf("Goroutine %d delete failed: %v", id, err)
 | |
| 				return
 | |
| 			}
 | |
| 		}(i)
 | |
| 	}
 | |
| 	
 | |
| 	// Wait for all goroutines to complete
 | |
| 	for i := 0; i < 10; i++ {
 | |
| 		<-done
 | |
| 	}
 | |
| 	
 | |
| 	// Verify final state - all content should be deleted
 | |
| 	keys, err := storage.List(ctx, "")
 | |
| 	if err != nil {
 | |
| 		t.Errorf("List after concurrent operations failed: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	if len(keys) != 0 {
 | |
| 		t.Errorf("Expected 0 keys after concurrent operations, got %d", len(keys))
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Benchmark tests
 | |
| func BenchmarkStorageStore(b *testing.B) {
 | |
| 	tempDir := createTempStorageDirForBench(b)
 | |
| 	defer os.RemoveAll(tempDir)
 | |
| 	
 | |
| 	storage, err := NewBasicContentStorage(tempDir)
 | |
| 	if err != nil {
 | |
| 		b.Fatalf("Failed to create storage: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	ctx := context.Background()
 | |
| 	content := &Content{
 | |
| 		Data:        []byte("benchmark test content"),
 | |
| 		ContentType: "text/plain",
 | |
| 	}
 | |
| 	
 | |
| 	b.ResetTimer()
 | |
| 	for i := 0; i < b.N; i++ {
 | |
| 		key := fmt.Sprintf("benchmark-key-%d", i)
 | |
| 		storage.Store(ctx, key, content)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func BenchmarkStorageRetrieve(b *testing.B) {
 | |
| 	tempDir := createTempStorageDirForBench(b)
 | |
| 	defer os.RemoveAll(tempDir)
 | |
| 	
 | |
| 	storage, err := NewBasicContentStorage(tempDir)
 | |
| 	if err != nil {
 | |
| 		b.Fatalf("Failed to create storage: %v", err)
 | |
| 	}
 | |
| 	
 | |
| 	ctx := context.Background()
 | |
| 	content := &Content{
 | |
| 		Data:        []byte("benchmark test content"),
 | |
| 		ContentType: "text/plain",
 | |
| 	}
 | |
| 	
 | |
| 	// Pre-populate storage
 | |
| 	keys := make([]string, 1000)
 | |
| 	for i := 0; i < 1000; i++ {
 | |
| 		keys[i] = fmt.Sprintf("benchmark-key-%d", i)
 | |
| 		storage.Store(ctx, keys[i], content)
 | |
| 	}
 | |
| 	
 | |
| 	b.ResetTimer()
 | |
| 	for i := 0; i < b.N; i++ {
 | |
| 		key := keys[i%1000]
 | |
| 		storage.Retrieve(ctx, key)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Helper function for benchmark that creates temp directory
 | |
| func createTempStorageDirForBench(t testing.TB) string {
 | |
| 	dir, err := ioutil.TempDir("", "ucxi-storage-test-*")
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create temp directory: %v", err)
 | |
| 	}
 | |
| 	return dir
 | |
| } |