config_test.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. // Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
  2. // All rights reserved. Use of this source code is governed by an MIT-style
  3. // license that can be found in the LICENSE file.
  4. package config
  5. import (
  6. "bytes"
  7. "io"
  8. "os"
  9. "reflect"
  10. "testing"
  11. "github.com/calmh/syncthing/files"
  12. "github.com/calmh/syncthing/protocol"
  13. )
  14. var node1, node2, node3, node4 protocol.NodeID
  15. func init() {
  16. node1, _ = protocol.NodeIDFromString("AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ")
  17. node2, _ = protocol.NodeIDFromString("GYRZZQB-IRNPV4Z-T7TC52W-EQYJ3TT-FDQW6MW-DFLMU42-SSSU6EM-FBK2VAY")
  18. node3, _ = protocol.NodeIDFromString("LGFPDIT-7SKNNJL-VJZA4FC-7QNCRKA-CE753K7-2BW5QDK-2FOZ7FR-FEP57QJ")
  19. node4, _ = protocol.NodeIDFromString("P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2")
  20. }
  21. func TestDefaultValues(t *testing.T) {
  22. expected := OptionsConfiguration{
  23. ListenAddress: []string{"0.0.0.0:22000"},
  24. GlobalAnnServer: "announce.syncthing.net:22026",
  25. GlobalAnnEnabled: true,
  26. LocalAnnEnabled: true,
  27. LocalAnnPort: 21025,
  28. ParallelRequests: 16,
  29. MaxSendKbps: 0,
  30. RescanIntervalS: 60,
  31. ReconnectIntervalS: 60,
  32. MaxChangeKbps: 10000,
  33. StartBrowser: true,
  34. UPnPEnabled: true,
  35. }
  36. cfg, err := Load(bytes.NewReader(nil), node1)
  37. if err != io.EOF {
  38. t.Error(err)
  39. }
  40. if !reflect.DeepEqual(cfg.Options, expected) {
  41. t.Errorf("Default config differs;\n E: %#v\n A: %#v", expected, cfg.Options)
  42. }
  43. }
  44. func TestNodeConfig(t *testing.T) {
  45. v1data := []byte(`
  46. <configuration version="1">
  47. <repository id="test" directory="~/Sync">
  48. <node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ" name="node one">
  49. <address>a</address>
  50. </node>
  51. <node id="P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ" name="node two">
  52. <address>b</address>
  53. </node>
  54. </repository>
  55. <options>
  56. <readOnly>true</readOnly>
  57. </options>
  58. </configuration>
  59. `)
  60. v2data := []byte(`
  61. <configuration version="2">
  62. <repository id="test" directory="~/Sync" ro="true">
  63. <node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ"/>
  64. <node id="P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ"/>
  65. </repository>
  66. <node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ" name="node one">
  67. <address>a</address>
  68. </node>
  69. <node id="P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ" name="node two">
  70. <address>b</address>
  71. </node>
  72. </configuration>
  73. `)
  74. for i, data := range [][]byte{v1data, v2data} {
  75. cfg, err := Load(bytes.NewReader(data), node1)
  76. if err != nil {
  77. t.Error(err)
  78. }
  79. expectedRepos := []RepositoryConfiguration{
  80. {
  81. ID: "test",
  82. Directory: "~/Sync",
  83. Nodes: []NodeConfiguration{{NodeID: node1}, {NodeID: node4}},
  84. ReadOnly: true,
  85. },
  86. }
  87. expectedNodes := []NodeConfiguration{
  88. {
  89. NodeID: node1,
  90. Name: "node one",
  91. Addresses: []string{"a"},
  92. },
  93. {
  94. NodeID: node4,
  95. Name: "node two",
  96. Addresses: []string{"b"},
  97. },
  98. }
  99. expectedNodeIDs := []protocol.NodeID{node1, node4}
  100. if cfg.Version != 2 {
  101. t.Errorf("%d: Incorrect version %d != 2", i, cfg.Version)
  102. }
  103. if !reflect.DeepEqual(cfg.Repositories, expectedRepos) {
  104. t.Errorf("%d: Incorrect Repositories\n A: %#v\n E: %#v", i, cfg.Repositories, expectedRepos)
  105. }
  106. if !reflect.DeepEqual(cfg.Nodes, expectedNodes) {
  107. t.Errorf("%d: Incorrect Nodes\n A: %#v\n E: %#v", i, cfg.Nodes, expectedNodes)
  108. }
  109. if !reflect.DeepEqual(cfg.Repositories[0].NodeIDs(), expectedNodeIDs) {
  110. t.Errorf("%d: Incorrect NodeIDs\n A: %#v\n E: %#v", i, cfg.Repositories[0].NodeIDs(), expectedNodeIDs)
  111. }
  112. }
  113. }
  114. func TestNoListenAddress(t *testing.T) {
  115. data := []byte(`<configuration version="1">
  116. <options>
  117. <listenAddress></listenAddress>
  118. </options>
  119. </configuration>
  120. `)
  121. cfg, err := Load(bytes.NewReader(data), node1)
  122. if err != nil {
  123. t.Error(err)
  124. }
  125. expected := []string{""}
  126. if !reflect.DeepEqual(cfg.Options.ListenAddress, expected) {
  127. t.Errorf("Unexpected ListenAddress %#v", cfg.Options.ListenAddress)
  128. }
  129. }
  130. func TestOverriddenValues(t *testing.T) {
  131. data := []byte(`<configuration version="2">
  132. <options>
  133. <listenAddress>:23000</listenAddress>
  134. <allowDelete>false</allowDelete>
  135. <globalAnnounceServer>syncthing.nym.se:22026</globalAnnounceServer>
  136. <globalAnnounceEnabled>false</globalAnnounceEnabled>
  137. <localAnnounceEnabled>false</localAnnounceEnabled>
  138. <localAnnouncePort>42123</localAnnouncePort>
  139. <parallelRequests>32</parallelRequests>
  140. <maxSendKbps>1234</maxSendKbps>
  141. <rescanIntervalS>600</rescanIntervalS>
  142. <reconnectionIntervalS>6000</reconnectionIntervalS>
  143. <maxChangeKbps>2345</maxChangeKbps>
  144. <startBrowser>false</startBrowser>
  145. <upnpEnabled>false</upnpEnabled>
  146. </options>
  147. </configuration>
  148. `)
  149. expected := OptionsConfiguration{
  150. ListenAddress: []string{":23000"},
  151. GlobalAnnServer: "syncthing.nym.se:22026",
  152. GlobalAnnEnabled: false,
  153. LocalAnnEnabled: false,
  154. LocalAnnPort: 42123,
  155. ParallelRequests: 32,
  156. MaxSendKbps: 1234,
  157. RescanIntervalS: 600,
  158. ReconnectIntervalS: 6000,
  159. MaxChangeKbps: 2345,
  160. StartBrowser: false,
  161. UPnPEnabled: false,
  162. }
  163. cfg, err := Load(bytes.NewReader(data), node1)
  164. if err != nil {
  165. t.Error(err)
  166. }
  167. if !reflect.DeepEqual(cfg.Options, expected) {
  168. t.Errorf("Overridden config differs;\n E: %#v\n A: %#v", expected, cfg.Options)
  169. }
  170. }
  171. func TestNodeAddresses(t *testing.T) {
  172. data := []byte(`
  173. <configuration version="2">
  174. <node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ">
  175. <address></address>
  176. </node>
  177. <node id="GYRZZQBIRNPV4T7TC52WEQYJ3TFDQW6MWDFLMU4SSSU6EMFBK2VA">
  178. </node>
  179. <node id="LGFPDIT7SKNNJVJZA4FC7QNCRKCE753K72BW5QD2FOZ7FRFEP57Q">
  180. <address>dynamic</address>
  181. </node>
  182. </configuration>
  183. `)
  184. name, _ := os.Hostname()
  185. expected := []NodeConfiguration{
  186. {
  187. NodeID: node1,
  188. Addresses: []string{"dynamic"},
  189. },
  190. {
  191. NodeID: node2,
  192. Addresses: []string{"dynamic"},
  193. },
  194. {
  195. NodeID: node3,
  196. Addresses: []string{"dynamic"},
  197. },
  198. {
  199. NodeID: node4,
  200. Name: name, // Set when auto created
  201. Addresses: []string{"dynamic"},
  202. },
  203. }
  204. cfg, err := Load(bytes.NewReader(data), node4)
  205. if err != nil {
  206. t.Error(err)
  207. }
  208. if !reflect.DeepEqual(cfg.Nodes, expected) {
  209. t.Errorf("Nodes differ;\n E: %#v\n A: %#v", expected, cfg.Nodes)
  210. }
  211. }
  212. func TestSyncOrders(t *testing.T) {
  213. data := []byte(`
  214. <configuration version="2">
  215. <repository directory="~/Sync">
  216. <syncorder>
  217. <pattern pattern="\.jpg$" priority="1" />
  218. </syncorder>
  219. </repository>
  220. </configuration>
  221. `)
  222. expected := []SyncOrderPattern{
  223. {
  224. Pattern: "\\.jpg$",
  225. Priority: 1,
  226. },
  227. }
  228. cfg, err := Load(bytes.NewReader(data), node1)
  229. if err != nil {
  230. t.Error(err)
  231. }
  232. for i := range expected {
  233. if !reflect.DeepEqual(cfg.Repositories[0].SyncOrderPatterns[i], expected[i]) {
  234. t.Errorf("Patterns[%d] differ;\n E: %#v\n A: %#v", i, expected[i], cfg.Repositories[0].SyncOrderPatterns[i])
  235. }
  236. }
  237. }
  238. func TestFileSorter(t *testing.T) {
  239. rcfg := RepositoryConfiguration{
  240. SyncOrderPatterns: []SyncOrderPattern{
  241. {"\\.jpg$", 10, nil},
  242. {"\\.mov$", 5, nil},
  243. {"^camera-uploads", 100, nil},
  244. },
  245. }
  246. f := []protocol.FileInfo{
  247. {Name: "bar.mov"},
  248. {Name: "baz.txt"},
  249. {Name: "foo.jpg"},
  250. {Name: "frew/foo.jpg"},
  251. {Name: "frew/lol.go"},
  252. {Name: "frew/rofl.copter"},
  253. {Name: "frew/bar.mov"},
  254. {Name: "camera-uploads/foo.jpg"},
  255. {Name: "camera-uploads/hurr.pl"},
  256. {Name: "camera-uploads/herp.mov"},
  257. {Name: "camera-uploads/wee.txt"},
  258. }
  259. files.SortBy(rcfg.FileRanker()).Sort(f)
  260. expected := []protocol.FileInfo{
  261. {Name: "camera-uploads/foo.jpg"},
  262. {Name: "camera-uploads/herp.mov"},
  263. {Name: "camera-uploads/hurr.pl"},
  264. {Name: "camera-uploads/wee.txt"},
  265. {Name: "foo.jpg"},
  266. {Name: "frew/foo.jpg"},
  267. {Name: "bar.mov"},
  268. {Name: "frew/bar.mov"},
  269. {Name: "frew/lol.go"},
  270. {Name: "baz.txt"},
  271. {Name: "frew/rofl.copter"},
  272. }
  273. if !reflect.DeepEqual(f, expected) {
  274. t.Errorf(
  275. "\n\nexpected:\n" +
  276. formatFiles(expected) + "\n" +
  277. "got:\n" +
  278. formatFiles(f) + "\n\n",
  279. )
  280. }
  281. }
  282. func formatFiles(f []protocol.FileInfo) string {
  283. ret := ""
  284. for _, v := range f {
  285. ret += " " + v.Name + "\n"
  286. }
  287. return ret
  288. }