diff --git a/test/override_test.go b/test/override_test.go index 9af544e3f..150147fe2 100644 --- a/test/override_test.go +++ b/test/override_test.go @@ -193,6 +193,317 @@ func TestOverride(t *testing.T) { } } +func TestOverrideIgnores(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 os.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", 10, 2, "../LICENSE") + if err != nil { + t.Fatal(err) + } + + fd, err := os.Create("s1/testfile.txt") + if err != nil { + t.Fatal(err) + } + _, err = fd.WriteString("original text\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) + } + + log.Println("Starting master...") + master := syncthingProcess{ // id1 + instance: "1", + argv: []string{"-home", "h1"}, + port: 8081, + apiKey: apiKey, + } + err = master.start() + if err != nil { + t.Fatal(err) + } + defer master.stop() + + // Wait for one scan to succeed, or up to 20 seconds... This is to let + // startup, UPnP etc complete and make sure the master has the full index + // before they connect. + for i := 0; i < 20; i++ { + err := master.rescan("default") + if err != nil { + time.Sleep(time.Second) + continue + } + break + } + + log.Println("Starting slave...") + slave := syncthingProcess{ // id2 + instance: "2", + argv: []string{"-home", "h2"}, + port: 8082, + apiKey: apiKey, + } + err = slave.start() + if err != nil { + master.stop() + t.Fatal(err) + } + defer slave.stop() + + log.Println("Syncing...") + + if err = ovCompletion(100, master, slave); err != nil { + t.Fatal(err) + } + + 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("Ignoring testfile.txt on master...") + + fd, err = os.Create("s1/.stignore") + if err != nil { + t.Fatal(err) + } + _, err = fd.WriteString("testfile.txt\n") + if err != nil { + t.Fatal(err) + } + err = fd.Close() + if err != nil { + t.Fatal(err) + } + + log.Println("Modify testfile.txt on master...") + + fd, err = os.Create("s1/testfile.txt") + if err != nil { + t.Fatal(err) + } + _, err = fd.WriteString("updated on master but ignored\n") + if err != nil { + t.Fatal(err) + } + err = fd.Close() + if err != nil { + t.Fatal(err) + } + + fd, err = os.Create("s1/testfile2.txt") + if err != nil { + t.Fatal(err) + } + _, err = fd.WriteString("sync me\n") + if err != nil { + t.Fatal(err) + } + err = fd.Close() + if err != nil { + t.Fatal(err) + } + + err = master.rescan("default") + + log.Println("Syncing...") + + // Expect 100% completion since the change should be invisible to the master side + if err = ovCompletion(100, master, slave); err != nil { + t.Fatal(err) + } + + // Verify that sync worked + + 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), "original text") { + t.Error("Changes should not have been synced to slave") + } + + fd, err = os.Open("s2/testfile2.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), "sync me") { + t.Error("Changes should have been synced to slave") + } + + log.Println("Removing file on slave side...") + + os.Remove("s2/testfile.txt") + + err = slave.rescan("default") + if err != nil { + t.Fatal(err) + } + + log.Println("Syncing...") + + // Expect 100% completion since the change should be invisible to the master side + if err = ovCompletion(100, master, slave); err != nil { + t.Fatal(err) + } + + // Verify that nothing changed + + 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), "updated on master but ignored") { + t.Error("Changes should not have been synced to master") + } + + fd, err = os.Open("s2/testfile.txt") + if err == nil { + t.Error("File should not exist on the slave") + } + + log.Println("Creating file on slave...") + + fd, err = os.Create("s2/testfile3.txt") + if err != nil { + t.Fatal(err) + } + _, err = fd.WriteString("created on slave, should be removed on override\n") + if err != nil { + t.Fatal(err) + } + err = fd.Close() + if err != nil { + t.Fatal(err) + } + + log.Println("Hitting Override on master...") + + resp, err := master.post("/rest/db/override?folder=default", nil) + if err != nil { + t.Fatal(err) + } + if resp.StatusCode != 200 { + t.Fatal(resp.Status) + } + + log.Println("Syncing...") + + // Expect ~99% completion since the change will be rejected by the master side + if err = ovCompletion(99, master, slave); err != nil { + t.Fatal(err) + } + + fd, err = os.Open("s2/testfile.txt") + if err == nil { + t.Error("File should not exist on the slave") + } + fd, err = os.Open("s2/testfile2.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), "sync me") { + t.Error("Changes should have been synced to slave") + } + fd, err = os.Open("s2/testfile3.txt") + if err != nil { + t.Error("File should still exist on the slave") + } + fd.Close() + + log.Println("Hitting Override on master (again)...") + + resp, err = master.post("/rest/db/override?folder=default", nil) + if err != nil { + t.Fatal(err) + } + if resp.StatusCode != 200 { + t.Fatal(resp.Status) + } + + log.Println("Syncing...") + + // Expect ~99% completion since the change will be rejected by the master side + if err = ovCompletion(99, master, slave); err != nil { + t.Fatal(err) + } + + fd, err = os.Open("s2/testfile.txt") + if err == nil { + t.Error("File should not exist on the slave") + } + fd, err = os.Open("s2/testfile2.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), "sync me") { + t.Error("Changes should have been synced to slave") + } + fd, err = os.Open("s2/testfile3.txt") + if err != nil { + t.Error("File should still exist on the slave") + } + fd.Close() + +} + func ovCompletion(expected int, p ...syncthingProcess) error { mainLoop: for {