func loadConfig() (*config.Wrapper, error) { cfgFile := locations[locConfigFile] cfg, err := config.Load(cfgFile, myID) if err != nil { l.Infoln("Error loading config file; using defaults for now") myName, _ := os.Hostname() newCfg := defaultConfig(myName) cfg = config.Wrap(cfgFile, newCfg) } return cfg, err }
func TestShortIDCheck(t *testing.T) { cfg := config.Wrap("/tmp/test", config.Configuration{ Devices: []config.DeviceConfiguration{ {DeviceID: protocol.DeviceID{8, 16, 24, 32, 40, 48, 56, 0, 0}}, {DeviceID: protocol.DeviceID{8, 16, 24, 32, 40, 48, 56, 1, 1}}, // first 56 bits same, differ in the first 64 bits }, }) if err := checkShortIDs(cfg); err != nil { t.Error("Unexpected error:", err) } cfg = config.Wrap("/tmp/test", config.Configuration{ Devices: []config.DeviceConfiguration{ {DeviceID: protocol.DeviceID{8, 16, 24, 32, 40, 48, 56, 64, 0}}, {DeviceID: protocol.DeviceID{8, 16, 24, 32, 40, 48, 56, 64, 1}}, // first 64 bits same }, }) if err := checkShortIDs(cfg); err == nil { t.Error("Should have gotten an error") } }
func init() { device1, _ = protocol.DeviceIDFromString("AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR") device2, _ = protocol.DeviceIDFromString("GYRZZQB-IRNPV4Z-T7TC52W-EQYJ3TT-FDQW6MW-DFLMU42-SSSU6EM-FBK2VAY") defaultFolderConfig = config.NewFolderConfiguration("default", "testdata") defaultFolderConfig.Devices = []config.FolderDeviceConfiguration{{DeviceID: device1}} _defaultConfig := config.Configuration{ Folders: []config.FolderConfiguration{defaultFolderConfig}, Devices: []config.DeviceConfiguration{config.NewDeviceConfiguration(device1, "device1")}, Options: config.OptionsConfiguration{ // Don't remove temporaries directly on startup KeepTemporariesH: 1, }, } defaultConfig = config.Wrap("/tmp/test", _defaultConfig) }
func TestProgressEmitter(t *testing.T) { w := events.Default.Subscribe(events.DownloadProgress) c := config.Wrap("/tmp/test", config.Configuration{}) c.SetOptions(config.OptionsConfiguration{ ProgressUpdateIntervalS: 0, }) p := NewProgressEmitter(c) go p.Serve() expectTimeout(w, t) s := sharedPullerState{ mut: sync.NewMutex(), } p.Register(&s) expectEvent(w, t, 1) expectTimeout(w, t) s.copyDone() expectEvent(w, t, 1) expectTimeout(w, t) s.copiedFromOrigin() expectEvent(w, t, 1) expectTimeout(w, t) s.pullStarted() expectEvent(w, t, 1) expectTimeout(w, t) s.pullDone() expectEvent(w, t, 1) expectTimeout(w, t) p.Deregister(&s) expectEvent(w, t, 0) expectTimeout(w, t) }
func TestStopAfterBrokenConfig(t *testing.T) { baseDirs["config"] = "../../test/h1" // to load HTTPS keys expandLocations() cfg := config.Configuration{ GUI: config.GUIConfiguration{ RawAddress: "127.0.0.1:0", RawUseTLS: false, }, } w := config.Wrap("/dev/null", cfg) srv, err := newAPIService(protocol.LocalDeviceID, w, "", nil, nil, nil, nil, nil, nil) if err != nil { t.Fatal(err) } srv.started = make(chan struct{}) sup := suture.NewSimple("test") sup.Add(srv) sup.ServeBackground() <-srv.started // Service is now running, listening on a random port on localhost. Now we // request a config change to a completely invalid listen address. The // commit will fail and the service will be in a broken state. newCfg := config.Configuration{ GUI: config.GUIConfiguration{ RawAddress: "totally not a valid address", RawUseTLS: false, }, } if srv.CommitConfiguration(cfg, newCfg) { t.Fatal("Config commit should have failed") } // Nonetheless, it should be fine to Stop() it without panic. sup.Stop() }
func generate(generateDir string) { dir, err := osutil.ExpandTilde(generateDir) if err != nil { l.Fatalln("generate:", err) } ensureDir(dir, 0700) certFile, keyFile := filepath.Join(dir, "cert.pem"), filepath.Join(dir, "key.pem") cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err == nil { l.Warnln("Key exists; will not overwrite.") l.Infoln("Device ID:", protocol.NewDeviceID(cert.Certificate[0])) } else { cert, err = tlsutil.NewCertificate(certFile, keyFile, tlsDefaultCommonName, bepRSABits) if err != nil { l.Fatalln("Create certificate:", err) } myID = protocol.NewDeviceID(cert.Certificate[0]) if err != nil { l.Fatalln("Load certificate:", err) } if err == nil { l.Infoln("Device ID:", protocol.NewDeviceID(cert.Certificate[0])) } } cfgFile := filepath.Join(dir, "config.xml") if _, err := os.Stat(cfgFile); err == nil { l.Warnln("Config exists; will not overwrite.") return } var myName, _ = os.Hostname() var newCfg = defaultConfig(myName) var cfg = config.Wrap(cfgFile, newCfg) err = cfg.Save() if err != nil { l.Warnln("Failed to save config", err) } }
func TestFolderErrors(t *testing.T) { // This test intentionally avoids starting the folders. If they are // started, they will perform an initial scan, which will create missing // folder markers and race with the stuff we do in the test. fcfg := config.FolderConfiguration{ ID: "folder", RawPath: "testdata/testfolder", } cfg := config.Wrap("/tmp/test", config.Configuration{ Folders: []config.FolderConfiguration{fcfg}, }) for _, file := range []string{".stfolder", "testfolder/.stfolder", "testfolder"} { if err := os.Remove("testdata/" + file); err != nil && !os.IsNotExist(err) { t.Fatal(err) } } ldb := db.OpenMemory() // Case 1 - new folder, directory and marker created m := model.NewModel(cfg, protocol.LocalDeviceID, "device", "syncthing", "dev", ldb, nil) m.AddFolder(fcfg) if err := m.CheckFolderHealth("folder"); err != nil { t.Error("Unexpected error", cfg.Folders()["folder"].Invalid) } s, err := os.Stat("testdata/testfolder") if err != nil || !s.IsDir() { t.Error(err) } _, err = os.Stat("testdata/testfolder/.stfolder") if err != nil { t.Error(err) } if err := os.Remove("testdata/testfolder/.stfolder"); err != nil { t.Fatal(err) } if err := os.Remove("testdata/testfolder/"); err != nil { t.Fatal(err) } // Case 2 - new folder, marker created fcfg.RawPath = "testdata/" cfg = config.Wrap("/tmp/test", config.Configuration{ Folders: []config.FolderConfiguration{fcfg}, }) m = model.NewModel(cfg, protocol.LocalDeviceID, "device", "syncthing", "dev", ldb, nil) m.AddFolder(fcfg) if err := m.CheckFolderHealth("folder"); err != nil { t.Error("Unexpected error", cfg.Folders()["folder"].Invalid) } _, err = os.Stat("testdata/.stfolder") if err != nil { t.Error(err) } if err := os.Remove("testdata/.stfolder"); err != nil { t.Fatal(err) } // Case 3 - Folder marker missing set := db.NewFileSet("folder", ldb) set.Update(protocol.LocalDeviceID, []protocol.FileInfo{ {Name: "dummyfile"}, }) m = model.NewModel(cfg, protocol.LocalDeviceID, "device", "syncthing", "dev", ldb, nil) m.AddFolder(fcfg) if err := m.CheckFolderHealth("folder"); err == nil || err.Error() != "folder marker missing" { t.Error("Incorrect error: Folder marker missing !=", m.CheckFolderHealth("folder")) } // Case 3.1 - recover after folder marker missing if err = fcfg.CreateMarker(); err != nil { t.Error(err) } if err := m.CheckFolderHealth("folder"); err != nil { t.Error("Unexpected error", cfg.Folders()["folder"].Invalid) } // Case 4 - Folder path missing if err := os.Remove("testdata/testfolder/.stfolder"); err != nil && !os.IsNotExist(err) { t.Fatal(err) } if err := os.Remove("testdata/testfolder"); err != nil && !os.IsNotExist(err) { t.Fatal(err) } fcfg.RawPath = "testdata/testfolder" cfg = config.Wrap("testdata/subfolder", config.Configuration{ Folders: []config.FolderConfiguration{fcfg}, }) m = model.NewModel(cfg, protocol.LocalDeviceID, "device", "syncthing", "dev", ldb, nil) m.AddFolder(fcfg) if err := m.CheckFolderHealth("folder"); err == nil || err.Error() != "folder path missing" { t.Error("Incorrect error: Folder path missing !=", m.CheckFolderHealth("folder")) } // Case 4.1 - recover after folder path missing if err := os.Mkdir("testdata/testfolder", 0700); err != nil { t.Fatal(err) } if err := m.CheckFolderHealth("folder"); err == nil || err.Error() != "folder marker missing" { t.Error("Incorrect error: Folder marker missing !=", m.CheckFolderHealth("folder")) } // Case 4.2 - recover after missing marker if err = fcfg.CreateMarker(); err != nil { t.Error(err) } if err := m.CheckFolderHealth("folder"); err != nil { t.Error("Unexpected error", cfg.Folders()["folder"].Invalid) } }
func TestRWScanRecovery(t *testing.T) { ldb := db.OpenMemory() set := db.NewFileSet("default", ldb) set.Update(protocol.LocalDeviceID, []protocol.FileInfo{ {Name: "dummyfile"}, }) fcfg := config.FolderConfiguration{ ID: "default", RawPath: "testdata/rwtestfolder", RescanIntervalS: 1, } cfg := config.Wrap("/tmp/test", config.Configuration{ Folders: []config.FolderConfiguration{fcfg}, Devices: []config.DeviceConfiguration{ { DeviceID: device1, }, }, }) os.RemoveAll(fcfg.RawPath) m := NewModel(cfg, protocol.LocalDeviceID, "device", "syncthing", "dev", ldb, nil) m.AddFolder(fcfg) m.StartFolderRW("default") m.ServeBackground() waitFor := func(status string) error { timeout := time.Now().Add(2 * time.Second) for { if time.Now().After(timeout) { return fmt.Errorf("Timed out waiting for status: %s, current status: %s", status, m.cfg.Folders()["default"].Invalid) } _, _, err := m.State("default") if err == nil && status == "" { return nil } if err != nil && err.Error() == status { return nil } time.Sleep(10 * time.Millisecond) } } if err := waitFor("folder path missing"); err != nil { t.Error(err) return } os.Mkdir(fcfg.RawPath, 0700) if err := waitFor("folder marker missing"); err != nil { t.Error(err) return } fd, err := os.Create(filepath.Join(fcfg.RawPath, ".stfolder")) if err != nil { t.Error(err) return } fd.Close() if err := waitFor(""); err != nil { t.Error(err) return } os.Remove(filepath.Join(fcfg.RawPath, ".stfolder")) if err := waitFor("folder marker missing"); err != nil { t.Error(err) return } os.Remove(fcfg.RawPath) if err := waitFor("folder path missing"); err != nil { t.Error(err) return } }
func TestClusterConfig(t *testing.T) { cfg := config.New(device1) cfg.Devices = []config.DeviceConfiguration{ { DeviceID: device1, Introducer: true, }, { DeviceID: device2, }, } cfg.Folders = []config.FolderConfiguration{ { ID: "folder1", Devices: []config.FolderDeviceConfiguration{ {DeviceID: device1}, {DeviceID: device2}, }, }, { ID: "folder2", Devices: []config.FolderDeviceConfiguration{ {DeviceID: device1}, {DeviceID: device2}, }, }, } db := db.OpenMemory() m := NewModel(config.Wrap("/tmp/test", cfg), protocol.LocalDeviceID, "device", "syncthing", "dev", db, nil) m.AddFolder(cfg.Folders[0]) m.AddFolder(cfg.Folders[1]) m.ServeBackground() cm := m.generateClusterConfig(device2) if l := len(cm.Folders); l != 2 { t.Fatalf("Incorrect number of folders %d != 2", l) } r := cm.Folders[0] if r.ID != "folder1" { t.Errorf("Incorrect folder %q != folder1", r.ID) } if l := len(r.Devices); l != 2 { t.Errorf("Incorrect number of devices %d != 2", l) } if id := r.Devices[0].ID; bytes.Compare(id, device1[:]) != 0 { t.Errorf("Incorrect device ID %x != %x", id, device1) } if r.Devices[0].Flags&protocol.FlagIntroducer == 0 { t.Error("Device1 should be flagged as Introducer") } if id := r.Devices[1].ID; bytes.Compare(id, device2[:]) != 0 { t.Errorf("Incorrect device ID %x != %x", id, device2) } if r.Devices[1].Flags&protocol.FlagIntroducer != 0 { t.Error("Device2 should not be flagged as Introducer") } r = cm.Folders[1] if r.ID != "folder2" { t.Errorf("Incorrect folder %q != folder2", r.ID) } if l := len(r.Devices); l != 2 { t.Errorf("Incorrect number of devices %d != 2", l) } if id := r.Devices[0].ID; bytes.Compare(id, device1[:]) != 0 { t.Errorf("Incorrect device ID %x != %x", id, device1) } if r.Devices[0].Flags&protocol.FlagIntroducer == 0 { t.Error("Device1 should be flagged as Introducer") } if id := r.Devices[1].ID; bytes.Compare(id, device2[:]) != 0 { t.Errorf("Incorrect device ID %x != %x", id, device2) } if r.Devices[1].Flags&protocol.FlagIntroducer != 0 { t.Error("Device2 should not be flagged as Introducer") } }
func TestDeviceRename(t *testing.T) { ccm := protocol.ClusterConfigMessage{ ClientName: "syncthing", ClientVersion: "v0.9.4", } defer os.Remove("tmpconfig.xml") rawCfg := config.New(device1) rawCfg.Devices = []config.DeviceConfiguration{ { DeviceID: device1, }, } cfg := config.Wrap("tmpconfig.xml", rawCfg) db := db.OpenMemory() m := NewModel(cfg, protocol.LocalDeviceID, "device", "syncthing", "dev", db, nil) fc := FakeConnection{ id: device1, requestData: []byte("some data to return"), } m.AddConnection(Connection{ &net.TCPConn{}, fc, ConnectionTypeDirectAccept, }) m.ServeBackground() if cfg.Devices()[device1].Name != "" { t.Errorf("Device already has a name") } m.ClusterConfig(device1, ccm) if cfg.Devices()[device1].Name != "" { t.Errorf("Device already has a name") } ccm.DeviceName = "tester" m.ClusterConfig(device1, ccm) if cfg.Devices()[device1].Name != "tester" { t.Errorf("Device did not get a name") } ccm.DeviceName = "tester2" m.ClusterConfig(device1, ccm) if cfg.Devices()[device1].Name != "tester" { t.Errorf("Device name got overwritten") } cfgw, err := config.Load("tmpconfig.xml", protocol.LocalDeviceID) if err != nil { t.Error(err) return } if cfgw.Devices()[device1].Name != "tester" { t.Errorf("Device name not saved in config") } }