diff --git a/test/common_test.go b/test/common_test.go index 75cc8aca9..0132fa276 100644 --- a/test/common_test.go +++ b/test/common_test.go @@ -8,14 +8,12 @@ package integration_test import ( "crypto/md5" - "crypto/rand" "encoding/json" "errors" "fmt" "io" - "io/ioutil" "log" - mr "math/rand" + "math/rand" "net/http" "os" "os/exec" @@ -23,6 +21,10 @@ import ( "time" ) +func init() { + rand.Seed(42) +} + const ( id1 = "I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU" id2 = "JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU" @@ -34,6 +36,7 @@ var env = []string{ "STTRACE=model", "STGUIAPIKEY=" + apiKey, "STNORESTART=1", + "STPERFSTATS=1", } type syncthingProcess struct { @@ -42,6 +45,7 @@ type syncthingProcess struct { port int apiKey string csrfToken string + lastEvent int cmd *exec.Cmd logfd *os.File @@ -114,17 +118,46 @@ func (p *syncthingProcess) peerCompletion() (map[string]int, error) { return comp, err } +type event struct { + ID int + Time time.Time + Type string + Data interface{} +} + +func (p *syncthingProcess) events() ([]event, error) { + resp, err := p.get(fmt.Sprintf("/rest/events?since=%d", p.lastEvent)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var evs []event + err = json.NewDecoder(resp.Body).Decode(&evs) + if err != nil { + return nil, err + } + p.lastEvent = evs[len(evs)-1].ID + return evs, err +} + +type versionResp struct { + Version string +} + func (p *syncthingProcess) version() (string, error) { resp, err := p.get("/rest/version") if err != nil { return "", err } - bs, err := ioutil.ReadAll(resp.Body) - resp.Body.Close() + defer resp.Body.Close() + + var v versionResp + err = json.NewDecoder(resp.Body).Decode(&v) if err != nil { return "", err } - return string(bs), nil + return v.Version, nil } type fileGenerator struct { @@ -147,12 +180,12 @@ func generateFiles(dir string, files, maxexp int, srcname string) error { log.Fatal(err) } - s := 1 << uint(mr.Intn(maxexp)) + s := 1 << uint(rand.Intn(maxexp)) a := 128 * 1024 if a > s { a = s } - s += mr.Intn(a) + s += rand.Intn(a) src := io.LimitReader(&inifiteReader{fd}, int64(s)) @@ -172,12 +205,12 @@ func generateFiles(dir string, files, maxexp int, srcname string) error { return err } - err = os.Chmod(p1, os.FileMode(mr.Intn(0777)|0400)) + err = os.Chmod(p1, os.FileMode(rand.Intn(0777)|0400)) if err != nil { return err } - t := time.Now().Add(-time.Duration(mr.Intn(30*86400)) * time.Second) + t := time.Now().Add(-time.Duration(rand.Intn(30*86400)) * time.Second) err = os.Chtimes(p1, t, t) if err != nil { return err @@ -187,9 +220,20 @@ func generateFiles(dir string, files, maxexp int, srcname string) error { return nil } +func ReadRand(bs []byte) (int, error) { + var r uint32 + for i := range bs { + if i%4 == 0 { + r = uint32(rand.Int63()) + } + bs[i] = byte(r >> uint((i%4)*8)) + } + return len(bs), nil +} + func randomName() string { var b [16]byte - rand.Reader.Read(b[:]) + ReadRand(b[:]) return fmt.Sprintf("%x", b[:]) } diff --git a/test/genfiles.go b/test/genfiles.go index b1b3fa47b..e30d48d9d 100644 --- a/test/genfiles.go +++ b/test/genfiles.go @@ -7,20 +7,34 @@ package main import ( - "crypto/rand" "flag" "fmt" "io" "log" - mr "math/rand" + "math/rand" "os" "path/filepath" "time" ) +func init() { + rand.Seed(42) +} + +func ReadRand(bs []byte) (int, error) { + var r uint32 + for i := range bs { + if i%4 == 0 { + r = uint32(rand.Int63()) + } + bs[i] = byte(r >> uint((i%4)*8)) + } + return len(bs), nil +} + func name() string { var b [16]byte - rand.Reader.Read(b[:]) + ReadRand(b[:]) return fmt.Sprintf("%x", b[:]) } @@ -47,12 +61,12 @@ func main() { log.Fatal(err) } - s := 1 << uint(mr.Intn(maxexp)) + s := 1 << uint(rand.Intn(maxexp)) a := 128 * 1024 if a > s { a = s } - s += mr.Intn(a) + s += rand.Intn(a) src := io.LimitReader(&inifiteReader{fd}, int64(s)) @@ -72,12 +86,12 @@ func main() { log.Fatal(err) } - err = os.Chmod(p1, os.FileMode(mr.Intn(0777)|0400)) + err = os.Chmod(p1, os.FileMode(rand.Intn(0777)|0400)) if err != nil { log.Fatal(err) } - t := time.Now().Add(-time.Duration(mr.Intn(30*86400)) * time.Second) + t := time.Now().Add(-time.Duration(rand.Intn(30*86400)) * time.Second) err = os.Chtimes(p1, t, t) if err != nil { log.Fatal(err) diff --git a/test/h1/config.xml b/test/h1/config.xml index 96bce685f..bd06639cb 100644 --- a/test/h1/config.xml +++ b/test/h1/config.xml @@ -36,8 +36,8 @@ 21025 [ff32::5222]:21026 16 - 0 - 0 + 50000 + 50000 5 false true diff --git a/test/transfer-bench_test.go b/test/transfer-bench_test.go new file mode 100644 index 000000000..fbee825cd --- /dev/null +++ b/test/transfer-bench_test.go @@ -0,0 +1,90 @@ +// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file). +// All rights reserved. Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build integration + +package integration_test + +import ( + "log" + "strings" + "testing" + "time" +) + +func TestBenchmarkTransfer(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", 10000, 22, "../bin/syncthing") + if err != nil { + t.Fatal(err) + } + + log.Println("Starting up...") + sender := syncthingProcess{ // id1 + log: "1.out", + argv: []string{"-home", "h1"}, + port: 8081, + apiKey: apiKey, + } + ver, err := sender.start() + if err != nil { + t.Fatal(err) + } + log.Println(ver) + + receiver := syncthingProcess{ // id2 + log: "2.out", + argv: []string{"-home", "h2"}, + port: 8082, + apiKey: apiKey, + } + ver, err = receiver.start() + if err != nil { + sender.stop() + t.Fatal(err) + } + log.Println(ver) + + var t0 time.Time +loop: + for { + evs, err := receiver.events() + if err != nil { + if strings.Contains(err.Error(), "use of closed network connection") { + log.Println("...") + continue + } + sender.stop() + receiver.stop() + t.Fatal(err) + } + + for _, ev := range evs { + if ev.Type == "StateChanged" { + data := ev.Data.(map[string]interface{}) + if data["repo"].(string) != "default" { + continue + } + log.Println(ev) + if data["to"].(string) == "syncing" { + t0 = ev.Time + continue + } + if t0 != (time.Time{}) && data["to"].(string) == "idle" { + log.Println("Sync took", ev.Time.Sub(t0)) + break loop + } + } + } + } + + sender.stop() + receiver.stop() +}