config_test.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. // Copyright (C) 2014 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package config
  7. import (
  8. "bytes"
  9. "encoding/json"
  10. "fmt"
  11. "os"
  12. "path/filepath"
  13. "reflect"
  14. "runtime"
  15. "sort"
  16. "strings"
  17. "testing"
  18. "github.com/d4l3k/messagediff"
  19. "github.com/syncthing/syncthing/lib/fs"
  20. "github.com/syncthing/syncthing/lib/protocol"
  21. )
  22. var device1, device2, device3, device4 protocol.DeviceID
  23. func init() {
  24. device1, _ = protocol.DeviceIDFromString("AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ")
  25. device2, _ = protocol.DeviceIDFromString("GYRZZQB-IRNPV4Z-T7TC52W-EQYJ3TT-FDQW6MW-DFLMU42-SSSU6EM-FBK2VAY")
  26. device3, _ = protocol.DeviceIDFromString("LGFPDIT-7SKNNJL-VJZA4FC-7QNCRKA-CE753K7-2BW5QDK-2FOZ7FR-FEP57QJ")
  27. device4, _ = protocol.DeviceIDFromString("P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2")
  28. }
  29. func TestDefaultValues(t *testing.T) {
  30. expected := OptionsConfiguration{
  31. ListenAddresses: []string{"default"},
  32. GlobalAnnServers: []string{"default"},
  33. GlobalAnnEnabled: true,
  34. LocalAnnEnabled: true,
  35. LocalAnnPort: 21027,
  36. LocalAnnMCAddr: "[ff12::8384]:21027",
  37. MaxSendKbps: 0,
  38. MaxRecvKbps: 0,
  39. ReconnectIntervalS: 60,
  40. RelaysEnabled: true,
  41. RelayReconnectIntervalM: 10,
  42. StartBrowser: true,
  43. NATEnabled: true,
  44. NATLeaseM: 60,
  45. NATRenewalM: 30,
  46. NATTimeoutS: 10,
  47. RestartOnWakeup: true,
  48. AutoUpgradeIntervalH: 12,
  49. KeepTemporariesH: 24,
  50. CacheIgnoredFiles: false,
  51. ProgressUpdateIntervalS: 5,
  52. LimitBandwidthInLan: false,
  53. MinHomeDiskFree: Size{1, "%"},
  54. URURL: "https://data.syncthing.net/newdata",
  55. URInitialDelayS: 1800,
  56. URPostInsecurely: false,
  57. ReleasesURL: "https://upgrades.syncthing.net/meta.json",
  58. AlwaysLocalNets: []string{},
  59. OverwriteRemoteDevNames: false,
  60. TempIndexMinBlocks: 10,
  61. UnackedNotificationIDs: []string{},
  62. WeakHashSelectionMethod: WeakHashAuto,
  63. StunKeepaliveS: 24,
  64. StunServers: []string{"default"},
  65. KCPCongestionControl: true,
  66. KCPReceiveWindowSize: 128,
  67. KCPSendWindowSize: 128,
  68. KCPUpdateIntervalMs: 25,
  69. KCPFastResend: false,
  70. DefaultFolderPath: "~",
  71. }
  72. cfg := New(device1)
  73. if diff, equal := messagediff.PrettyDiff(expected, cfg.Options); !equal {
  74. t.Errorf("Default config differs. Diff:\n%s", diff)
  75. }
  76. }
  77. func TestDeviceConfig(t *testing.T) {
  78. for i := OldestHandledVersion; i <= CurrentVersion; i++ {
  79. os.RemoveAll(filepath.Join("testdata", DefaultMarkerName))
  80. wr, err := Load(fmt.Sprintf("testdata/v%d.xml", i), device1)
  81. if err != nil {
  82. t.Fatal(err)
  83. }
  84. _, err = os.Stat(filepath.Join("testdata", DefaultMarkerName))
  85. if i < 6 && err != nil {
  86. t.Fatal(err)
  87. } else if i >= 6 && err == nil {
  88. t.Fatal("Unexpected file")
  89. }
  90. cfg := wr.cfg
  91. expectedFolders := []FolderConfiguration{
  92. {
  93. ID: "test",
  94. FilesystemType: fs.FilesystemTypeBasic,
  95. Path: "testdata",
  96. Devices: []FolderDeviceConfiguration{{DeviceID: device1}, {DeviceID: device4}},
  97. Type: FolderTypeSendOnly,
  98. RescanIntervalS: 600,
  99. FSWatcherEnabled: false,
  100. FSWatcherDelayS: 10,
  101. Copiers: 0,
  102. Pullers: 0,
  103. Hashers: 0,
  104. AutoNormalize: true,
  105. MinDiskFree: Size{1, "%"},
  106. MaxConflicts: -1,
  107. Versioning: VersioningConfiguration{
  108. Params: map[string]string{},
  109. },
  110. WeakHashThresholdPct: 25,
  111. MarkerName: DefaultMarkerName,
  112. },
  113. }
  114. // The cachedFilesystem will have been resolved to an absolute path,
  115. // depending on where the tests are running. Zero it out so we don't
  116. // fail based on that.
  117. for i := range cfg.Folders {
  118. cfg.Folders[i].cachedFilesystem = nil
  119. }
  120. expectedDevices := []DeviceConfiguration{
  121. {
  122. DeviceID: device1,
  123. Name: "node one",
  124. Addresses: []string{"tcp://a"},
  125. Compression: protocol.CompressMetadata,
  126. AllowedNetworks: []string{},
  127. },
  128. {
  129. DeviceID: device4,
  130. Name: "node two",
  131. Addresses: []string{"tcp://b"},
  132. Compression: protocol.CompressMetadata,
  133. AllowedNetworks: []string{},
  134. },
  135. }
  136. expectedDeviceIDs := []protocol.DeviceID{device1, device4}
  137. if cfg.Version != CurrentVersion {
  138. t.Errorf("%d: Incorrect version %d != %d", i, cfg.Version, CurrentVersion)
  139. }
  140. if diff, equal := messagediff.PrettyDiff(expectedFolders, cfg.Folders); !equal {
  141. t.Errorf("%d: Incorrect Folders. Diff:\n%s", i, diff)
  142. }
  143. if diff, equal := messagediff.PrettyDiff(expectedDevices, cfg.Devices); !equal {
  144. t.Errorf("%d: Incorrect Devices. Diff:\n%s", i, diff)
  145. }
  146. if diff, equal := messagediff.PrettyDiff(expectedDeviceIDs, cfg.Folders[0].DeviceIDs()); !equal {
  147. t.Errorf("%d: Incorrect DeviceIDs. Diff:\n%s", i, diff)
  148. }
  149. }
  150. }
  151. func TestNoListenAddresses(t *testing.T) {
  152. cfg, err := Load("testdata/nolistenaddress.xml", device1)
  153. if err != nil {
  154. t.Error(err)
  155. }
  156. expected := []string{""}
  157. actual := cfg.Options().ListenAddresses
  158. if diff, equal := messagediff.PrettyDiff(expected, actual); !equal {
  159. t.Errorf("Unexpected ListenAddresses. Diff:\n%s", diff)
  160. }
  161. }
  162. func TestOverriddenValues(t *testing.T) {
  163. expected := OptionsConfiguration{
  164. ListenAddresses: []string{"tcp://:23000"},
  165. GlobalAnnServers: []string{"udp4://syncthing.nym.se:22026"},
  166. GlobalAnnEnabled: false,
  167. LocalAnnEnabled: false,
  168. LocalAnnPort: 42123,
  169. LocalAnnMCAddr: "quux:3232",
  170. MaxSendKbps: 1234,
  171. MaxRecvKbps: 2341,
  172. ReconnectIntervalS: 6000,
  173. RelaysEnabled: false,
  174. RelayReconnectIntervalM: 20,
  175. StartBrowser: false,
  176. NATEnabled: false,
  177. NATLeaseM: 90,
  178. NATRenewalM: 15,
  179. NATTimeoutS: 15,
  180. RestartOnWakeup: false,
  181. AutoUpgradeIntervalH: 24,
  182. KeepTemporariesH: 48,
  183. CacheIgnoredFiles: true,
  184. ProgressUpdateIntervalS: 10,
  185. LimitBandwidthInLan: true,
  186. MinHomeDiskFree: Size{5.2, "%"},
  187. URSeen: 2,
  188. URURL: "https://localhost/newdata",
  189. URInitialDelayS: 800,
  190. URPostInsecurely: true,
  191. ReleasesURL: "https://localhost/releases",
  192. AlwaysLocalNets: []string{},
  193. OverwriteRemoteDevNames: true,
  194. TempIndexMinBlocks: 100,
  195. UnackedNotificationIDs: []string{
  196. "channelNotification", // added in 17->18 migration
  197. },
  198. WeakHashSelectionMethod: WeakHashNever,
  199. StunKeepaliveS: 10,
  200. StunServers: []string{"a.stun.com", "b.stun.com"},
  201. KCPCongestionControl: false,
  202. KCPReceiveWindowSize: 1280,
  203. KCPSendWindowSize: 1280,
  204. KCPUpdateIntervalMs: 1000,
  205. KCPFastResend: true,
  206. DefaultFolderPath: "/media/syncthing",
  207. }
  208. os.Unsetenv("STNOUPGRADE")
  209. cfg, err := Load("testdata/overridenvalues.xml", device1)
  210. if err != nil {
  211. t.Error(err)
  212. }
  213. if diff, equal := messagediff.PrettyDiff(expected, cfg.Options()); !equal {
  214. t.Errorf("Overridden config differs. Diff:\n%s", diff)
  215. }
  216. }
  217. func TestDeviceAddressesDynamic(t *testing.T) {
  218. name, _ := os.Hostname()
  219. expected := map[protocol.DeviceID]DeviceConfiguration{
  220. device1: {
  221. DeviceID: device1,
  222. Addresses: []string{"dynamic"},
  223. AllowedNetworks: []string{},
  224. },
  225. device2: {
  226. DeviceID: device2,
  227. Addresses: []string{"dynamic"},
  228. AllowedNetworks: []string{},
  229. },
  230. device3: {
  231. DeviceID: device3,
  232. Addresses: []string{"dynamic"},
  233. AllowedNetworks: []string{},
  234. },
  235. device4: {
  236. DeviceID: device4,
  237. Name: name, // Set when auto created
  238. Addresses: []string{"dynamic"},
  239. Compression: protocol.CompressMetadata,
  240. AllowedNetworks: []string{},
  241. },
  242. }
  243. cfg, err := Load("testdata/deviceaddressesdynamic.xml", device4)
  244. if err != nil {
  245. t.Error(err)
  246. }
  247. actual := cfg.Devices()
  248. if diff, equal := messagediff.PrettyDiff(expected, actual); !equal {
  249. t.Errorf("Devices differ. Diff:\n%s", diff)
  250. }
  251. }
  252. func TestDeviceCompression(t *testing.T) {
  253. name, _ := os.Hostname()
  254. expected := map[protocol.DeviceID]DeviceConfiguration{
  255. device1: {
  256. DeviceID: device1,
  257. Addresses: []string{"dynamic"},
  258. Compression: protocol.CompressMetadata,
  259. AllowedNetworks: []string{},
  260. },
  261. device2: {
  262. DeviceID: device2,
  263. Addresses: []string{"dynamic"},
  264. Compression: protocol.CompressMetadata,
  265. AllowedNetworks: []string{},
  266. },
  267. device3: {
  268. DeviceID: device3,
  269. Addresses: []string{"dynamic"},
  270. Compression: protocol.CompressNever,
  271. AllowedNetworks: []string{},
  272. },
  273. device4: {
  274. DeviceID: device4,
  275. Name: name, // Set when auto created
  276. Addresses: []string{"dynamic"},
  277. Compression: protocol.CompressMetadata,
  278. AllowedNetworks: []string{},
  279. },
  280. }
  281. cfg, err := Load("testdata/devicecompression.xml", device4)
  282. if err != nil {
  283. t.Error(err)
  284. }
  285. actual := cfg.Devices()
  286. if diff, equal := messagediff.PrettyDiff(expected, actual); !equal {
  287. t.Errorf("Devices differ. Diff:\n%s", diff)
  288. }
  289. }
  290. func TestDeviceAddressesStatic(t *testing.T) {
  291. name, _ := os.Hostname()
  292. expected := map[protocol.DeviceID]DeviceConfiguration{
  293. device1: {
  294. DeviceID: device1,
  295. Addresses: []string{"tcp://192.0.2.1", "tcp://192.0.2.2"},
  296. AllowedNetworks: []string{},
  297. },
  298. device2: {
  299. DeviceID: device2,
  300. Addresses: []string{"tcp://192.0.2.3:6070", "tcp://[2001:db8::42]:4242"},
  301. AllowedNetworks: []string{},
  302. },
  303. device3: {
  304. DeviceID: device3,
  305. Addresses: []string{"tcp://[2001:db8::44]:4444", "tcp://192.0.2.4:6090"},
  306. AllowedNetworks: []string{},
  307. },
  308. device4: {
  309. DeviceID: device4,
  310. Name: name, // Set when auto created
  311. Addresses: []string{"dynamic"},
  312. Compression: protocol.CompressMetadata,
  313. AllowedNetworks: []string{},
  314. },
  315. }
  316. cfg, err := Load("testdata/deviceaddressesstatic.xml", device4)
  317. if err != nil {
  318. t.Error(err)
  319. }
  320. actual := cfg.Devices()
  321. if diff, equal := messagediff.PrettyDiff(expected, actual); !equal {
  322. t.Errorf("Devices differ. Diff:\n%s", diff)
  323. }
  324. }
  325. func TestVersioningConfig(t *testing.T) {
  326. cfg, err := Load("testdata/versioningconfig.xml", device4)
  327. if err != nil {
  328. t.Error(err)
  329. }
  330. vc := cfg.Folders()["test"].Versioning
  331. if vc.Type != "simple" {
  332. t.Errorf(`vc.Type %q != "simple"`, vc.Type)
  333. }
  334. if l := len(vc.Params); l != 2 {
  335. t.Errorf("len(vc.Params) %d != 2", l)
  336. }
  337. expected := map[string]string{
  338. "foo": "bar",
  339. "baz": "quux",
  340. }
  341. if diff, equal := messagediff.PrettyDiff(expected, vc.Params); !equal {
  342. t.Errorf("vc.Params differ. Diff:\n%s", diff)
  343. }
  344. }
  345. func TestIssue1262(t *testing.T) {
  346. if runtime.GOOS != "windows" {
  347. t.Skipf("path gets converted to absolute as part of the filesystem initialization on linux")
  348. }
  349. cfg, err := Load("testdata/issue-1262.xml", device4)
  350. if err != nil {
  351. t.Fatal(err)
  352. }
  353. actual := cfg.Folders()["test"].Filesystem().URI()
  354. expected := `e:\`
  355. if actual != expected {
  356. t.Errorf("%q != %q", actual, expected)
  357. }
  358. }
  359. func TestIssue1750(t *testing.T) {
  360. cfg, err := Load("testdata/issue-1750.xml", device4)
  361. if err != nil {
  362. t.Fatal(err)
  363. }
  364. if cfg.Options().ListenAddresses[0] != "tcp://:23000" {
  365. t.Errorf("%q != %q", cfg.Options().ListenAddresses[0], "tcp://:23000")
  366. }
  367. if cfg.Options().ListenAddresses[1] != "tcp://:23001" {
  368. t.Errorf("%q != %q", cfg.Options().ListenAddresses[1], "tcp://:23001")
  369. }
  370. if cfg.Options().GlobalAnnServers[0] != "udp4://syncthing.nym.se:22026" {
  371. t.Errorf("%q != %q", cfg.Options().GlobalAnnServers[0], "udp4://syncthing.nym.se:22026")
  372. }
  373. if cfg.Options().GlobalAnnServers[1] != "udp4://syncthing.nym.se:22027" {
  374. t.Errorf("%q != %q", cfg.Options().GlobalAnnServers[1], "udp4://syncthing.nym.se:22027")
  375. }
  376. }
  377. func TestFolderPath(t *testing.T) {
  378. folder := FolderConfiguration{
  379. Path: "~/tmp",
  380. }
  381. realPath := folder.Filesystem().URI()
  382. if !filepath.IsAbs(realPath) {
  383. t.Error(realPath, "should be absolute")
  384. }
  385. if strings.Contains(realPath, "~") {
  386. t.Error(realPath, "should not contain ~")
  387. }
  388. }
  389. func TestNewSaveLoad(t *testing.T) {
  390. path := "testdata/temp.xml"
  391. os.Remove(path)
  392. exists := func(path string) bool {
  393. _, err := os.Stat(path)
  394. return err == nil
  395. }
  396. intCfg := New(device1)
  397. cfg := Wrap(path, intCfg)
  398. // To make the equality pass later
  399. cfg.cfg.XMLName.Local = "configuration"
  400. if exists(path) {
  401. t.Error(path, "exists")
  402. }
  403. err := cfg.Save()
  404. if err != nil {
  405. t.Error(err)
  406. }
  407. if !exists(path) {
  408. t.Error(path, "does not exist")
  409. }
  410. cfg2, err := Load(path, device1)
  411. if err != nil {
  412. t.Error(err)
  413. }
  414. if diff, equal := messagediff.PrettyDiff(cfg.RawCopy(), cfg2.RawCopy()); !equal {
  415. t.Errorf("Configs are not equal. Diff:\n%s", diff)
  416. }
  417. os.Remove(path)
  418. }
  419. func TestPrepare(t *testing.T) {
  420. var cfg Configuration
  421. if cfg.Folders != nil || cfg.Devices != nil || cfg.Options.ListenAddresses != nil {
  422. t.Error("Expected nil")
  423. }
  424. cfg.prepare(device1)
  425. if cfg.Folders == nil || cfg.Devices == nil || cfg.Options.ListenAddresses == nil {
  426. t.Error("Unexpected nil")
  427. }
  428. }
  429. func TestCopy(t *testing.T) {
  430. wrapper, err := Load("testdata/example.xml", device1)
  431. if err != nil {
  432. t.Fatal(err)
  433. }
  434. cfg := wrapper.RawCopy()
  435. bsOrig, err := json.MarshalIndent(cfg, "", " ")
  436. if err != nil {
  437. t.Fatal(err)
  438. }
  439. copy := cfg.Copy()
  440. cfg.Devices[0].Addresses[0] = "wrong"
  441. cfg.Folders[0].Devices[0].DeviceID = protocol.DeviceID{0, 1, 2, 3}
  442. cfg.Options.ListenAddresses[0] = "wrong"
  443. cfg.GUI.APIKey = "wrong"
  444. bsChanged, err := json.MarshalIndent(cfg, "", " ")
  445. if err != nil {
  446. t.Fatal(err)
  447. }
  448. bsCopy, err := json.MarshalIndent(copy, "", " ")
  449. if err != nil {
  450. t.Fatal(err)
  451. }
  452. if bytes.Equal(bsOrig, bsChanged) {
  453. t.Error("Config should have changed")
  454. }
  455. if !bytes.Equal(bsOrig, bsCopy) {
  456. //ioutil.WriteFile("a", bsOrig, 0644)
  457. //ioutil.WriteFile("b", bsCopy, 0644)
  458. t.Error("Copy should be unchanged")
  459. }
  460. }
  461. func TestPullOrder(t *testing.T) {
  462. wrapper, err := Load("testdata/pullorder.xml", device1)
  463. if err != nil {
  464. t.Fatal(err)
  465. }
  466. folders := wrapper.Folders()
  467. expected := []struct {
  468. name string
  469. order PullOrder
  470. }{
  471. {"f1", OrderRandom}, // empty value, default
  472. {"f2", OrderRandom}, // explicit
  473. {"f3", OrderAlphabetic}, // explicit
  474. {"f4", OrderRandom}, // unknown value, default
  475. {"f5", OrderSmallestFirst}, // explicit
  476. {"f6", OrderLargestFirst}, // explicit
  477. {"f7", OrderOldestFirst}, // explicit
  478. {"f8", OrderNewestFirst}, // explicit
  479. }
  480. // Verify values are deserialized correctly
  481. for _, tc := range expected {
  482. if actual := folders[tc.name].Order; actual != tc.order {
  483. t.Errorf("Incorrect pull order for %q: %v != %v", tc.name, actual, tc.order)
  484. }
  485. }
  486. // Serialize and deserialize again to verify it survives the transformation
  487. buf := new(bytes.Buffer)
  488. cfg := wrapper.RawCopy()
  489. cfg.WriteXML(buf)
  490. t.Logf("%s", buf.Bytes())
  491. cfg, err = ReadXML(buf, device1)
  492. if err != nil {
  493. t.Fatal(err)
  494. }
  495. wrapper = Wrap("testdata/pullorder.xml", cfg)
  496. folders = wrapper.Folders()
  497. for _, tc := range expected {
  498. if actual := folders[tc.name].Order; actual != tc.order {
  499. t.Errorf("Incorrect pull order for %q: %v != %v", tc.name, actual, tc.order)
  500. }
  501. }
  502. }
  503. func TestLargeRescanInterval(t *testing.T) {
  504. wrapper, err := Load("testdata/largeinterval.xml", device1)
  505. if err != nil {
  506. t.Fatal(err)
  507. }
  508. if wrapper.Folders()["l1"].RescanIntervalS != MaxRescanIntervalS {
  509. t.Error("too large rescan interval should be maxed out")
  510. }
  511. if wrapper.Folders()["l2"].RescanIntervalS != 0 {
  512. t.Error("negative rescan interval should become zero")
  513. }
  514. }
  515. func TestGUIConfigURL(t *testing.T) {
  516. testcases := [][2]string{
  517. {"192.0.2.42:8080", "http://192.0.2.42:8080/"},
  518. {":8080", "http://127.0.0.1:8080/"},
  519. {"0.0.0.0:8080", "http://127.0.0.1:8080/"},
  520. {"127.0.0.1:8080", "http://127.0.0.1:8080/"},
  521. {"127.0.0.2:8080", "http://127.0.0.2:8080/"},
  522. {"[::]:8080", "http://[::1]:8080/"},
  523. {"[2001::42]:8080", "http://[2001::42]:8080/"},
  524. }
  525. for _, tc := range testcases {
  526. c := GUIConfiguration{
  527. RawAddress: tc[0],
  528. }
  529. u := c.URL()
  530. if u != tc[1] {
  531. t.Errorf("Incorrect URL %s != %s for addr %s", u, tc[1], tc[0])
  532. }
  533. }
  534. }
  535. func TestDuplicateDevices(t *testing.T) {
  536. // Duplicate devices should be removed
  537. wrapper, err := Load("testdata/dupdevices.xml", device1)
  538. if err != nil {
  539. t.Fatal(err)
  540. }
  541. if l := len(wrapper.RawCopy().Devices); l != 3 {
  542. t.Errorf("Incorrect number of devices, %d != 3", l)
  543. }
  544. f := wrapper.Folders()["f2"]
  545. if l := len(f.Devices); l != 2 {
  546. t.Errorf("Incorrect number of folder devices, %d != 2", l)
  547. }
  548. }
  549. func TestDuplicateFolders(t *testing.T) {
  550. // Duplicate folders are a loading error
  551. _, err := Load("testdata/dupfolders.xml", device1)
  552. if err == nil || !strings.HasPrefix(err.Error(), "duplicate folder ID") {
  553. t.Fatal(`Expected error to mention "duplicate folder ID":`, err)
  554. }
  555. }
  556. func TestEmptyFolderPaths(t *testing.T) {
  557. // Empty folder paths are allowed at the loading stage, and should not
  558. // get messed up by the prepare steps (e.g., become the current dir or
  559. // get a slash added so that it becomes the root directory or similar).
  560. wrapper, err := Load("testdata/nopath.xml", device1)
  561. if err != nil {
  562. t.Fatal(err)
  563. }
  564. folder := wrapper.Folders()["f1"]
  565. if folder.cachedFilesystem != nil {
  566. t.Errorf("Expected %q to be empty", folder.cachedFilesystem)
  567. }
  568. }
  569. func TestV14ListenAddressesMigration(t *testing.T) {
  570. tcs := [][3][]string{
  571. // Default listen plus default relays is now "default"
  572. {
  573. {"tcp://0.0.0.0:22000"},
  574. {"dynamic+https://relays.syncthing.net/endpoint"},
  575. {"default"},
  576. },
  577. // Default listen address without any relay addresses gets converted
  578. // to just the listen address. It's easier this way, and frankly the
  579. // user has gone to some trouble to get the empty string in the
  580. // config to start with...
  581. {
  582. {"tcp://0.0.0.0:22000"}, // old listen addrs
  583. {""}, // old relay addrs
  584. {"tcp://0.0.0.0:22000"}, // new listen addrs
  585. },
  586. // Default listen plus non-default relays gets copied verbatim
  587. {
  588. {"tcp://0.0.0.0:22000"},
  589. {"dynamic+https://other.example.com"},
  590. {"tcp://0.0.0.0:22000", "dynamic+https://other.example.com"},
  591. },
  592. // Non-default listen plus default relays gets copied verbatim
  593. {
  594. {"tcp://1.2.3.4:22000"},
  595. {"dynamic+https://relays.syncthing.net/endpoint"},
  596. {"tcp://1.2.3.4:22000", "dynamic+https://relays.syncthing.net/endpoint"},
  597. },
  598. // Default stuff gets sucked into "default", the rest gets copied
  599. {
  600. {"tcp://0.0.0.0:22000", "tcp://1.2.3.4:22000"},
  601. {"dynamic+https://relays.syncthing.net/endpoint", "relay://other.example.com"},
  602. {"default", "tcp://1.2.3.4:22000", "relay://other.example.com"},
  603. },
  604. }
  605. for _, tc := range tcs {
  606. cfg := Configuration{
  607. Version: 13,
  608. Options: OptionsConfiguration{
  609. ListenAddresses: tc[0],
  610. DeprecatedRelayServers: tc[1],
  611. },
  612. }
  613. convertV13V14(&cfg)
  614. if cfg.Version != 14 {
  615. t.Error("Configuration was not converted")
  616. }
  617. sort.Strings(tc[2])
  618. if !reflect.DeepEqual(cfg.Options.ListenAddresses, tc[2]) {
  619. t.Errorf("Migration error; actual %#v != expected %#v", cfg.Options.ListenAddresses, tc[2])
  620. }
  621. }
  622. }
  623. func TestIgnoredDevices(t *testing.T) {
  624. // Verify that ignored devices that are also present in the
  625. // configuration are not in fact ignored.
  626. wrapper, err := Load("testdata/ignoreddevices.xml", device1)
  627. if err != nil {
  628. t.Fatal(err)
  629. }
  630. if wrapper.IgnoredDevice(device1) {
  631. t.Errorf("Device %v should not be ignored", device1)
  632. }
  633. if !wrapper.IgnoredDevice(device3) {
  634. t.Errorf("Device %v should be ignored", device3)
  635. }
  636. }
  637. func TestGetDevice(t *testing.T) {
  638. // Verify that the Device() call does the right thing
  639. wrapper, err := Load("testdata/ignoreddevices.xml", device1)
  640. if err != nil {
  641. t.Fatal(err)
  642. }
  643. // device1 is mentioned in the config
  644. device, ok := wrapper.Device(device1)
  645. if !ok {
  646. t.Error(device1, "should exist")
  647. }
  648. if device.DeviceID != device1 {
  649. t.Error("Should have returned", device1, "not", device.DeviceID)
  650. }
  651. // device3 is not
  652. device, ok = wrapper.Device(device3)
  653. if ok {
  654. t.Error(device3, "should not exist")
  655. }
  656. if device.DeviceID == device3 {
  657. t.Error("Should not returned ID", device3)
  658. }
  659. }
  660. func TestSharesRemovedOnDeviceRemoval(t *testing.T) {
  661. wrapper, err := Load("testdata/example.xml", device1)
  662. if err != nil {
  663. t.Errorf("Failed: %s", err)
  664. }
  665. raw := wrapper.RawCopy()
  666. raw.Devices = raw.Devices[:len(raw.Devices)-1]
  667. if len(raw.Folders[0].Devices) <= len(raw.Devices) {
  668. t.Error("Should have less devices")
  669. }
  670. err = wrapper.Replace(raw)
  671. if err != nil {
  672. t.Errorf("Failed: %s", err)
  673. }
  674. raw = wrapper.RawCopy()
  675. if len(raw.Folders[0].Devices) > len(raw.Devices) {
  676. t.Error("Unexpected extra device")
  677. }
  678. }
  679. func TestIssue4219(t *testing.T) {
  680. // Adding a folder that was previously ignored should make it unignored.
  681. r := bytes.NewReader([]byte(`{
  682. "folders": [
  683. {"id": "abcd123"}
  684. ],
  685. "ignoredFolders": ["t1", "abcd123", "t2"]
  686. }`))
  687. cfg, err := ReadJSON(r, protocol.LocalDeviceID)
  688. if err != nil {
  689. t.Fatal(err)
  690. }
  691. if len(cfg.IgnoredFolders) != 2 {
  692. t.Errorf("There should be two ignored folders, not %d", len(cfg.IgnoredFolders))
  693. }
  694. w := Wrap("/tmp/cfg", cfg)
  695. if !w.IgnoredFolder("t1") {
  696. t.Error("Folder t1 should be ignored")
  697. }
  698. if !w.IgnoredFolder("t2") {
  699. t.Error("Folder t2 should be ignored")
  700. }
  701. if w.IgnoredFolder("abcd123") {
  702. t.Error("Folder abcd123 should not be ignored")
  703. }
  704. }