143 lines
4.7 KiB
Go
143 lines
4.7 KiB
Go
package agate
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"gitea.unprism.ru/KRBL/Agate/remote"
|
|
)
|
|
|
|
// TestFullUpdateCycle tests a complete workflow: full download, then incremental update.
|
|
func TestFullUpdateCycle(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("Skipping full gRPC update cycle test in short mode")
|
|
}
|
|
|
|
// --- 1. Setup Server ---
|
|
serverDir, err := os.MkdirTemp("", "agate-server-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create server temp directory: %v", err)
|
|
}
|
|
defer os.RemoveAll(serverDir)
|
|
|
|
serverAgate, err := New(AgateOptions{WorkDir: serverDir})
|
|
if err != nil {
|
|
t.Fatalf("Failed to create server Agate instance: %v", err)
|
|
}
|
|
defer serverAgate.Close()
|
|
|
|
// --- 2. Create Initial Snapshot (A) ---
|
|
dataDir := serverAgate.GetActiveDir()
|
|
if err := os.WriteFile(filepath.Join(dataDir, "file1.txt"), []byte("Version 1"), 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(dataDir, "file2.txt"), []byte("Original Content"), 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
snapshotAID, err := serverAgate.SaveSnapshot(ctx, "Snapshot A", "")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create Snapshot A: %v", err)
|
|
}
|
|
t.Logf("Created Snapshot A with ID: %s", snapshotAID)
|
|
|
|
// --- 3. Start Server ---
|
|
serverAddress := "localhost:50051"
|
|
server := remote.NewServer(serverAgate.manager)
|
|
go func() {
|
|
if err := server.Start(ctx, serverAddress); err != nil && err != context.Canceled {
|
|
log.Printf("Server start error: %v", err)
|
|
}
|
|
}()
|
|
defer server.Stop()
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
// --- 4. Setup Client ---
|
|
clientDir, err := os.MkdirTemp("", "agate-client-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create client temp directory: %v", err)
|
|
}
|
|
defer os.RemoveAll(clientDir)
|
|
|
|
clientAgate, err := New(AgateOptions{WorkDir: clientDir, CleanOnRestore: true})
|
|
if err != nil {
|
|
t.Fatalf("Failed to create client Agate instance: %v", err)
|
|
}
|
|
defer clientAgate.Close()
|
|
|
|
// --- 5. Client Performs Full Download of Snapshot A ---
|
|
t.Log("Client performing full download of Snapshot A...")
|
|
if err := clientAgate.GetRemoteSnapshot(ctx, serverAddress, snapshotAID, ""); err != nil {
|
|
t.Fatalf("Client failed to get Snapshot A: %v", err)
|
|
}
|
|
|
|
// Verify content of Snapshot A on client
|
|
if err := clientAgate.RestoreSnapshot(ctx, snapshotAID); err != nil {
|
|
t.Fatalf("Failed to restore Snapshot A: %v", err)
|
|
}
|
|
verifyFileContent(t, clientAgate.GetActiveDir(), "file1.txt", "Version 1")
|
|
verifyFileContent(t, clientAgate.GetActiveDir(), "file2.txt", "Original Content")
|
|
t.Log("Snapshot A verified on client.")
|
|
|
|
// --- 6. Server Creates Incremental Snapshot (B) ---
|
|
if err := os.WriteFile(filepath.Join(dataDir, "file1.txt"), []byte("Version 2"), 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(dataDir, "file3.txt"), []byte("New File"), 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.Remove(filepath.Join(dataDir, "file2.txt")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
snapshotBID, err := serverAgate.SaveSnapshot(ctx, "Snapshot B", snapshotAID)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create Snapshot B: %v", err)
|
|
}
|
|
t.Logf("Created Snapshot B with ID: %s", snapshotBID)
|
|
|
|
// --- 7. Client Performs Incremental Download of Snapshot B ---
|
|
t.Log("Client performing incremental download of Snapshot B...")
|
|
parentIDOnClient := clientAgate.GetCurrentSnapshotID()
|
|
if parentIDOnClient != snapshotAID {
|
|
t.Fatalf("Client has incorrect current snapshot ID. Got %s, want %s", parentIDOnClient, snapshotAID)
|
|
}
|
|
|
|
if err := clientAgate.GetRemoteSnapshot(ctx, serverAddress, snapshotBID, parentIDOnClient); err != nil {
|
|
t.Fatalf("Client failed to get Snapshot B: %v", err)
|
|
}
|
|
|
|
// --- 8. Verify Final State on Client ---
|
|
if err := clientAgate.RestoreSnapshot(ctx, snapshotBID); err != nil {
|
|
t.Fatalf("Failed to restore Snapshot B: %v", err)
|
|
}
|
|
t.Log("Snapshot B restored on client. Verifying content...")
|
|
|
|
verifyFileContent(t, clientAgate.GetActiveDir(), "file1.txt", "Version 2")
|
|
verifyFileContent(t, clientAgate.GetActiveDir(), "file3.txt", "New File")
|
|
|
|
// Verify that file2.txt was removed because CleanOnRestore is true
|
|
if _, err := os.Stat(filepath.Join(clientAgate.GetActiveDir(), "file2.txt")); !os.IsNotExist(err) {
|
|
t.Errorf("file2.txt should have been removed after restoring Snapshot B, but it still exists.")
|
|
}
|
|
t.Log("Final state verified successfully!")
|
|
}
|
|
|
|
func verifyFileContent(t *testing.T, dir, filename, expectedContent string) {
|
|
t.Helper()
|
|
content, err := os.ReadFile(filepath.Join(dir, filename))
|
|
if err != nil {
|
|
t.Fatalf("Failed to read file %s: %v", filename, err)
|
|
}
|
|
if string(content) != expectedContent {
|
|
t.Errorf("File %s has wrong content: got '%s', want '%s'", filename, string(content), expectedContent)
|
|
}
|
|
}
|