server auth
This commit is contained in:
@@ -3,6 +3,7 @@ package sync
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -174,6 +175,75 @@ func TestApplyDeltaDetectsConflicts(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyDeltaAllowsDifferentFileEditsWithoutConflict(t *testing.T) {
|
||||
service, sourceDir := setupTestService(t)
|
||||
ctx := context.Background()
|
||||
|
||||
snap, err := service.InitSync(ctx, "device-1", "user:test")
|
||||
if err != nil {
|
||||
t.Fatalf("InitSync() error = %v", err)
|
||||
}
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
if err := os.WriteFile(filepath.Join(sourceDir, "guide.md"), []byte("# Guide\n\nServer-side guide update"), 0o644); err != nil {
|
||||
t.Fatalf("update guide.md: %v", err)
|
||||
}
|
||||
|
||||
clientChange := Change{
|
||||
Type: ChangeUpdate,
|
||||
Path: "hello.md",
|
||||
Hash: "clienthash-different-file",
|
||||
Size: 128,
|
||||
Modified: time.Now().UTC(),
|
||||
}
|
||||
|
||||
result, err := service.ApplyDelta(ctx, snap.ID, Delta{Changes: []Change{clientChange}})
|
||||
if err != nil {
|
||||
t.Fatalf("ApplyDelta() error = %v", err)
|
||||
}
|
||||
|
||||
if len(result.Conflicts) != 0 {
|
||||
t.Fatalf("expected no conflicts for different-file edits, got %#v", result.Conflicts)
|
||||
}
|
||||
if len(result.ServerDelta) != 1 {
|
||||
t.Fatalf("expected one server delta for guide.md, got %d", len(result.ServerDelta))
|
||||
}
|
||||
if result.ServerDelta[0].Path != "guide.md" {
|
||||
t.Fatalf("server delta path = %q, want guide.md", result.ServerDelta[0].Path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveConflictsPreservesServerContent(t *testing.T) {
|
||||
service, sourceDir := setupTestService(t)
|
||||
ctx := context.Background()
|
||||
|
||||
snap, err := service.InitSync(ctx, "device-1", "user:test")
|
||||
if err != nil {
|
||||
t.Fatalf("InitSync() error = %v", err)
|
||||
}
|
||||
|
||||
serverContent := "# Hello\n\nServer Update"
|
||||
if err := os.WriteFile(filepath.Join(sourceDir, "hello.md"), []byte(serverContent), 0o644); err != nil {
|
||||
t.Fatalf("update hello.md: %v", err)
|
||||
}
|
||||
|
||||
_, err = service.ResolveConflicts(ctx, snap.ID, []Resolution{{
|
||||
Path: "hello.md",
|
||||
Strategy: ResolutionServerWins,
|
||||
}})
|
||||
if err != nil {
|
||||
t.Fatalf("ResolveConflicts() error = %v", err)
|
||||
}
|
||||
|
||||
content, err := os.ReadFile(filepath.Join(sourceDir, "hello.md"))
|
||||
if err != nil {
|
||||
t.Fatalf("read hello.md: %v", err)
|
||||
}
|
||||
if string(content) != serverContent {
|
||||
t.Fatalf("resolved content = %q, want %q", string(content), serverContent)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveConflictsCreatesNewSnapshot(t *testing.T) {
|
||||
service, _ := setupTestService(t)
|
||||
ctx := context.Background()
|
||||
@@ -229,3 +299,47 @@ func TestGetContentReturnsFileBytes(t *testing.T) {
|
||||
t.Fatal("expected non-empty content")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSnapshotDeltaHandles100FilesUnderTarget(t *testing.T) {
|
||||
service, sourceDir := setupTestService(t)
|
||||
ctx := context.Background()
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
name := filepath.Join(sourceDir, fmt.Sprintf("note-%03d.md", i))
|
||||
content := fmt.Sprintf("# Note %03d\n\nDeterministic body %03d\n", i, i)
|
||||
if err := os.WriteFile(name, []byte(content), 0o644); err != nil {
|
||||
t.Fatalf("create %s: %v", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
snap, err := service.InitSync(ctx, "device-100", "user:test")
|
||||
if err != nil {
|
||||
t.Fatalf("InitSync() error = %v", err)
|
||||
}
|
||||
if elapsed := time.Since(start); elapsed > 10*time.Second {
|
||||
t.Fatalf("InitSync() took %s, want <= 10s", elapsed)
|
||||
}
|
||||
if len(snap.Files) != 102 {
|
||||
t.Fatalf("snapshot files = %d, want 102", len(snap.Files))
|
||||
}
|
||||
|
||||
if err := os.WriteFile(filepath.Join(sourceDir, "note-050.md"), []byte("# Note 050\n\nUpdated body\n"), 0o644); err != nil {
|
||||
t.Fatalf("update note-050.md: %v", err)
|
||||
}
|
||||
|
||||
start = time.Now()
|
||||
result, err := service.ApplyDelta(ctx, snap.ID, Delta{})
|
||||
if err != nil {
|
||||
t.Fatalf("ApplyDelta() error = %v", err)
|
||||
}
|
||||
if elapsed := time.Since(start); elapsed > 10*time.Second {
|
||||
t.Fatalf("ApplyDelta() took %s, want <= 10s", elapsed)
|
||||
}
|
||||
if len(result.ServerDelta) != 1 {
|
||||
t.Fatalf("server delta count = %d, want 1", len(result.ServerDelta))
|
||||
}
|
||||
if result.ServerDelta[0].Path != "note-050.md" {
|
||||
t.Fatalf("server delta path = %q, want note-050.md", result.ServerDelta[0].Path)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user