Refactor and improve integration tests

This commit is contained in:
Jakob Borg 2015-04-01 10:43:19 +02:00
parent 6459d11d32
commit a3cf37cb2e
6 changed files with 134 additions and 74 deletions

View File

@ -78,6 +78,7 @@ func TestGetIndexAuth(t *testing.T) {
argv: []string{"-home", "h1"}, argv: []string{"-home", "h1"},
port: 8081, port: 8081,
instance: "1", instance: "1",
apiKey: "abc123",
} }
err := st.start() err := st.start()
if err != nil { if err != nil {

View File

@ -42,16 +42,11 @@ func TestIgnores(t *testing.T) {
// startup, UPnP etc complete and make sure that we've performed folder // startup, UPnP etc complete and make sure that we've performed folder
// error checking which creates the folder path if it's missing. // error checking which creates the folder path if it's missing.
for i := 0; i < 20; i++ { for i := 0; i < 20; i++ {
resp, err := p.post("/rest/scan?folder=default", nil) err := p.rescan("default")
if err != nil { if err != nil {
time.Sleep(time.Second) time.Sleep(time.Second)
continue continue
} }
if resp.StatusCode != 200 {
resp.Body.Close()
time.Sleep(time.Second)
continue
}
break break
} }
@ -93,16 +88,11 @@ func TestIgnores(t *testing.T) {
// Wait for one scan to succeed, or up to 20 seconds... // Wait for one scan to succeed, or up to 20 seconds...
// This is to let startup, UPnP etc complete. // This is to let startup, UPnP etc complete.
for i := 0; i < 20; i++ { for i := 0; i < 20; i++ {
resp, err := p.post("/rest/scan?folder=default", nil) err := p.rescan("default")
if err != nil { if err != nil {
time.Sleep(time.Second) time.Sleep(time.Second)
continue continue
} }
if resp.StatusCode != 200 {
resp.Body.Close()
time.Sleep(time.Second)
continue
}
break break
} }
@ -132,7 +122,7 @@ func TestIgnores(t *testing.T) {
// Rescan and verify that we see them // Rescan and verify that we see them
p.post("/rest/scan?folder=default", nil) p.rescan("default")
m, err = p.model("default") m, err = p.model("default")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -159,7 +149,7 @@ func TestIgnores(t *testing.T) {
// Rescan and verify that we see them // Rescan and verify that we see them
p.post("/rest/scan?folder=default", nil) p.rescan("default")
m, err = p.model("default") m, err = p.model("default")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View File

@ -50,16 +50,11 @@ func TestParallellScan(t *testing.T) {
// Wait for one scan to succeed, or up to 20 seconds... // Wait for one scan to succeed, or up to 20 seconds...
// This is to let startup, UPnP etc complete. // This is to let startup, UPnP etc complete.
for i := 0; i < 20; i++ { for i := 0; i < 20; i++ {
resp, err := st.post("/rest/scan?folder=default", nil) err := st.rescan("default")
if err != nil { if err != nil {
time.Sleep(time.Second) time.Sleep(time.Second)
continue continue
} }
if resp.StatusCode != 200 {
resp.Body.Close()
time.Sleep(time.Second)
continue
}
break break
} }
@ -73,16 +68,12 @@ func TestParallellScan(t *testing.T) {
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
resp, err := st.post("/rest/scan?folder=default", nil) err := st.rescan("default")
log.Println(j) log.Println(j)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
t.Fatal(err) t.Fatal(err)
} }
if resp.StatusCode != 200 {
t.Fatalf("%d != 200", resp.StatusCode)
}
resp.Body.Close()
}() }()
} }

View File

@ -38,7 +38,7 @@ func testRestartDuringTransfer(t *testing.T, restartSender, restartReceiver bool
} }
log.Println("Generating files...") log.Println("Generating files...")
err = generateFiles("s1", 1000, 22, "../LICENSE") err = generateFiles("s1", 250, 20, "../LICENSE")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -138,7 +138,7 @@ func testRestartDuringTransfer(t *testing.T, restartSender, restartReceiver bool
prevComp = curComp prevComp = curComp
} }
time.Sleep(250 * time.Millisecond) time.Sleep(time.Second)
} }
err = sender.stop() err = sender.stop()

