func TestManyPeers(t *testing.T) { log.Println("Cleaning...") err := removeAll("s1", "s2", "h1/index*", "h2/index*") if err != nil { t.Fatal(err) } log.Println("Generating files...") err = generateFiles("s1", 200, 20, "../LICENSE") if err != nil { t.Fatal(err) } receiver := startInstance(t, 2) defer checkedStop(t, receiver) bs, err := receiver.Get("/rest/system/config") if err != nil { t.Fatal(err) } var cfg config.Configuration if err := json.Unmarshal(bs, &cfg); err != nil { t.Fatal(err) } for len(cfg.Devices) < 100 { bs := make([]byte, 16) ReadRand(bs) id := protocol.NewDeviceID(bs) cfg.Devices = append(cfg.Devices, config.DeviceConfiguration{DeviceID: id}) cfg.Folders[0].Devices = append(cfg.Folders[0].Devices, config.FolderDeviceConfiguration{DeviceID: id}) } osutil.Rename("h2/config.xml", "h2/config.xml.orig") defer osutil.Rename("h2/config.xml.orig", "h2/config.xml") var buf bytes.Buffer json.NewEncoder(&buf).Encode(cfg) _, err = receiver.Post("/rest/system/config", &buf) if err != nil { t.Fatal(err) } sender := startInstance(t, 1) defer checkedStop(t, sender) rc.AwaitSync("default", sender, receiver) log.Println("Comparing directories...") err = compareDirectories("s1", "s2") if err != nil { t.Fatal(err) } }
func testSymlinks(t *testing.T) { log.Println("Cleaning...") err := removeAll("s1", "s2", "h1/index*", "h2/index*") if err != nil { t.Fatal(err) } log.Println("Generating files...") err = generateFiles("s1", 100, 20, "../LICENSE") if err != nil { t.Fatal(err) } // A file that we will replace with a symlink later fd, err := os.Create("s1/fileToReplace") if err != nil { t.Fatal(err) } fd.Close() // A directory that we will replace with a symlink later err = os.Mkdir("s1/dirToReplace", 0755) if err != nil { t.Fatal(err) } // A file and a symlink to that file fd, err = os.Create("s1/file") if err != nil { t.Fatal(err) } fd.Close() err = symlinks.Create("s1/fileLink", "file", 0) if err != nil { log.Fatal(err) } // A directory and a symlink to that directory err = os.Mkdir("s1/dir", 0755) if err != nil { t.Fatal(err) } err = symlinks.Create("s1/dirLink", "dir", 0) if err != nil { log.Fatal(err) } // A link to something in the repo that does not exist err = symlinks.Create("s1/noneLink", "does/not/exist", 0) if err != nil { log.Fatal(err) } // A link we will replace with a file later err = symlinks.Create("s1/repFileLink", "does/not/exist", 0) if err != nil { log.Fatal(err) } // A link we will replace with a directory later err = symlinks.Create("s1/repDirLink", "does/not/exist", 0) if err != nil { log.Fatal(err) } // A link we will remove later err = symlinks.Create("s1/removeLink", "does/not/exist", 0) if err != nil { log.Fatal(err) } // Verify that the files and symlinks sync to the other side sender := startInstance(t, 1) defer checkedStop(t, sender) receiver := startInstance(t, 2) defer checkedStop(t, receiver) log.Println("Syncing...") rc.AwaitSync("default", sender, receiver) log.Println("Comparing directories...") err = compareDirectories("s1", "s2") if err != nil { t.Fatal(err) } log.Println("Making some changes...") // Remove one symlink err = os.Remove("s1/fileLink") if err != nil { log.Fatal(err) } // Change the target of another err = os.Remove("s1/dirLink") if err != nil { log.Fatal(err) } err = symlinks.Create("s1/dirLink", "file", 0) if err != nil { log.Fatal(err) } // Replace one with a file err = os.Remove("s1/repFileLink") if err != nil { log.Fatal(err) } fd, err = os.Create("s1/repFileLink") if err != nil { log.Fatal(err) } fd.Close() // Replace one with a directory err = os.Remove("s1/repDirLink") if err != nil { log.Fatal(err) } err = os.Mkdir("s1/repDirLink", 0755) if err != nil { log.Fatal(err) } // Replace a file with a symlink err = os.Remove("s1/fileToReplace") if err != nil { log.Fatal(err) } err = symlinks.Create("s1/fileToReplace", "somewhere/non/existent", 0) if err != nil { log.Fatal(err) } // Replace a directory with a symlink err = os.RemoveAll("s1/dirToReplace") if err != nil { log.Fatal(err) } err = symlinks.Create("s1/dirToReplace", "somewhere/non/existent", 0) if err != nil { log.Fatal(err) } // Remove a broken symlink err = os.Remove("s1/removeLink") if err != nil { log.Fatal(err) } // Sync these changes and recheck log.Println("Syncing...") if err := sender.Rescan("default"); err != nil { t.Fatal(err) } rc.AwaitSync("default", sender, receiver) log.Println("Comparing directories...") err = compareDirectories("s1", "s2") if err != nil { t.Fatal(err) } }
func testFileTypeChange(t *testing.T) { log.Println("Cleaning...") err := removeAll("s1", "s2", "h1/index*", "h2/index*") if err != nil { t.Fatal(err) } log.Println("Generating files...") err = generateFiles("s1", 100, 20, "../LICENSE") if err != nil { t.Fatal(err) } // A file that we will replace with a directory later if fd, err := os.Create("s1/fileToReplace"); err != nil { t.Fatal(err) } else { fd.Close() } // A directory that we will replace with a file later err = os.Mkdir("s1/emptyDirToReplace", 0755) if err != nil { t.Fatal(err) } // A directory with files that we will replace with a file later err = os.Mkdir("s1/dirToReplace", 0755) if err != nil { t.Fatal(err) } if fd, err := os.Create("s1/dirToReplace/emptyFile"); err != nil { t.Fatal(err) } else { fd.Close() } // Verify that the files and directories sync to the other side sender := startInstance(t, 1) defer checkedStop(t, sender) receiver := startInstance(t, 2) defer checkedStop(t, receiver) log.Println("Syncing...") rc.AwaitSync("default", sender, receiver) // Delay scans for the moment if err := sender.RescanDelay("default", 86400); err != nil { t.Fatal(err) } log.Println("Comparing directories...") err = compareDirectories("s1", "s2") if err != nil { t.Fatal(err) } log.Println("Making some changes...") // Replace file with directory err = os.RemoveAll("s1/fileToReplace") if err != nil { t.Fatal(err) } err = os.Mkdir("s1/fileToReplace", 0755) if err != nil { t.Fatal(err) } // Replace empty directory with file err = os.RemoveAll("s1/emptyDirToReplace") if err != nil { t.Fatal(err) } if fd, err := os.Create("s1/emptyDirToReplace"); err != nil { t.Fatal(err) } else { fd.Close() } // Clear directory and replace with file err = os.RemoveAll("s1/dirToReplace") if err != nil { t.Fatal(err) } if fd, err := os.Create("s1/dirToReplace"); err != nil { t.Fatal(err) } else { fd.Close() } // Sync these changes and recheck log.Println("Syncing...") if err := sender.Rescan("default"); err != nil { t.Fatal(err) } rc.AwaitSync("default", sender, receiver) log.Println("Comparing directories...") err = compareDirectories("s1", "s2") if err != nil { t.Fatal(err) } }
func TestSyncSparseFile(t *testing.T) { // This test verifies that when syncing a file that consists mostly of // zeroes, those blocks are not transferred. It doesn't verify whether // the resulting file is actually *sparse* or not.alterFiles 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) } log.Println("Generating files...") if err := os.Mkdir("s1", 0755); err != nil { t.Fatal(err) } fd, err := os.Create("s1/testfile") if err != nil { t.Fatal(err) } if _, err := fd.Write([]byte("Start")); err != nil { t.Fatal(err) } kib := make([]byte, 1024) for i := 0; i < 8192; i++ { if _, err := fd.Write(kib); err != nil { t.Fatal(err) } } if _, err := fd.Write([]byte("End")); err != nil { t.Fatal(err) } fd.Close() // Start the syncers log.Println("Syncing...") p0 := startInstance(t, 1) defer checkedStop(t, p0) p1 := startInstance(t, 2) defer checkedStop(t, p1) rc.AwaitSync("default", p0, p1) log.Println("Comparing...") if err := compareDirectories("s1", "s2"); err != nil { t.Fatal(err) } conns, err := p0.Connections() if err != nil { t.Fatal(err) } tot := conns["total"] if tot.OutBytesTotal > 256<<10 { t.Fatal("Sending side has sent", tot.OutBytesTotal, "bytes, which is too much") } }
func TestOverride(t *testing.T) { // Enable "Master" on s1/default id, _ := protocol.DeviceIDFromString(id1) cfg, _ := config.Load("h1/config.xml", id) fld := cfg.Folders()["default"] fld.ReadOnly = true cfg.SetFolder(fld) os.Rename("h1/config.xml", "h1/config.xml.orig") defer osutil.Rename("h1/config.xml.orig", "h1/config.xml") cfg.Save() log.Println("Cleaning...") err := removeAll("s1", "s2", "h1/index*", "h2/index*") if err != nil { t.Fatal(err) } log.Println("Generating files...") err = generateFiles("s1", 100, 20, "../LICENSE") if err != nil { t.Fatal(err) } fd, err := os.Create("s1/testfile.txt") if err != nil { t.Fatal(err) } _, err = fd.WriteString("hello\n") if err != nil { t.Fatal(err) } err = fd.Close() if err != nil { t.Fatal(err) } expected, err := directoryContents("s1") if err != nil { t.Fatal(err) } master := startInstance(t, 1) defer checkedStop(t, master) slave := startInstance(t, 2) defer checkedStop(t, slave) log.Println("Syncing...") rc.AwaitSync("default", master, slave) log.Println("Verifying...") actual, err := directoryContents("s2") if err != nil { t.Fatal(err) } err = compareDirectoryContents(actual, expected) if err != nil { t.Fatal(err) } log.Println("Changing file on slave side...") fd, err = os.OpenFile("s2/testfile.txt", os.O_WRONLY|os.O_APPEND, 0644) if err != nil { t.Fatal(err) } _, err = fd.WriteString("text added to s2\n") if err != nil { t.Fatal(err) } err = fd.Close() if err != nil { t.Fatal(err) } if err := slave.Rescan("default"); err != nil { t.Fatal(err) } log.Println("Waiting for index to send...") time.Sleep(10 * time.Second) log.Println("Hitting Override on master...") if _, err := master.Post("/rest/db/override?folder=default", nil); err != nil { t.Fatal(err) } log.Println("Syncing...") rc.AwaitSync("default", master, slave) // Verify that the override worked fd, err = os.Open("s1/testfile.txt") if err != nil { t.Fatal(err) } bs, err := ioutil.ReadAll(fd) if err != nil { t.Fatal(err) } fd.Close() if strings.Contains(string(bs), "added to s2") { t.Error("Change should not have been synced to master") } fd, err = os.Open("s2/testfile.txt") if err != nil { t.Fatal(err) } bs, err = ioutil.ReadAll(fd) if err != nil { t.Fatal(err) } fd.Close() if strings.Contains(string(bs), "added to s2") { t.Error("Change should have been overridden on slave") } }
func TestSubScan(t *testing.T) { log.Println("Cleaning...") err := removeAll("s1", "s2", "h1/index*", "h2/index*") if err != nil { t.Fatal(err) } log.Println("Generating files...") err = generateFiles("s1", 10, 10, "../LICENSE") if err != nil { t.Fatal(err) } // 1. Scan a single file in a known directory "file1.txt" // 2. Scan a single file in an unknown directory "filetest/file1.txt" // 3. Scan a single file in a deep unknown directory "filetest/1/2/3/4/5/6/7/file1.txt" // 4. Scan a directory in a deep unknown directory "dirtest/1/2/3/4/5/6/7" // 5. Scan a deleted file in a known directory "filetest/file1.txt" // 6. Scan a deleted file in a deep unknown directory "rmdirtest/1/2/3/4/5/6/7" // 7. 'Accidentally' forget to scan 1 of the 2 files in a known directory // Verify that the files and directories sync to the other side sender := startInstance(t, 1) defer checkedStop(t, sender) receiver := startInstance(t, 2) defer checkedStop(t, receiver) log.Println("Syncing...") rc.AwaitSync("default", sender, receiver) // Delay scans for the moment if err := sender.RescanDelay("default", 86400); err != nil { t.Fatal(err) } log.Println("Comparing directories...") err = compareDirectories("s1", "s2") if err != nil { t.Fatal(err) } // 1 log.Println("Creating new file...") if fd, err := os.Create("s1/file1.txt"); err != nil { t.Fatal(err) } else { fd.Close() } if err := sender.RescanSub("default", "file1.txt", 86400); err != nil { t.Fatal(err) } log.Println("Syncing...") rc.AwaitSync("default", sender, receiver) log.Println("Comparing directories...") err = compareDirectories("s1", "s2") if err != nil { t.Fatal(err) } // 2 log.Println("Creating a file in an unknown directory") os.MkdirAll("s1/filetest", 0755) if fd, err := os.Create("s1/filetest/file1.txt"); err != nil { t.Fatal(err) } else { fd.Close() } if err := sender.RescanSub("default", "filetest/file1.txt", 86400); err != nil { t.Fatal(err) } log.Println("Syncing...") rc.AwaitSync("default", sender, receiver) log.Println("Comparing directories...") err = compareDirectories("s1", "s2") if err != nil { t.Fatal(err) } // 3 log.Println("Creating a file in an unknown deep directory") os.MkdirAll("s1/filetest/1/2/3/4/5/6/7", 0755) if fd, err := os.Create("s1/filetest/1/2/3/4/5/6/7/file1.txt"); err != nil { t.Fatal(err) } else { fd.Close() } if err := sender.RescanSub("default", "filetest/1/2/3/4/5/6/7/file1.txt", 86400); err != nil { t.Fatal(err) } log.Println("Syncing...") rc.AwaitSync("default", sender, receiver) log.Println("Comparing directories...") err = compareDirectories("s1", "s2") if err != nil { t.Fatal(err) } // 4 log.Println("Creating a directory in an unknown directory") err = os.MkdirAll("s1/dirtest/1/2/3/4/5/6/7", 0755) if err != nil { t.Fatal(err) } if err := sender.RescanSub("default", "dirtest/1/2/3/4/5/6/7", 86400); err != nil { t.Fatal(err) } log.Println("Syncing...") rc.AwaitSync("default", sender, receiver) log.Println("Comparing directories...") err = compareDirectories("s1", "s2") if err != nil { t.Fatal(err) } // 5 log.Println("Scan a deleted file in a known directory") if err := os.Remove("s1/filetest/file1.txt"); err != nil { t.Fatal(err) } if err := sender.RescanSub("default", "filetest/file1.txt", 86400); err != nil { t.Fatal(err) } log.Println("Syncing...") rc.AwaitSync("default", sender, receiver) log.Println("Comparing directories...") err = compareDirectories("s1", "s2") if err != nil { t.Fatal(err) } // 6 log.Println("Scan a deleted file in an unknown directory") if err := sender.RescanSub("default", "rmdirtest/1/2/3/4/5/6/7", 86400); err != nil { t.Fatal(err) } log.Println("Syncing...") rc.AwaitSync("default", sender, receiver) log.Println("Comparing directories...") err = compareDirectories("s1", "s2") if err != nil { t.Fatal(err) } // 7 log.Println("'Accidentally' forget to scan 1 of the 2 files") if fd, err := os.Create("s1/filetest/1/2/3/4/5/6/7/file2.txt"); err != nil { t.Fatal(err) } else { fd.Close() } if fd, err := os.Create("s1/filetest/1/2/3/4/5/6/7/file3.txt"); err != nil { t.Fatal(err) } else { fd.Close() } if err := sender.RescanSub("default", "filetest/1/2/3/4/5/6/7/file2.txt", 86400); err != nil { t.Fatal(err) } log.Println("Syncing...") rc.AwaitSync("default", sender, receiver) log.Println("Comparing directories...") err = compareDirectories("s1", "s2") if err == nil { t.Fatal("filetest/1/2/3/4/5/6/7/file3.txt should not be synced") } os.Remove("s1/filetest/1/2/3/4/5/6/7/file3.txt") err = compareDirectories("s1", "s2") if err != nil { t.Fatal(err) } }
func TestConflictsIndexReset(t *testing.T) { log.Println("Cleaning...") err := removeAll("s1", "s2", "h1/index*", "h2/index*") if err != nil { t.Fatal(err) } err = os.Mkdir("s1", 0755) if err != nil { t.Fatal(err) } err = os.Mkdir("s2", 0755) if err != nil { t.Fatal(err) } // Three files on s1 err = ioutil.WriteFile("s1/file1", []byte("hello\n"), 0644) if err != nil { t.Fatal(err) } err = ioutil.WriteFile("s1/file2", []byte("hello\n"), 0644) if err != nil { t.Fatal(err) } err = ioutil.WriteFile("s2/file3", []byte("hello\n"), 0644) if err != nil { t.Fatal(err) } // Let them sync sender := startInstance(t, 1) defer checkedStop(t, sender) receiver := startInstance(t, 2) defer checkedStop(t, receiver) log.Println("Syncing...") rc.AwaitSync("default", sender, receiver) log.Println("Verifying...") // s1 should have three files files, err := osutil.Glob("s1/file*") if err != nil { t.Fatal(err) } if len(files) != 3 { t.Errorf("Expected 3 files in s1 instead of %d", len(files)) } // s2 should have three files, err = osutil.Glob("s2/file*") if err != nil { t.Fatal(err) } if len(files) != 3 { t.Errorf("Expected 3 files in s2 instead of %d", len(files)) } log.Println("Updating...") // change s2/file2 a few times, so that it's version counter increases. // This will make the file on the cluster look newer than what we have // locally after we rest the index, unless we have a fix for that. for i := 0; i < 5; i++ { err = ioutil.WriteFile("s2/file2", []byte("hello1\n"), 0644) if err != nil { t.Fatal(err) } err = receiver.Rescan("default") if err != nil { t.Fatal(err) } time.Sleep(time.Second) } rc.AwaitSync("default", sender, receiver) // Now nuke the index log.Println("Resetting...") checkedStop(t, receiver) removeAll("h2/index*") // s1/file1 (remote) changes while receiver is down err = ioutil.WriteFile("s1/file1", []byte("goodbye\n"), 0644) if err != nil { t.Fatal(err) } // s1 must know about it err = sender.Rescan("default") if err != nil { t.Fatal(err) } // s2/file2 (local) changes while receiver is down err = ioutil.WriteFile("s2/file2", []byte("goodbye\n"), 0644) if err != nil { t.Fatal(err) } receiver = startInstance(t, 2) defer checkedStop(t, receiver) log.Println("Syncing...") rc.AwaitSync("default", sender, receiver) // s2 should have five files (three plus two conflicts) files, err = osutil.Glob("s2/file*") if err != nil { t.Fatal(err) } if len(files) != 5 { t.Errorf("Expected 5 files in s2 instead of %d", len(files)) } // file1 is in conflict, so there's two versions of that one files, err = osutil.Glob("s2/file1*") if err != nil { t.Fatal(err) } if len(files) != 2 { t.Errorf("Expected 2 'file1' files in s2 instead of %d", len(files)) } // file2 is in conflict, so there's two versions of that one files, err = osutil.Glob("s2/file2*") if err != nil { t.Fatal(err) } if len(files) != 2 { t.Errorf("Expected 2 'file2' files in s2 instead of %d", len(files)) } }
func TestConflictsDefault(t *testing.T) { log.Println("Cleaning...") err := removeAll("s1", "s2", "h1/index*", "h2/index*") if err != nil { t.Fatal(err) } log.Println("Generating files...") err = generateFiles("s1", 100, 20, "../LICENSE") if err != nil { t.Fatal(err) } fd, err := os.Create("s1/testfile.txt") if err != nil { t.Fatal(err) } _, err = fd.WriteString("hello\n") if err != nil { t.Fatal(err) } err = fd.Close() if err != nil { t.Fatal(err) } expected, err := directoryContents("s1") if err != nil { t.Fatal(err) } sender := startInstance(t, 1) defer checkedStop(t, sender) receiver := startInstance(t, 2) defer checkedStop(t, receiver) // Rescan with a delay on the next one, so we are not surprised by a // sudden rescan while we're trying to introduce conflicts. if err := sender.RescanDelay("default", 86400); err != nil { t.Fatal(err) } if err := receiver.RescanDelay("default", 86400); err != nil { t.Fatal(err) } rc.AwaitSync("default", sender, receiver) log.Println("Verifying...") actual, err := directoryContents("s2") if err != nil { t.Fatal(err) } err = compareDirectoryContents(actual, expected) if err != nil { t.Fatal(err) } log.Println("Introducing a conflict (simultaneous edit)...") if err := sender.PauseDevice(receiver.ID()); err != nil { t.Fatal(err) } fd, err = os.OpenFile("s1/testfile.txt", os.O_WRONLY|os.O_APPEND, 0644) if err != nil { t.Fatal(err) } _, err = fd.WriteString("text added to s1\n") if err != nil { t.Fatal(err) } err = fd.Close() if err != nil { t.Fatal(err) } fd, err = os.OpenFile("s2/testfile.txt", os.O_WRONLY|os.O_APPEND, 0644) if err != nil { t.Fatal(err) } _, err = fd.WriteString("text added to s2\n") if err != nil { t.Fatal(err) } err = fd.Close() if err != nil { t.Fatal(err) } if err := sender.ResumeDevice(receiver.ID()); err != nil { t.Fatal(err) } log.Println("Syncing...") if err := sender.RescanDelay("default", 86400); err != nil { t.Fatal(err) } if err := receiver.RescanDelay("default", 86400); err != nil { t.Fatal(err) } rc.AwaitSync("default", sender, receiver) // The conflict is expected on the s2 side due to how we calculate which // file is the winner (based on device ID) files, err := osutil.Glob("s2/*sync-conflict*") if err != nil { t.Fatal(err) } if len(files) != 1 { t.Errorf("Expected 1 conflicted files instead of %d", len(files)) } log.Println("Introducing a conflict (edit plus delete)...") if err := sender.PauseDevice(receiver.ID()); err != nil { t.Fatal(err) } err = os.Remove("s1/testfile.txt") if err != nil { t.Fatal(err) } fd, err = os.OpenFile("s2/testfile.txt", os.O_WRONLY|os.O_APPEND, 0644) if err != nil { t.Fatal(err) } _, err = fd.WriteString("more text added to s2\n") if err != nil { t.Fatal(err) } err = fd.Close() if err != nil { t.Fatal(err) } if err := sender.ResumeDevice(receiver.ID()); err != nil { t.Fatal(err) } log.Println("Syncing...") if err := sender.RescanDelay("default", 86400); err != nil { t.Fatal(err) } if err := receiver.RescanDelay("default", 86400); err != nil { t.Fatal(err) } rc.AwaitSync("default", sender, receiver) // The conflict is resolved to the advantage of the edit over the delete. // As such, we get the edited content synced back to s1 where it was // removed. files, err = osutil.Glob("s2/*sync-conflict*") if err != nil { t.Fatal(err) } if len(files) != 1 { t.Errorf("Expected 1 conflicted files instead of %d", len(files)) } bs, err := ioutil.ReadFile("s1/testfile.txt") if err != nil { t.Error("reading file:", err) } if !bytes.Contains(bs, []byte("more text added to s2")) { t.Error("s1/testfile.txt should contain data added in s2") } }
func TestConflictsInitialMerge(t *testing.T) { log.Println("Cleaning...") err := removeAll("s1", "s2", "h1/index*", "h2/index*") if err != nil { t.Fatal(err) } err = os.Mkdir("s1", 0755) if err != nil { t.Fatal(err) } err = os.Mkdir("s2", 0755) if err != nil { t.Fatal(err) } // File 1 is a conflict err = ioutil.WriteFile("s1/file1", []byte("hello\n"), 0644) if err != nil { t.Fatal(err) } err = ioutil.WriteFile("s2/file1", []byte("goodbye\n"), 0644) if err != nil { t.Fatal(err) } // File 2 exists on s1 only err = ioutil.WriteFile("s1/file2", []byte("hello\n"), 0644) if err != nil { t.Fatal(err) } // File 3 exists on s2 only err = ioutil.WriteFile("s2/file3", []byte("goodbye\n"), 0644) if err != nil { t.Fatal(err) } // Let them sync sender := startInstance(t, 1) defer checkedStop(t, sender) receiver := startInstance(t, 2) defer checkedStop(t, receiver) log.Println("Syncing...") rc.AwaitSync("default", sender, receiver) checkedStop(t, sender) checkedStop(t, receiver) log.Println("Verifying...") // s1 should have three-four files (there's a conflict from s2 which may or may not have synced yet) files, err := osutil.Glob("s1/file*") if err != nil { t.Fatal(err) } if len(files) < 3 || len(files) > 4 { t.Errorf("Expected 3-4 files in s1 instead of %d", len(files)) } // s2 should have four files (there's a conflict) files, err = osutil.Glob("s2/file*") if err != nil { t.Fatal(err) } if len(files) != 4 { t.Errorf("Expected 4 files in s2 instead of %d", len(files)) } // file1 is in conflict, so there's two versions of that one files, err = osutil.Glob("s2/file1*") if err != nil { t.Fatal(err) } if len(files) != 2 { t.Errorf("Expected 2 'file1' files in s2 instead of %d", len(files)) } }
func TestFolderWithoutRestart(t *testing.T) { log.Println("Cleaning...") err := removeAll("testfolder-p1", "testfolder-p4", "h1/index*", "h4/index*") if err != nil { t.Fatal(err) } defer removeAll("testfolder-p1", "testfolder-p4") if err := generateFiles("testfolder-p1", 50, 18, "../LICENSE"); err != nil { t.Fatal(err) } p1 := startInstance(t, 1) defer checkedStop(t, p1) p4 := startInstance(t, 4) defer checkedStop(t, p4) if ok, err := p1.ConfigInSync(); err != nil || !ok { t.Fatal("p1 should be in sync;", ok, err) } if ok, err := p4.ConfigInSync(); err != nil || !ok { t.Fatal("p4 should be in sync;", ok, err) } // Add a new folder to p1, shared with p4. Back up and restore the config // first. log.Println("Adding testfolder to p1...") os.Remove("h1/config.xml.orig") os.Rename("h1/config.xml", "h1/config.xml.orig") defer osutil.Rename("h1/config.xml.orig", "h1/config.xml") cfg, err := p1.GetConfig() if err != nil { t.Fatal(err) } newFolder := config.FolderConfiguration{ ID: "testfolder", RawPath: "testfolder-p1", RescanIntervalS: 86400, Copiers: 1, Hashers: 1, Pullers: 1, Devices: []config.FolderDeviceConfiguration{{DeviceID: p4.ID()}}, } newDevice := config.DeviceConfiguration{ DeviceID: p4.ID(), Name: "p4", Addresses: []string{"dynamic"}, Compression: protocol.CompressMetadata, } cfg.Folders = append(cfg.Folders, newFolder) cfg.Devices = append(cfg.Devices, newDevice) if err = p1.PostConfig(cfg); err != nil { t.Fatal(err) } // Add a new folder to p4, shared with p1. Back up and restore the config // first. log.Println("Adding testfolder to p4...") os.Remove("h4/config.xml.orig") os.Rename("h4/config.xml", "h4/config.xml.orig") defer osutil.Rename("h4/config.xml.orig", "h4/config.xml") cfg, err = p4.GetConfig() if err != nil { t.Fatal(err) } newFolder.RawPath = "testfolder-p4" newFolder.Devices = []config.FolderDeviceConfiguration{{DeviceID: p1.ID()}} newDevice.DeviceID = p1.ID() newDevice.Name = "p1" newDevice.Addresses = []string{"127.0.0.1:22001"} cfg.Folders = append(cfg.Folders, newFolder) cfg.Devices = append(cfg.Devices, newDevice) if err = p4.PostConfig(cfg); err != nil { t.Fatal(err) } // The change should not require a restart, so the config should be "in sync" if ok, err := p1.ConfigInSync(); err != nil || !ok { t.Fatal("p1 should be in sync;", ok, err) } if ok, err := p4.ConfigInSync(); err != nil || !ok { t.Fatal("p4 should be in sync;", ok, err) } // The folder should start and scan - wait for the event that signals this // has happened. log.Println("Waiting for testfolder to scan...") since := 0 outer: for { events, err := p4.Events(since) if err != nil { t.Fatal(err) } for _, event := range events { if event.Type == "StateChanged" { data := event.Data.(map[string]interface{}) folder := data["folder"].(string) from := data["from"].(string) to := data["to"].(string) if folder == "testfolder" && from == "scanning" && to == "idle" { break outer } } since = event.ID } } // It should sync to the other side successfully log.Println("Waiting for p1 and p4 to connect and sync...") rc.AwaitSync("testfolder", p1, p4) }
func TestAddDeviceWithoutRestart(t *testing.T) { log.Println("Cleaning...") err := removeAll("s1", "h1/index*", "s4", "h4/index*") if err != nil { t.Fatal(err) } log.Println("Generating files...") err = generateFiles("s1", 100, 18, "../LICENSE") if err != nil { t.Fatal(err) } p1 := startInstance(t, 1) defer checkedStop(t, p1) p4 := startInstance(t, 4) defer checkedStop(t, p4) if ok, err := p1.ConfigInSync(); err != nil || !ok { t.Fatal("p1 should be in sync;", ok, err) } if ok, err := p4.ConfigInSync(); err != nil || !ok { t.Fatal("p4 should be in sync;", ok, err) } // Add the p1 device to p4. Back up and restore p4's config first. log.Println("Adding p1 to p4...") os.Remove("h4/config.xml.orig") os.Rename("h4/config.xml", "h4/config.xml.orig") defer osutil.Rename("h4/config.xml.orig", "h4/config.xml") cfg, err := p4.GetConfig() if err != nil { t.Fatal(err) } devCfg := config.DeviceConfiguration{ DeviceID: p1.ID(), Name: "s1", Addresses: []string{"127.0.0.1:22001"}, Compression: protocol.CompressMetadata, } cfg.Devices = append(cfg.Devices, devCfg) cfg.Folders[0].Devices = append(cfg.Folders[0].Devices, config.FolderDeviceConfiguration{DeviceID: p1.ID()}) if err = p4.PostConfig(cfg); err != nil { t.Fatal(err) } // The change should not require a restart, so the config should be "in sync" if ok, err := p4.ConfigInSync(); err != nil || !ok { t.Fatal("p4 should be in sync;", ok, err) } // Wait for the devices to connect and sync. log.Println("Waiting for p1 and p4 to connect and sync...") rc.AwaitSync("default", p1, p4) }