protocol_test.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. // Copyright (C) 2014 The Protocol Authors.
  2. package protocol
  3. import (
  4. "bytes"
  5. "crypto/sha256"
  6. "encoding/hex"
  7. "encoding/json"
  8. "errors"
  9. "io"
  10. "io/ioutil"
  11. "runtime"
  12. "sync"
  13. "testing"
  14. "testing/quick"
  15. "time"
  16. "github.com/syncthing/syncthing/lib/rand"
  17. "github.com/syncthing/syncthing/lib/testutils"
  18. )
  19. var (
  20. c0ID = NewDeviceID([]byte{1})
  21. c1ID = NewDeviceID([]byte{2})
  22. quickCfg = &quick.Config{}
  23. )
  24. func TestPing(t *testing.T) {
  25. ar, aw := io.Pipe()
  26. br, bw := io.Pipe()
  27. c0 := NewConnection(c0ID, ar, bw, newTestModel(), "name", CompressAlways).(wireFormatConnection).Connection.(*rawConnection)
  28. c0.Start()
  29. c1 := NewConnection(c1ID, br, aw, newTestModel(), "name", CompressAlways).(wireFormatConnection).Connection.(*rawConnection)
  30. c1.Start()
  31. c0.ClusterConfig(ClusterConfig{})
  32. c1.ClusterConfig(ClusterConfig{})
  33. if ok := c0.ping(); !ok {
  34. t.Error("c0 ping failed")
  35. }
  36. if ok := c1.ping(); !ok {
  37. t.Error("c1 ping failed")
  38. }
  39. }
  40. var errManual = errors.New("manual close")
  41. func TestClose(t *testing.T) {
  42. m0 := newTestModel()
  43. m1 := newTestModel()
  44. ar, aw := io.Pipe()
  45. br, bw := io.Pipe()
  46. c0 := NewConnection(c0ID, ar, bw, m0, "name", CompressAlways).(wireFormatConnection).Connection.(*rawConnection)
  47. c0.Start()
  48. c1 := NewConnection(c1ID, br, aw, m1, "name", CompressAlways)
  49. c1.Start()
  50. c0.ClusterConfig(ClusterConfig{})
  51. c1.ClusterConfig(ClusterConfig{})
  52. c0.internalClose(errManual)
  53. <-c0.closed
  54. if err := m0.closedError(); err != errManual {
  55. t.Fatal("Connection should be closed")
  56. }
  57. // None of these should panic, some should return an error
  58. if c0.ping() {
  59. t.Error("Ping should not return true")
  60. }
  61. c0.Index("default", nil)
  62. c0.Index("default", nil)
  63. if _, err := c0.Request("default", "foo", 0, 0, nil, 0, false); err == nil {
  64. t.Error("Request should return an error")
  65. }
  66. }
  67. // TestCloseOnBlockingSend checks that the connection does not deadlock when
  68. // Close is called while the underlying connection is broken (send blocks).
  69. // https://github.com/syncthing/syncthing/pull/5442
  70. func TestCloseOnBlockingSend(t *testing.T) {
  71. m := newTestModel()
  72. c := NewConnection(c0ID, &testutils.BlockingRW{}, &testutils.BlockingRW{}, m, "name", CompressAlways).(wireFormatConnection).Connection.(*rawConnection)
  73. c.Start()
  74. wg := sync.WaitGroup{}
  75. wg.Add(1)
  76. go func() {
  77. c.ClusterConfig(ClusterConfig{})
  78. wg.Done()
  79. }()
  80. wg.Add(1)
  81. go func() {
  82. c.Close(errManual)
  83. wg.Done()
  84. }()
  85. // This simulates an error from ping timeout
  86. wg.Add(1)
  87. go func() {
  88. c.internalClose(ErrTimeout)
  89. wg.Done()
  90. }()
  91. done := make(chan struct{})
  92. go func() {
  93. wg.Wait()
  94. close(done)
  95. }()
  96. select {
  97. case <-done:
  98. case <-time.After(time.Second):
  99. t.Fatal("timed out before all functions returned")
  100. }
  101. }
  102. func TestCloseRace(t *testing.T) {
  103. indexReceived := make(chan struct{})
  104. unblockIndex := make(chan struct{})
  105. m0 := newTestModel()
  106. m0.indexFn = func(_ DeviceID, _ string, _ []FileInfo) {
  107. close(indexReceived)
  108. <-unblockIndex
  109. }
  110. m1 := newTestModel()
  111. ar, aw := io.Pipe()
  112. br, bw := io.Pipe()
  113. c0 := NewConnection(c0ID, ar, bw, m0, "c0", CompressNever).(wireFormatConnection).Connection.(*rawConnection)
  114. c0.Start()
  115. c1 := NewConnection(c1ID, br, aw, m1, "c1", CompressNever)
  116. c1.Start()
  117. c0.ClusterConfig(ClusterConfig{})
  118. c1.ClusterConfig(ClusterConfig{})
  119. c1.Index("default", nil)
  120. select {
  121. case <-indexReceived:
  122. case <-time.After(time.Second):
  123. t.Fatal("timed out before receiving index")
  124. }
  125. go c0.internalClose(errManual)
  126. select {
  127. case <-c0.closed:
  128. case <-time.After(time.Second):
  129. t.Fatal("timed out before c0.closed was closed")
  130. }
  131. select {
  132. case <-m0.closedCh:
  133. t.Errorf("receiver.Closed called before receiver.Index")
  134. default:
  135. }
  136. close(unblockIndex)
  137. if err := m0.closedError(); err != errManual {
  138. t.Fatal("Connection should be closed")
  139. }
  140. }
  141. func TestClusterConfigFirst(t *testing.T) {
  142. m := newTestModel()
  143. c := NewConnection(c0ID, &testutils.BlockingRW{}, &testutils.NoopRW{}, m, "name", CompressAlways).(wireFormatConnection).Connection.(*rawConnection)
  144. c.Start()
  145. select {
  146. case c.outbox <- asyncMessage{&Ping{}, nil}:
  147. t.Fatal("able to send ping before cluster config")
  148. case <-time.After(100 * time.Millisecond):
  149. // Allow some time for c.writerLoop to setup after c.Start
  150. }
  151. c.ClusterConfig(ClusterConfig{})
  152. done := make(chan struct{})
  153. if ok := c.send(&Ping{}, done); !ok {
  154. t.Fatal("send ping after cluster config returned false")
  155. }
  156. select {
  157. case <-done:
  158. case <-time.After(time.Second):
  159. t.Fatal("timed out before ping was sent")
  160. }
  161. done = make(chan struct{})
  162. go func() {
  163. c.internalClose(errManual)
  164. close(done)
  165. }()
  166. select {
  167. case <-done:
  168. case <-time.After(5 * time.Second):
  169. t.Fatal("Close didn't return before timeout")
  170. }
  171. if err := m.closedError(); err != errManual {
  172. t.Fatal("Connection should be closed")
  173. }
  174. }
  175. func TestMarshalIndexMessage(t *testing.T) {
  176. if testing.Short() {
  177. quickCfg.MaxCount = 10
  178. }
  179. f := func(m1 Index) bool {
  180. if len(m1.Files) == 0 {
  181. m1.Files = nil
  182. }
  183. for i, f := range m1.Files {
  184. if len(f.Blocks) == 0 {
  185. m1.Files[i].Blocks = nil
  186. } else {
  187. for j := range f.Blocks {
  188. f.Blocks[j].Offset = 0
  189. if len(f.Blocks[j].Hash) == 0 {
  190. f.Blocks[j].Hash = nil
  191. }
  192. }
  193. }
  194. if len(f.Version.Counters) == 0 {
  195. m1.Files[i].Version.Counters = nil
  196. }
  197. }
  198. return testMarshal(t, "index", &m1, &Index{})
  199. }
  200. if err := quick.Check(f, quickCfg); err != nil {
  201. t.Error(err)
  202. }
  203. }
  204. func TestMarshalRequestMessage(t *testing.T) {
  205. if testing.Short() {
  206. quickCfg.MaxCount = 10
  207. }
  208. f := func(m1 Request) bool {
  209. if len(m1.Hash) == 0 {
  210. m1.Hash = nil
  211. }
  212. return testMarshal(t, "request", &m1, &Request{})
  213. }
  214. if err := quick.Check(f, quickCfg); err != nil {
  215. t.Error(err)
  216. }
  217. }
  218. func TestMarshalResponseMessage(t *testing.T) {
  219. if testing.Short() {
  220. quickCfg.MaxCount = 10
  221. }
  222. f := func(m1 Response) bool {
  223. if len(m1.Data) == 0 {
  224. m1.Data = nil
  225. }
  226. return testMarshal(t, "response", &m1, &Response{})
  227. }
  228. if err := quick.Check(f, quickCfg); err != nil {
  229. t.Error(err)
  230. }
  231. }
  232. func TestMarshalClusterConfigMessage(t *testing.T) {
  233. if testing.Short() {
  234. quickCfg.MaxCount = 10
  235. }
  236. f := func(m1 ClusterConfig) bool {
  237. if len(m1.Folders) == 0 {
  238. m1.Folders = nil
  239. }
  240. for i := range m1.Folders {
  241. if len(m1.Folders[i].Devices) == 0 {
  242. m1.Folders[i].Devices = nil
  243. }
  244. }
  245. return testMarshal(t, "clusterconfig", &m1, &ClusterConfig{})
  246. }
  247. if err := quick.Check(f, quickCfg); err != nil {
  248. t.Error(err)
  249. }
  250. }
  251. func TestMarshalCloseMessage(t *testing.T) {
  252. if testing.Short() {
  253. quickCfg.MaxCount = 10
  254. }
  255. f := func(m1 Close) bool {
  256. return testMarshal(t, "close", &m1, &Close{})
  257. }
  258. if err := quick.Check(f, quickCfg); err != nil {
  259. t.Error(err)
  260. }
  261. }
  262. func TestMarshalFDPU(t *testing.T) {
  263. if testing.Short() {
  264. quickCfg.MaxCount = 10
  265. }
  266. f := func(m1 FileDownloadProgressUpdate) bool {
  267. if len(m1.Version.Counters) == 0 {
  268. m1.Version.Counters = nil
  269. }
  270. return testMarshal(t, "close", &m1, &FileDownloadProgressUpdate{})
  271. }
  272. if err := quick.Check(f, quickCfg); err != nil {
  273. t.Error(err)
  274. }
  275. }
  276. func TestUnmarshalFDPUv16v17(t *testing.T) {
  277. var fdpu FileDownloadProgressUpdate
  278. m0, _ := hex.DecodeString("08cda1e2e3011278f3918787f3b89b8af2958887f0aa9389f3a08588f3aa8f96f39aa8a5f48b9188f19286a0f3848da4f3aba799f3beb489f0a285b9f487b684f2a3bda2f48598b4f2938a89f2a28badf187a0a2f2aebdbdf4849494f4808fbbf2b3a2adf2bb95bff0a6ada4f198ab9af29a9c8bf1abb793f3baabb2f188a6ba1a0020bb9390f60220f6d9e42220b0c7e2b2fdffffffff0120fdb2dfcdfbffffffff0120cedab1d50120bd8784c0feffffffff0120ace99591fdffffffff0120eed7d09af9ffffffff01")
  279. if err := fdpu.Unmarshal(m0); err != nil {
  280. t.Fatal("Unmarshalling message from v0.14.16:", err)
  281. }
  282. m1, _ := hex.DecodeString("0880f1969905128401f099b192f0abb1b9f3b280aff19e9aa2f3b89e84f484b39df1a7a6b0f1aea4b1f0adac94f3b39caaf1939281f1928a8af0abb1b0f0a8b3b3f3a88e94f2bd85acf29c97a9f2969da6f0b7a188f1908ea2f09a9c9bf19d86a6f29aada8f389bb95f0bf9d88f1a09d89f1b1a4b5f29b9eabf298a59df1b2a589f2979ebdf0b69880f18986b21a440a1508c7d8fb8897ca93d90910e8c4d8e8f2f8f0ccee010a1508afa8ffd8c085b393c50110e5bdedc3bddefe9b0b0a1408a1bedddba4cac5da3c10b8e5d9958ca7e3ec19225ae2f88cb2f8ffffffff018ceda99cfbffffffff01b9c298a407e295e8e9fcffffffff01f3b9ade5fcffffffff01c08bfea9fdffffffff01a2c2e5e1ffffffffff0186dcc5dafdffffffff01e9ffc7e507c9d89db8fdffffffff01")
  283. if err := fdpu.Unmarshal(m1); err != nil {
  284. t.Fatal("Unmarshalling message from v0.14.16:", err)
  285. }
  286. }
  287. func testMarshal(t *testing.T, prefix string, m1, m2 message) bool {
  288. buf, err := m1.Marshal()
  289. if err != nil {
  290. t.Fatal(err)
  291. }
  292. err = m2.Unmarshal(buf)
  293. if err != nil {
  294. t.Fatal(err)
  295. }
  296. bs1, _ := json.MarshalIndent(m1, "", " ")
  297. bs2, _ := json.MarshalIndent(m2, "", " ")
  298. if !bytes.Equal(bs1, bs2) {
  299. ioutil.WriteFile(prefix+"-1.txt", bs1, 0644)
  300. ioutil.WriteFile(prefix+"-2.txt", bs2, 0644)
  301. return false
  302. }
  303. return true
  304. }
  305. func TestLZ4Compression(t *testing.T) {
  306. c := new(rawConnection)
  307. for i := 0; i < 10; i++ {
  308. dataLen := 150 + rand.Intn(150)
  309. data := make([]byte, dataLen)
  310. _, err := io.ReadFull(rand.Reader, data[100:])
  311. if err != nil {
  312. t.Fatal(err)
  313. }
  314. comp, err := c.lz4Compress(data)
  315. if err != nil {
  316. t.Errorf("compressing %d bytes: %v", dataLen, err)
  317. continue
  318. }
  319. res, err := c.lz4Decompress(comp)
  320. if err != nil {
  321. t.Errorf("decompressing %d bytes to %d: %v", len(comp), dataLen, err)
  322. continue
  323. }
  324. if len(res) != len(data) {
  325. t.Errorf("Incorrect len %d != expected %d", len(res), len(data))
  326. }
  327. if !bytes.Equal(data, res) {
  328. t.Error("Incorrect decompressed data")
  329. }
  330. t.Logf("OK #%d, %d -> %d -> %d", i, dataLen, len(comp), dataLen)
  331. }
  332. }
  333. func TestCheckFilename(t *testing.T) {
  334. cases := []struct {
  335. name string
  336. ok bool
  337. }{
  338. // Valid filenames
  339. {"foo", true},
  340. {"foo/bar/baz", true},
  341. {"foo/bar:baz", true}, // colon is ok in general, will be filtered on windows
  342. {`\`, true}, // path separator on the wire is forward slash, so as above
  343. {`\.`, true},
  344. {`\..`, true},
  345. {".foo", true},
  346. {"foo..", true},
  347. // Invalid filenames
  348. {"foo/..", false},
  349. {"foo/../bar", false},
  350. {"../foo/../bar", false},
  351. {"", false},
  352. {".", false},
  353. {"..", false},
  354. {"/", false},
  355. {"/.", false},
  356. {"/..", false},
  357. {"/foo", false},
  358. {"./foo", false},
  359. {"foo./", false},
  360. {"foo/.", false},
  361. {"foo/", false},
  362. }
  363. for _, tc := range cases {
  364. err := checkFilename(tc.name)
  365. if (err == nil) != tc.ok {
  366. t.Errorf("Unexpected result for checkFilename(%q): %v", tc.name, err)
  367. }
  368. }
  369. }
  370. func TestCheckConsistency(t *testing.T) {
  371. cases := []struct {
  372. fi FileInfo
  373. ok bool
  374. }{
  375. {
  376. // valid
  377. fi: FileInfo{
  378. Name: "foo",
  379. Type: FileInfoTypeFile,
  380. Blocks: []BlockInfo{{Size: 1234, Offset: 0, Hash: []byte{1, 2, 3, 4}}},
  381. },
  382. ok: true,
  383. },
  384. {
  385. // deleted with blocks
  386. fi: FileInfo{
  387. Name: "foo",
  388. Deleted: true,
  389. Type: FileInfoTypeFile,
  390. Blocks: []BlockInfo{{Size: 1234, Offset: 0, Hash: []byte{1, 2, 3, 4}}},
  391. },
  392. ok: false,
  393. },
  394. {
  395. // no blocks
  396. fi: FileInfo{
  397. Name: "foo",
  398. Type: FileInfoTypeFile,
  399. },
  400. ok: false,
  401. },
  402. {
  403. // directory with blocks
  404. fi: FileInfo{
  405. Name: "foo",
  406. Type: FileInfoTypeDirectory,
  407. Blocks: []BlockInfo{{Size: 1234, Offset: 0, Hash: []byte{1, 2, 3, 4}}},
  408. },
  409. ok: false,
  410. },
  411. }
  412. for _, tc := range cases {
  413. err := checkFileInfoConsistency(tc.fi)
  414. if tc.ok && err != nil {
  415. t.Errorf("Unexpected error %v (want nil) for %v", err, tc.fi)
  416. }
  417. if !tc.ok && err == nil {
  418. t.Errorf("Unexpected nil error for %v", tc.fi)
  419. }
  420. }
  421. }
  422. func TestBlockSize(t *testing.T) {
  423. cases := []struct {
  424. fileSize int64
  425. blockSize int
  426. }{
  427. {1 << KiB, 128 << KiB},
  428. {1 << MiB, 128 << KiB},
  429. {499 << MiB, 256 << KiB},
  430. {500 << MiB, 512 << KiB},
  431. {501 << MiB, 512 << KiB},
  432. {1 << GiB, 1 << MiB},
  433. {2 << GiB, 2 << MiB},
  434. {3 << GiB, 2 << MiB},
  435. {500 << GiB, 16 << MiB},
  436. {50000 << GiB, 16 << MiB},
  437. }
  438. for _, tc := range cases {
  439. size := BlockSize(tc.fileSize)
  440. if size != tc.blockSize {
  441. t.Errorf("BlockSize(%d), size=%d, expected %d", tc.fileSize, size, tc.blockSize)
  442. }
  443. }
  444. }
  445. var blockSize int
  446. func BenchmarkBlockSize(b *testing.B) {
  447. for i := 0; i < b.N; i++ {
  448. blockSize = BlockSize(16 << 30)
  449. }
  450. }
  451. func TestLocalFlagBits(t *testing.T) {
  452. var f FileInfo
  453. if f.IsIgnored() || f.MustRescan() || f.IsInvalid() {
  454. t.Error("file should have no weird bits set by default")
  455. }
  456. f.SetIgnored(42)
  457. if !f.IsIgnored() || f.MustRescan() || !f.IsInvalid() {
  458. t.Error("file should be ignored and invalid")
  459. }
  460. f.SetMustRescan(42)
  461. if f.IsIgnored() || !f.MustRescan() || !f.IsInvalid() {
  462. t.Error("file should be must-rescan and invalid")
  463. }
  464. f.SetUnsupported(42)
  465. if f.IsIgnored() || f.MustRescan() || !f.IsInvalid() {
  466. t.Error("file should be invalid")
  467. }
  468. }
  469. func TestIsEquivalent(t *testing.T) {
  470. b := func(v bool) *bool {
  471. return &v
  472. }
  473. type testCase struct {
  474. a FileInfo
  475. b FileInfo
  476. ignPerms *bool // nil means should not matter, we'll test both variants
  477. ignBlocks *bool
  478. ignFlags uint32
  479. eq bool
  480. }
  481. cases := []testCase{
  482. // Empty FileInfos are equivalent
  483. {eq: true},
  484. // Various basic attributes, all of which cause ineqality when
  485. // they differ
  486. {
  487. a: FileInfo{Name: "foo"},
  488. b: FileInfo{Name: "bar"},
  489. eq: false,
  490. },
  491. {
  492. a: FileInfo{Type: FileInfoTypeFile},
  493. b: FileInfo{Type: FileInfoTypeDirectory},
  494. eq: false,
  495. },
  496. {
  497. a: FileInfo{Size: 1234},
  498. b: FileInfo{Size: 2345},
  499. eq: false,
  500. },
  501. {
  502. a: FileInfo{Deleted: false},
  503. b: FileInfo{Deleted: true},
  504. eq: false,
  505. },
  506. {
  507. a: FileInfo{RawInvalid: false},
  508. b: FileInfo{RawInvalid: true},
  509. eq: false,
  510. },
  511. {
  512. a: FileInfo{ModifiedS: 1234},
  513. b: FileInfo{ModifiedS: 2345},
  514. eq: false,
  515. },
  516. {
  517. a: FileInfo{ModifiedNs: 1234},
  518. b: FileInfo{ModifiedNs: 2345},
  519. eq: false,
  520. },
  521. // Special handling of local flags and invalidity. "MustRescan"
  522. // files are never equivalent to each other. Otherwise, equivalence
  523. // is based just on whether the file becomes IsInvalid() or not, not
  524. // the specific reason or flag bits.
  525. {
  526. a: FileInfo{LocalFlags: FlagLocalMustRescan},
  527. b: FileInfo{LocalFlags: FlagLocalMustRescan},
  528. eq: false,
  529. },
  530. {
  531. a: FileInfo{RawInvalid: true},
  532. b: FileInfo{RawInvalid: true},
  533. eq: true,
  534. },
  535. {
  536. a: FileInfo{LocalFlags: FlagLocalUnsupported},
  537. b: FileInfo{LocalFlags: FlagLocalUnsupported},
  538. eq: true,
  539. },
  540. {
  541. a: FileInfo{RawInvalid: true},
  542. b: FileInfo{LocalFlags: FlagLocalUnsupported},
  543. eq: true,
  544. },
  545. {
  546. a: FileInfo{LocalFlags: 0},
  547. b: FileInfo{LocalFlags: FlagLocalReceiveOnly},
  548. eq: false,
  549. },
  550. {
  551. a: FileInfo{LocalFlags: 0},
  552. b: FileInfo{LocalFlags: FlagLocalReceiveOnly},
  553. ignFlags: FlagLocalReceiveOnly,
  554. eq: true,
  555. },
  556. // Difference in blocks is not OK
  557. {
  558. a: FileInfo{Blocks: []BlockInfo{{Hash: []byte{1, 2, 3, 4}}}},
  559. b: FileInfo{Blocks: []BlockInfo{{Hash: []byte{2, 3, 4, 5}}}},
  560. ignBlocks: b(false),
  561. eq: false,
  562. },
  563. // ... unless we say it is
  564. {
  565. a: FileInfo{Blocks: []BlockInfo{{Hash: []byte{1, 2, 3, 4}}}},
  566. b: FileInfo{Blocks: []BlockInfo{{Hash: []byte{2, 3, 4, 5}}}},
  567. ignBlocks: b(true),
  568. eq: true,
  569. },
  570. // Difference in permissions is not OK.
  571. {
  572. a: FileInfo{Permissions: 0444},
  573. b: FileInfo{Permissions: 0666},
  574. ignPerms: b(false),
  575. eq: false,
  576. },
  577. // ... unless we say it is
  578. {
  579. a: FileInfo{Permissions: 0666},
  580. b: FileInfo{Permissions: 0444},
  581. ignPerms: b(true),
  582. eq: true,
  583. },
  584. // These attributes are not checked at all
  585. {
  586. a: FileInfo{NoPermissions: false},
  587. b: FileInfo{NoPermissions: true},
  588. eq: true,
  589. },
  590. {
  591. a: FileInfo{Version: Vector{Counters: []Counter{{ID: 1, Value: 42}}}},
  592. b: FileInfo{Version: Vector{Counters: []Counter{{ID: 42, Value: 1}}}},
  593. eq: true,
  594. },
  595. {
  596. a: FileInfo{Sequence: 1},
  597. b: FileInfo{Sequence: 2},
  598. eq: true,
  599. },
  600. // The block size is not checked (but this would fail the blocks
  601. // check in real world)
  602. {
  603. a: FileInfo{RawBlockSize: 1},
  604. b: FileInfo{RawBlockSize: 2},
  605. eq: true,
  606. },
  607. // The symlink target is checked for symlinks
  608. {
  609. a: FileInfo{Type: FileInfoTypeSymlink, SymlinkTarget: "a"},
  610. b: FileInfo{Type: FileInfoTypeSymlink, SymlinkTarget: "b"},
  611. eq: false,
  612. },
  613. // ... but not for non-symlinks
  614. {
  615. a: FileInfo{Type: FileInfoTypeFile, SymlinkTarget: "a"},
  616. b: FileInfo{Type: FileInfoTypeFile, SymlinkTarget: "b"},
  617. eq: true,
  618. },
  619. }
  620. if runtime.GOOS == "windows" {
  621. // On windows we only check the user writable bit of the permission
  622. // set, so these are equivalent.
  623. cases = append(cases, testCase{
  624. a: FileInfo{Permissions: 0777},
  625. b: FileInfo{Permissions: 0600},
  626. ignPerms: b(false),
  627. eq: true,
  628. })
  629. }
  630. for i, tc := range cases {
  631. // Check the standard attributes with all permutations of the
  632. // special ignore flags, unless the value of those flags are given
  633. // in the tests.
  634. for _, ignPerms := range []bool{true, false} {
  635. for _, ignBlocks := range []bool{true, false} {
  636. if tc.ignPerms != nil && *tc.ignPerms != ignPerms {
  637. continue
  638. }
  639. if tc.ignBlocks != nil && *tc.ignBlocks != ignBlocks {
  640. continue
  641. }
  642. if res := tc.a.isEquivalent(tc.b, ignPerms, ignBlocks, tc.ignFlags); res != tc.eq {
  643. t.Errorf("Case %d:\na: %v\nb: %v\na.IsEquivalent(b, %v, %v) => %v, expected %v", i, tc.a, tc.b, ignPerms, ignBlocks, res, tc.eq)
  644. }
  645. if res := tc.b.isEquivalent(tc.a, ignPerms, ignBlocks, tc.ignFlags); res != tc.eq {
  646. t.Errorf("Case %d:\na: %v\nb: %v\nb.IsEquivalent(a, %v, %v) => %v, expected %v", i, tc.a, tc.b, ignPerms, ignBlocks, res, tc.eq)
  647. }
  648. }
  649. }
  650. }
  651. }
  652. func TestSha256OfEmptyBlock(t *testing.T) {
  653. // every block size should have a correct entry in sha256OfEmptyBlock
  654. for blockSize := MinBlockSize; blockSize <= MaxBlockSize; blockSize *= 2 {
  655. expected := sha256.Sum256(make([]byte, blockSize))
  656. if sha256OfEmptyBlock[blockSize] != expected {
  657. t.Error("missing or wrong hash for block of size", blockSize)
  658. }
  659. }
  660. }
  661. // TestClusterConfigAfterClose checks that ClusterConfig does not deadlock when
  662. // ClusterConfig is called on a closed connection.
  663. func TestClusterConfigAfterClose(t *testing.T) {
  664. m := newTestModel()
  665. c := NewConnection(c0ID, &testutils.BlockingRW{}, &testutils.BlockingRW{}, m, "name", CompressAlways).(wireFormatConnection).Connection.(*rawConnection)
  666. c.Start()
  667. c.internalClose(errManual)
  668. done := make(chan struct{})
  669. go func() {
  670. c.ClusterConfig(ClusterConfig{})
  671. close(done)
  672. }()
  673. select {
  674. case <-done:
  675. case <-time.After(time.Second):
  676. t.Fatal("timed out before Cluster Config returned")
  677. }
  678. }