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) } }