diff --git a/test/http_test.go b/test/http_test.go index 8030a761..2704db63 100644 --- a/test/http_test.go +++ b/test/http_test.go @@ -78,6 +78,7 @@ func TestGetIndexAuth(t *testing.T) { argv: []string{"-home", "h1"}, port: 8081, instance: "1", + apiKey: "abc123", } err := st.start() if err != nil { diff --git a/test/ignore_test.go b/test/ignore_test.go index 41a6d6b1..37c96a3f 100644 --- a/test/ignore_test.go +++ b/test/ignore_test.go @@ -42,16 +42,11 @@ func TestIgnores(t *testing.T) { // startup, UPnP etc complete and make sure that we've performed folder // error checking which creates the folder path if it's missing. for i := 0; i < 20; i++ { - resp, err := p.post("/rest/scan?folder=default", nil) + err := p.rescan("default") if err != nil { time.Sleep(time.Second) continue } - if resp.StatusCode != 200 { - resp.Body.Close() - time.Sleep(time.Second) - continue - } break } @@ -93,16 +88,11 @@ func TestIgnores(t *testing.T) { // Wait for one scan to succeed, or up to 20 seconds... // This is to let startup, UPnP etc complete. for i := 0; i < 20; i++ { - resp, err := p.post("/rest/scan?folder=default", nil) + err := p.rescan("default") if err != nil { time.Sleep(time.Second) continue } - if resp.StatusCode != 200 { - resp.Body.Close() - time.Sleep(time.Second) - continue - } break } @@ -132,7 +122,7 @@ func TestIgnores(t *testing.T) { // Rescan and verify that we see them - p.post("/rest/scan?folder=default", nil) + p.rescan("default") m, err = p.model("default") if err != nil { t.Fatal(err) @@ -159,7 +149,7 @@ func TestIgnores(t *testing.T) { // Rescan and verify that we see them - p.post("/rest/scan?folder=default", nil) + p.rescan("default") m, err = p.model("default") if err != nil { t.Fatal(err) diff --git a/test/parallell_scan_test.go b/test/parallell_scan_test.go index f20140b6..5c4d1fae 100644 --- a/test/parallell_scan_test.go +++ b/test/parallell_scan_test.go @@ -50,16 +50,11 @@ func TestParallellScan(t *testing.T) { // Wait for one scan to succeed, or up to 20 seconds... // This is to let startup, UPnP etc complete. for i := 0; i < 20; i++ { - resp, err := st.post("/rest/scan?folder=default", nil) + err := st.rescan("default") if err != nil { time.Sleep(time.Second) continue } - if resp.StatusCode != 200 { - resp.Body.Close() - time.Sleep(time.Second) - continue - } break } @@ -73,16 +68,12 @@ func TestParallellScan(t *testing.T) { wg.Add(1) go func() { defer wg.Done() - resp, err := st.post("/rest/scan?folder=default", nil) + err := st.rescan("default") log.Println(j) if err != nil { log.Println(err) t.Fatal(err) } - if resp.StatusCode != 200 { - t.Fatalf("%d != 200", resp.StatusCode) - } - resp.Body.Close() }() } diff --git a/test/reconnect_test.go b/test/reconnect_test.go index ca9a63cb..f4c834c5 100644 --- a/test/reconnect_test.go +++ b/test/reconnect_test.go @@ -38,7 +38,7 @@ func testRestartDuringTransfer(t *testing.T, restartSender, restartReceiver bool } log.Println("Generating files...") - err = generateFiles("s1", 1000, 22, "../LICENSE") + err = generateFiles("s1", 250, 20, "../LICENSE") if err != nil { t.Fatal(err) } @@ -138,7 +138,7 @@ func testRestartDuringTransfer(t *testing.T, restartSender, restartReceiver bool prevComp = curComp } - time.Sleep(250 * time.Millisecond) + time.Sleep(time.Second) } err = sender.stop() diff --git a/test/sync_test.go b/test/sync_test.go index 45b6c153..a37ee856 100644 --- a/test/sync_test.go +++ b/test/sync_test.go @@ -61,16 +61,20 @@ func TestSyncClusterStaggeredVersioning(t *testing.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 + // between all and stored in s1, s2 and s3 respectively. + // + // Another folder is shared between 1 and 2 only, in s12-1 and s12-2. A + // third folders is shared between 2 and 3, in s23-2 and s23-3. - This tests syncing files back and forth between three cluster members. - Their configs are in h1, h2 and h3. The folder "default" is shared - between all and stored in s1, s2 and s3 respectively. + const ( + numFiles = 100 + fileSizeExp = 20 + iterations = 3 + ) + log.Printf("Testing with numFiles=%d, fileSizeExp=%d, iterations=%d", numFiles, fileSizeExp, iterations) - Another folder is shared between 1 and 2 only, in s12-1 and s12-2. A - third folders is shared between 2 and 3, in s23-2 and s23-3. - - */ log.Println("Cleaning...") err := removeAll("s1", "s12-1", "s2", "s12-2", "s23-2", @@ -86,11 +90,11 @@ func testSyncCluster(t *testing.T) { log.Println("Generating files...") - err = generateFiles("s1", 1000, 21, "../LICENSE") + err = generateFiles("s1", numFiles, fileSizeExp, "../LICENSE") if err != nil { t.Fatal(err) } - err = generateFiles("s12-1", 1000, 21, "../LICENSE") + err = generateFiles("s12-1", numFiles, fileSizeExp, "../LICENSE") if err != nil { t.Fatal(err) } @@ -109,16 +113,16 @@ func testSyncCluster(t *testing.T) { t.Fatal(err) } - err = generateFiles("s2", 1000, 21, "../LICENSE") + err = generateFiles("s2", numFiles, fileSizeExp, "../LICENSE") if err != nil { t.Fatal(err) } - err = generateFiles("s23-2", 1000, 21, "../LICENSE") + err = generateFiles("s23-2", numFiles, fileSizeExp, "../LICENSE") if err != nil { t.Fatal(err) } - err = generateFiles("s3", 1000, 21, "../LICENSE") + err = generateFiles("s3", numFiles, fileSizeExp, "../LICENSE") if err != nil { t.Fatal(err) } @@ -158,17 +162,37 @@ func testSyncCluster(t *testing.T) { } }() - for count := 0; count < 5; count++ { + log.Println("Waiting for startup...") + // Wait for one scan to succeed, or up to 20 seconds... + // This is to let startup, UPnP etc complete. + for _, device := range p { + for i := 0; i < 20; i++ { + err := device.rescan("default") + if err != nil { + time.Sleep(time.Second) + continue + } + break + } + } + + for count := 0; count < iterations; count++ { log.Println("Forcing rescan...") // Force rescan of folders - for i := range p { - p[i].post("/rest/scan?folder=default", nil) - if i < 3 { - p[i].post("/rest/scan?folder=s12", nil) + for i, device := range p { + if err := device.rescan("default"); err != nil { + t.Fatal(err) + } + if i < 2 { + if err := device.rescan("s12"); err != nil { + t.Fatal(err) + } } if i > 1 { - p[i].post("/rest/scan?folder=s23", nil) + if err := device.rescan("s23"); err != nil { + t.Fatal(err) + } } } @@ -284,38 +308,23 @@ func scStartProcesses() ([]syncthingProcess, error) { } func scSyncAndCompare(p []syncthingProcess, expected [][]fileInfo) error { - ids := []string{id1, id2, id3} - log.Println("Syncing...") -mainLoop: for { - time.Sleep(2500 * time.Millisecond) + time.Sleep(2 * time.Second) - for i := range p { - comp, err := p[i].peerCompletion() - if err != nil { - if isTimeout(err) { - continue mainLoop - } - return err - } - - for id, pct := range comp { - if id == ids[i] { - // Don't check for self, which will be 0% - continue - } - if pct != 100 { - log.Printf("%s not done yet: %d%%", id, pct) - continue mainLoop - } - } + if err := allDevicesInSync(p); err != nil { + log.Println(err) + continue } break } + // This is necessary, or all files won't be in place even when everything + // is already reported in sync. Why?! + time.Sleep(5 * time.Second) + log.Println("Checking...") for _, dir := range []string{"s1", "s2", "s3"} { diff --git a/test/syncthingprocess.go b/test/syncthingprocess.go index ce6df3d4..f97ad104 100644 --- a/test/syncthingprocess.go +++ b/test/syncthingprocess.go @@ -15,10 +15,14 @@ import ( "errors" "fmt" "io" + "io/ioutil" + "log" "net/http" "os" "os/exec" "time" + + "github.com/syncthing/protocol" ) var env = []string{ @@ -34,6 +38,7 @@ type syncthingProcess struct { apiKey string csrfToken string lastEvent int + id protocol.DeviceID cmd *exec.Cmd logfd *os.File @@ -72,12 +77,32 @@ func (p *syncthingProcess) start() error { p.cmd = cmd for { - resp, err := p.get("/") - if err == nil { - resp.Body.Close() - return nil - } time.Sleep(250 * time.Millisecond) + + resp, err := p.get("/rest/system") + if err != nil { + continue + } + + var sysData map[string]interface{} + err = json.NewDecoder(resp.Body).Decode(&sysData) + resp.Body.Close() + if err != nil { + // This one is unexpected. Print it. + log.Println("/rest/system (JSON):", err) + continue + } + + id, err := protocol.DeviceIDFromString(sysData["myID"].(string)) + if err != nil { + // This one is unexpected. Print it. + log.Println("/rest/system (myID):", err) + continue + } + + p.id = id + + return nil } } @@ -173,9 +198,31 @@ func (p *syncthingProcess) peerCompletion() (map[string]int, error) { comp := map[string]int{} err = json.NewDecoder(resp.Body).Decode(&comp) + + // Remove ourselves from the set. In the remaining map, all peers should + // be att 100% if we're in sync. + for id := range comp { + if id == p.id.String() { + delete(comp, id) + } + } + return comp, err } +func (p *syncthingProcess) allPeersInSync() error { + comp, err := p.peerCompletion() + if err != nil { + return err + } + for id, val := range comp { + if val != 100 { + return fmt.Errorf("%.7s at %d%%", id, val) + } + } + return nil +} + type model struct { GlobalBytes int GlobalDeleted int @@ -249,3 +296,25 @@ func (p *syncthingProcess) version() (string, error) { } return v.Version, nil } + +func (p *syncthingProcess) rescan(folder string) error { + resp, err := p.post("/rest/scan?folder="+folder, nil) + if err != nil { + return err + } + data, _ := ioutil.ReadAll(resp.Body) + resp.Body.Close() + if resp.StatusCode != 200 { + return fmt.Errorf("Rescan %q: status code %d: %s", folder, resp.StatusCode, data) + } + return nil +} + +func allDevicesInSync(p []syncthingProcess) error { + for _, device := range p { + if err := device.allPeersInSync(); err != nil { + return fmt.Errorf("%.7s: %v", device.id.String(), err) + } + } + return nil +}