package storage import ( "os" "path/filepath" "testing" "time" ) func TestStorage_Init(t *testing.T) { // Create temp directory for testing tempDir := t.TempDir() _ = NewStorage(tempDir) // Verify directory exists if _, err := os.Stat(tempDir); os.IsNotExist(err) { t.Errorf("data directory should be created") } // Verify it's empty files, err := os.ReadDir(tempDir) if err != nil { t.Fatalf("failed to read directory: %v", err) } if len(files) != 0 { t.Errorf("directory should be empty initially") } } func TestStorage_ListFiles_Empty(t *testing.T) { tempDir := t.TempDir() store := NewStorage(tempDir) files, err := store.ListFiles() if err != nil { t.Fatalf("ListFiles failed: %v", err) } if len(files) != 0 { t.Errorf("expected 0 files, got %d", len(files)) } } func TestStorage_ListFiles_Multiple(t *testing.T) { tempDir := t.TempDir() store := NewStorage(tempDir) // Create test files testFiles := []string{"file1.md", "file2.md", "file3.md"} for _, name := range testFiles { content := "# Test " + name if err := os.WriteFile(filepath.Join(tempDir, name), []byte(content), 0644); err != nil { t.Fatalf("failed to create test file: %v", err) } } files, err := store.ListFiles() if err != nil { t.Fatalf("ListFiles failed: %v", err) } if len(files) != 3 { t.Errorf("expected 3 files, got %d", len(files)) } } func TestStorage_CRUD(t *testing.T) { tempDir := t.TempDir() store := NewStorage(tempDir) // Test Create filename := "test.md" content := "# Hello World\n\nThis is a test file." created, err := store.CreateFile(filename, content) if err != nil { t.Fatalf("CreateFile failed: %v", err) } if created.Filename != filename { t.Errorf("expected filename %s, got %s", filename, created.Filename) } if created.Content != content { t.Errorf("expected content %s, got %s", content, created.Content) } if created.Title != "test" { t.Errorf("expected title 'test', got '%s'", created.Title) } if created.Modified.IsZero() { t.Errorf("modified timestamp should not be zero") } if created.Size != int64(len(content)) { t.Errorf("expected size %d, got %d", len(content), created.Size) } // Test Get retrieved, err := store.GetFile(filename) if err != nil { t.Fatalf("GetFile failed: %v", err) } if retrieved.Content != content { t.Errorf("expected content %s, got %s", content, retrieved.Content) } // Test Update newContent := "# Updated\n\nContent was updated." updated, err := store.UpdateFile(filename, newContent) if err != nil { t.Fatalf("UpdateFile failed: %v", err) } if updated.Content != newContent { t.Errorf("expected updated content %s, got %s", newContent, updated.Content) } if updated.Modified.Before(created.Modified) { t.Errorf("modified timestamp should be updated") } // Test List includes updated file files, err := store.ListFiles() if err != nil { t.Fatalf("ListFiles failed: %v", err) } var found bool for _, f := range files { if f.Filename == filename { found = true if f.Size != int64(len(newContent)) { t.Errorf("expected size %d for list, got %d", len(newContent), f.Size) } } } if !found { t.Errorf("updated file not found in list") } // Test Delete if err := store.DeleteFile(filename); err != nil { t.Fatalf("DeleteFile failed: %v", err) } if _, err := os.Stat(filepath.Join(tempDir, filename)); !os.IsNotExist(err) { t.Errorf("file should be deleted") } // Verify file is gone if _, err := store.GetFile(filename); err == nil { t.Errorf("GetFile should fail after deletion") } } func TestStorage_ValidateFilename(t *testing.T) { tempDir := t.TempDir() store := NewStorage(tempDir) tests := []struct { name string filename string valid bool }{ {"valid .md file", "test.md", true}, {"valid with numbers", "file123.md", true}, {"invalid without extension", "test", false}, {"invalid wrong extension", "test.txt", false}, {"invalid path traversal", "../etc/passwd", false}, {"invalid with slash", "dir/file.md", false}, {"empty filename", "", false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := store.ValidateFilename(tt.filename) if tt.valid && err != nil { t.Errorf("expected valid, got error: %v", err) } if !tt.valid && err == nil { t.Errorf("expected error, got nil") } }) } } func TestStorage_FileNotFound(t *testing.T) { tempDir := t.TempDir() store := NewStorage(tempDir) _, err := store.GetFile("nonexistent.md") if err == nil { t.Errorf("GetFile should return error for non-existent file") } _, err = store.UpdateFile("nonexistent.md", "content") if err == nil { t.Errorf("UpdateFile should return error for non-existent file") } err = store.DeleteFile("nonexistent.md") if err == nil { t.Errorf("DeleteFile should return error for non-existent file") } } func TestStorage_FileExists(t *testing.T) { tempDir := t.TempDir() store := NewStorage(tempDir) // Create file _, err := store.CreateFile("exists.md", "content") if err != nil { t.Fatalf("CreateFile failed: %v", err) } // Try to create again _, err = store.CreateFile("exists.md", "content") if err == nil { t.Errorf("CreateFile should fail for existing file") } } func TestStorage_ModificationTime(t *testing.T) { tempDir := t.TempDir() store := NewStorage(tempDir) // Create file created, err := store.CreateFile("test.md", "content") if err != nil { t.Fatalf("CreateFile failed: %v", err) } // Wait a moment time.Sleep(100 * time.Millisecond) // Update file updated, err := store.UpdateFile("test.md", "new content") if err != nil { t.Fatalf("UpdateFile failed: %v", err) } // Verify modification time was updated if !updated.Modified.After(created.Modified) { t.Errorf("modified time should be updated on update") } }