integration_test.go (4017B)
1 package main 2 3 import ( 4 "os" 5 "path/filepath" 6 "testing" 7 "time" 8 9 "github.com/louloulibs/esync/internal/config" 10 "github.com/louloulibs/esync/internal/syncer" 11 "github.com/louloulibs/esync/internal/watcher" 12 ) 13 14 // TestLocalSyncIntegration verifies that the Syncer can rsync files between 15 // two local directories. This test requires rsync to be installed. 16 func TestLocalSyncIntegration(t *testing.T) { 17 // Ensure rsync is available 18 if _, err := os.Stat("/usr/bin/rsync"); err != nil { 19 if _, err2 := os.Stat("/opt/homebrew/bin/rsync"); err2 != nil { 20 t.Skip("rsync not found, skipping integration test") 21 } 22 } 23 24 // 1. Create two temp dirs (src, dst) 25 src := t.TempDir() 26 dst := t.TempDir() 27 28 // 2. Write a test file to src 29 testContent := "hello from integration test\n" 30 testFile := filepath.Join(src, "testfile.txt") 31 if err := os.WriteFile(testFile, []byte(testContent), 0644); err != nil { 32 t.Fatalf("failed to write test file: %v", err) 33 } 34 35 // 3. Create a Config pointing src -> dst with archive=true, progress=true 36 cfg := &config.Config{ 37 Sync: config.SyncSection{ 38 Local: src, 39 Remote: dst, 40 }, 41 Settings: config.Settings{ 42 Rsync: config.RsyncSettings{ 43 Archive: true, 44 Progress: true, 45 }, 46 }, 47 } 48 49 // 4. Create a Syncer, run it 50 s := syncer.New(cfg) 51 result, err := s.Run() 52 53 // 5. Verify: no error, result.Success is true 54 if err != nil { 55 t.Fatalf("syncer.Run() returned error: %v", err) 56 } 57 if !result.Success { 58 t.Fatalf("expected result.Success=true, got false; error: %s", result.ErrorMessage) 59 } 60 61 // 6. Verify: the file exists in dst with correct contents 62 dstFile := filepath.Join(dst, "testfile.txt") 63 got, err := os.ReadFile(dstFile) 64 if err != nil { 65 t.Fatalf("failed to read synced file %s: %v", dstFile, err) 66 } 67 if string(got) != testContent { 68 t.Errorf("synced file content mismatch:\n got: %q\n want: %q", string(got), testContent) 69 } 70 } 71 72 // TestWatcherTriggersSync verifies that the watcher detects a new file and 73 // triggers a sync from src to dst. This test requires rsync to be installed. 74 func TestWatcherTriggersSync(t *testing.T) { 75 // Ensure rsync is available 76 if _, err := os.Stat("/usr/bin/rsync"); err != nil { 77 if _, err2 := os.Stat("/opt/homebrew/bin/rsync"); err2 != nil { 78 t.Skip("rsync not found, skipping integration test") 79 } 80 } 81 82 // 1. Create two temp dirs (src, dst) 83 src := t.TempDir() 84 dst := t.TempDir() 85 86 // 2. Create Config and Syncer 87 cfg := &config.Config{ 88 Sync: config.SyncSection{ 89 Local: src, 90 Remote: dst, 91 }, 92 Settings: config.Settings{ 93 Rsync: config.RsyncSettings{ 94 Archive: true, 95 Progress: true, 96 }, 97 }, 98 } 99 s := syncer.New(cfg) 100 101 // 3. Create watcher with handler that runs syncer and signals a channel 102 synced := make(chan struct{}, 1) 103 handler := func() { 104 _, _ = s.Run() 105 select { 106 case synced <- struct{}{}: 107 default: 108 } 109 } 110 111 // Use short debounce (100ms) for fast tests 112 w, err := watcher.New(src, 100, nil, nil, handler) 113 if err != nil { 114 t.Fatalf("watcher.New() failed: %v", err) 115 } 116 117 // 4. Start watcher 118 if err := w.Start(); err != nil { 119 t.Fatalf("watcher.Start() failed: %v", err) 120 } 121 defer w.Stop() 122 123 // 5. Wait 200ms for watcher to settle 124 time.Sleep(200 * time.Millisecond) 125 126 // 6. Write a file to src 127 testContent := "watcher triggered sync\n" 128 testFile := filepath.Join(src, "watched.txt") 129 if err := os.WriteFile(testFile, []byte(testContent), 0644); err != nil { 130 t.Fatalf("failed to write test file: %v", err) 131 } 132 133 // 7. Wait for signal (with 5s timeout) 134 select { 135 case <-synced: 136 // success - sync was triggered 137 case <-time.After(5 * time.Second): 138 t.Fatal("timed out waiting for watcher to trigger sync") 139 } 140 141 // 8. Verify: file was synced to dst with correct contents 142 dstFile := filepath.Join(dst, "watched.txt") 143 got, err := os.ReadFile(dstFile) 144 if err != nil { 145 t.Fatalf("failed to read synced file %s: %v", dstFile, err) 146 } 147 if string(got) != testContent { 148 t.Errorf("synced file content mismatch:\n got: %q\n want: %q", string(got), testContent) 149 } 150 }