From 1e915a2903ed10c8d60e85b68bf496ac8a14649e Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Tue, 21 Oct 2014 07:37:38 +0200 Subject: [PATCH] Add test for syncing with 100 configured devices --- test/common_test.go | 28 ++++++++- test/manypeers_test.go | 125 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 test/manypeers_test.go diff --git a/test/common_test.go b/test/common_test.go index 7ef59b8e4..c93b203ff 100644 --- a/test/common_test.go +++ b/test/common_test.go @@ -44,7 +44,7 @@ const ( var env = []string{ "HOME=.", - "STTRACE=model", + "STTRACE=model,protocol", "STGUIAPIKEY=" + apiKey, "STNORESTART=1", "STPERFSTATS=1", @@ -121,6 +121,32 @@ func (p *syncthingProcess) get(path string) (*http.Response, error) { return resp, nil } +func (p *syncthingProcess) post(path string, data io.Reader) (*http.Response, error) { + client := &http.Client{ + Timeout: 2 * time.Second, + Transport: &http.Transport{ + DisableKeepAlives: true, + }, + } + req, err := http.NewRequest("POST", fmt.Sprintf("http://127.0.0.1:%d%s", p.port, path), data) + if err != nil { + return nil, err + } + if p.apiKey != "" { + req.Header.Add("X-API-Key", p.apiKey) + } + if p.csrfToken != "" { + req.Header.Add("X-CSRF-Token", p.csrfToken) + } + req.Header.Add("Content-Type", "application/json") + + resp, err := client.Do(req) + if err != nil { + return nil, err + } + return resp, nil +} + func (p *syncthingProcess) peerCompletion() (map[string]int, error) { resp, err := p.get("/rest/debug/peerCompletion") if err != nil { diff --git a/test/manypeers_test.go b/test/manypeers_test.go new file mode 100644 index 000000000..7474de7a2 --- /dev/null +++ b/test/manypeers_test.go @@ -0,0 +1,125 @@ +// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file). +// +// This program is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. If not, see . + +// +build integration + +package integration_test + +import ( + "bytes" + "encoding/json" + "log" + "strings" + "testing" + "time" + + "github.com/syncthing/syncthing/internal/config" + "github.com/syncthing/syncthing/internal/osutil" + "github.com/syncthing/syncthing/internal/protocol" +) + +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, "../bin/syncthing") + if err != nil { + t.Fatal(err) + } + + receiver := syncthingProcess{ // id2 + log: "2.out", + argv: []string{"-home", "h2"}, + port: 8082, + apiKey: apiKey, + } + err = receiver.start() + if err != nil { + t.Fatal(err) + } + defer receiver.stop() + + resp, err := receiver.get("/rest/config") + if err != nil { + t.Fatal(err) + } + if resp.StatusCode != 200 { + t.Fatalf("Code %d != 200", resp.StatusCode) + } + + var cfg config.Configuration + json.NewDecoder(resp.Body).Decode(&cfg) + resp.Body.Close() + + 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) + resp, err = receiver.post("/rest/config", &buf) + if err != nil { + t.Fatal(err) + } + if resp.StatusCode != 200 { + t.Fatalf("Code %d != 200", resp.StatusCode) + } + resp.Body.Close() + + log.Println("Starting up...") + sender := syncthingProcess{ // id1 + log: "1.out", + argv: []string{"-home", "h1"}, + port: 8081, + apiKey: apiKey, + } + err = sender.start() + if err != nil { + t.Fatal(err) + } + defer sender.stop() + + for { + comp, err := sender.peerCompletion() + if err != nil { + if strings.Contains(err.Error(), "use of closed network connection") { + time.Sleep(250 * time.Millisecond) + continue + } + t.Fatal(err) + } + if comp[id2] == 100 { + return + } + time.Sleep(2 * time.Second) + } + + log.Println("Comparing directories...") + err = compareDirectories("s1", "s2") + if err != nil { + t.Fatal(err) + } +}