View File

@ -61,16 +61,20 @@ func TestSyncClusterStaggeredVersioning(t *testing.T) {
} }
func testSyncCluster(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. const (
Their configs are in h1, h2 and h3. The folder "default" is shared numFiles = 100
between all and stored in s1, s2 and s3 respectively. 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...") log.Println("Cleaning...")
err := removeAll("s1", "s12-1", err := removeAll("s1", "s12-1",
"s2", "s12-2", "s23-2", "s2", "s12-2", "s23-2",
@ -86,11 +90,11 @@ func testSyncCluster(t *testing.T) {
log.Println("Generating files...") log.Println("Generating files...")
err = generateFiles("s1", 1000, 21, "../LICENSE") err = generateFiles("s1", numFiles, fileSizeExp, "../LICENSE")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = generateFiles("s12-1", 1000, 21, "../LICENSE") err = generateFiles("s12-1", numFiles, fileSizeExp, "../LICENSE")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -109,16 +113,16 @@ func testSyncCluster(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
err = generateFiles("s2", 1000, 21, "../LICENSE") err = generateFiles("s2", numFiles, fileSizeExp, "../LICENSE")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = generateFiles("s23-2", 1000, 21, "../LICENSE") err = generateFiles("s23-2", numFiles, fileSizeExp, "../LICENSE")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = generateFiles("s3", 1000, 21, "../LICENSE") err = generateFiles("s3", numFiles, fileSizeExp, "../LICENSE")
if err != nil { if err != nil {
t.Fatal(err) 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...") log.Println("Forcing rescan...")
// Force rescan of folders // Force rescan of folders
for i := range p { for i, device := range p {
p[i].post("/rest/scan?folder=default", nil) if err := device.rescan("default"); err != nil {
if i < 3 { t.Fatal(err)
p[i].post("/rest/scan?folder=s12", nil) }
if i < 2 {
if err := device.rescan("s12"); err != nil {
t.Fatal(err)
}
} }
if i > 1 { 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 { func scSyncAndCompare(p []syncthingProcess, expected [][]fileInfo) error {
ids := []string{id1, id2, id3}
log.Println("Syncing...") log.Println("Syncing...")
mainLoop:
for { for {
time.Sleep(2500 * time.Millisecond) time.Sleep(2 * time.Second)
for i := range p { if err := allDevicesInSync(p); err != nil {
comp, err := p[i].peerCompletion() log.Println(err)
if err != nil { continue
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
}
}
} }
break 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...") log.Println("Checking...")
for _, dir := range []string{"s1", "s2", "s3"} { for _, dir := range []string{"s1", "s2", "s3"} {

View File

@ -15,10 +15,14 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"log"
"net/http" "net/http"
"os" "os"
"os/exec" "os/exec"
"time" "time"
"github.com/syncthing/protocol"
) )
var env = []string{ var env = []string{
@ -34,6 +38,7 @@ type syncthingProcess struct {
apiKey string apiKey string
csrfToken string csrfToken string
lastEvent int lastEvent int
id protocol.DeviceID
cmd *exec.Cmd cmd *exec.Cmd
logfd *os.File logfd *os.File
@ -72,12 +77,32 @@ func (p *syncthingProcess) start() error {
p.cmd = cmd p.cmd = cmd
for { for {
resp, err := p.get("/")
if err == nil {
resp.Body.Close()
return nil
}
time.Sleep(250 * time.Millisecond) 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{} comp := map[string]int{}
err = json.NewDecoder(resp.Body).Decode(&comp) 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 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 { type model struct {
GlobalBytes int GlobalBytes int
GlobalDeleted int GlobalDeleted int
@ -249,3 +296,25 @@ func (p *syncthingProcess) version() (string, error) {
} }
return v.Version, nil 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
}