mirror of
https://github.com/octoleo/syncthing.git
synced 2025-01-03 07:12:27 +00:00
Refactor and improve integration tests
This commit is contained in:
parent
6459d11d32
commit
a3cf37cb2e
@ -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 {
|
||||||
|
@ -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)
|
||||||
|
@ -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()
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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"} {
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user