config_test.go 21 KB

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