|
|
@@ -10,6 +10,7 @@ package integration
|
|
|
|
|
|
import (
|
|
|
"fmt"
|
|
|
+ "io/ioutil"
|
|
|
"log"
|
|
|
"math/rand"
|
|
|
"os"
|
|
|
@@ -82,6 +83,18 @@ func TestSyncClusterStaggeredVersioning(t *testing.T) {
|
|
|
testSyncCluster(t)
|
|
|
}
|
|
|
|
|
|
+func TestSyncClusterForcedRescan(t *testing.T) {
|
|
|
+ // Use no versioning
|
|
|
+ id, _ := protocol.DeviceIDFromString(id2)
|
|
|
+ cfg, _ := config.Load("h2/config.xml", id)
|
|
|
+ fld := cfg.Folders()["default"]
|
|
|
+ fld.Versioning = config.VersioningConfiguration{}
|
|
|
+ cfg.SetFolder(fld)
|
|
|
+ cfg.Save()
|
|
|
+
|
|
|
+ testSyncClusterForcedRescan(t)
|
|
|
+}
|
|
|
+
|
|
|
func testSyncCluster(t *testing.T) {
|
|
|
// This tests syncing files back and forth between three cluster members.
|
|
|
// Their configs are in h1, h2 and h3. The folder "default" is shared
|
|
|
@@ -287,6 +300,116 @@ func testSyncCluster(t *testing.T) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+func testSyncClusterForcedRescan(t *testing.T) {
|
|
|
+ // During this test, we create 1K files, remove and then create them
|
|
|
+ // again. However, during these operations we will perform scan operations
|
|
|
+ // such that other nodes will retrieve these options while data is
|
|
|
+ // changing.
|
|
|
+
|
|
|
+ // When -short is passed, keep it more reasonable.
|
|
|
+ timeLimit := longTimeLimit
|
|
|
+ if testing.Short() {
|
|
|
+ timeLimit = shortTimeLimit
|
|
|
+ }
|
|
|
+
|
|
|
+ log.Println("Cleaning...")
|
|
|
+ err := removeAll("s1", "s12-1",
|
|
|
+ "s2", "s12-2", "s23-2",
|
|
|
+ "s3", "s23-3",
|
|
|
+ "h1/index*", "h2/index*", "h3/index*")
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create initial folder contents. All three devices have stuff in
|
|
|
+ // "default", which should be merged. The other two folders are initially
|
|
|
+ // empty on one side.
|
|
|
+
|
|
|
+ log.Println("Generating files...")
|
|
|
+ if err := os.MkdirAll("s1/test-stable-files", 0755); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ for i := 0; i < 1000; i++ {
|
|
|
+ name := fmt.Sprintf("s1/test-stable-files/%d", i)
|
|
|
+ if err := ioutil.WriteFile(name, []byte(time.Now().Format(time.RFC3339Nano)), 0644); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Prepare the expected state of folders after the sync
|
|
|
+ expected, err := directoryContents("s1")
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // Start the syncers
|
|
|
+ p0 := startInstance(t, 1)
|
|
|
+ defer checkedStop(t, p0)
|
|
|
+ p1 := startInstance(t, 2)
|
|
|
+ defer checkedStop(t, p1)
|
|
|
+ p2 := startInstance(t, 3)
|
|
|
+ defer checkedStop(t, p2)
|
|
|
+
|
|
|
+ p := []*rc.Process{p0, p1, p2}
|
|
|
+
|
|
|
+ start := time.Now()
|
|
|
+ for time.Since(start) < timeLimit {
|
|
|
+ rescan := func() {
|
|
|
+ for i := range p {
|
|
|
+ if err := p[i].Rescan("default"); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ log.Println("Forcing rescan...")
|
|
|
+ rescan()
|
|
|
+
|
|
|
+ // Sync stuff and verify it looks right
|
|
|
+ err = scSyncAndCompare(p, [][]fileInfo{expected})
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ log.Println("Altering...")
|
|
|
+
|
|
|
+ // Delete and recreate stable files while scanners and pullers are active
|
|
|
+ for i := 0; i < 1000; i++ {
|
|
|
+ name := fmt.Sprintf("s1/test-stable-files/%d", i)
|
|
|
+ if err := os.Remove(name); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ if rand.Intn(10) == 0 {
|
|
|
+ rescan()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ rescan()
|
|
|
+
|
|
|
+ time.Sleep(50 * time.Millisecond)
|
|
|
+ for i := 0; i < 1000; i++ {
|
|
|
+ name := fmt.Sprintf("s1/test-stable-files/%d", i)
|
|
|
+ if err := ioutil.WriteFile(name, []byte(time.Now().Format(time.RFC3339Nano)), 0644); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ if rand.Intn(10) == 0 {
|
|
|
+ rescan()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ rescan()
|
|
|
+
|
|
|
+ // Prepare the expected state of folders after the sync
|
|
|
+ expected, err = directoryContents("s1")
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ if len(expected) != 1001 {
|
|
|
+ t.Fatal("s1 does not have 1001 files;", len(expected))
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func scSyncAndCompare(p []*rc.Process, expected [][]fileInfo) error {
|
|
|
log.Println("Syncing...")
|
|
|
|