protocol_test.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978
  1. // Copyright (C) 2014 The Protocol Authors.
  2. package protocol
  3. import (
  4. "bytes"
  5. "context"
  6. "crypto/sha256"
  7. "encoding/hex"
  8. "encoding/json"
  9. "errors"
  10. "io"
  11. "io/ioutil"
  12. "runtime"
  13. "sync"
  14. "testing"
  15. "testing/quick"
  16. "time"
  17. "github.com/syncthing/syncthing/lib/rand"
  18. "github.com/syncthing/syncthing/lib/testutils"
  19. )
  20. var (
  21. c0ID = NewDeviceID([]byte{1})
  22. c1ID = NewDeviceID([]byte{2})
  23. quickCfg = &quick.Config{}
  24. )
  25. func TestPing(t *testing.T) {
  26. ar, aw := io.Pipe()
  27. br, bw := io.Pipe()
  28. c0 := NewConnection(c0ID, ar, bw, testutils.NoopCloser{}, newTestModel(), new(mockedConnectionInfo), CompressionAlways).(wireFormatConnection).Connection.(*rawConnection)
  29. c0.Start()
  30. defer closeAndWait(c0, ar, bw)
  31. c1 := NewConnection(c1ID, br, aw, testutils.NoopCloser{}, newTestModel(), new(mockedConnectionInfo), CompressionAlways).(wireFormatConnection).Connection.(*rawConnection)
  32. c1.Start()
  33. defer closeAndWait(c1, ar, bw)
  34. c0.ClusterConfig(ClusterConfig{})
  35. c1.ClusterConfig(ClusterConfig{})
  36. if ok := c0.ping(); !ok {
  37. t.Error("c0 ping failed")
  38. }
  39. if ok := c1.ping(); !ok {
  40. t.Error("c1 ping failed")
  41. }
  42. }
  43. var errManual = errors.New("manual close")
  44. func TestClose(t *testing.T) {
  45. m0 := newTestModel()
  46. m1 := newTestModel()
  47. ar, aw := io.Pipe()
  48. br, bw := io.Pipe()
  49. c0 := NewConnection(c0ID, ar, bw, testutils.NoopCloser{}, m0, new(mockedConnectionInfo), CompressionAlways).(wireFormatConnection).Connection.(*rawConnection)
  50. c0.Start()
  51. defer closeAndWait(c0, ar, bw)
  52. c1 := NewConnection(c1ID, br, aw, testutils.NoopCloser{}, m1, new(mockedConnectionInfo), CompressionAlways)
  53. c1.Start()
  54. defer closeAndWait(c1, ar, bw)
  55. c0.ClusterConfig(ClusterConfig{})
  56. c1.ClusterConfig(ClusterConfig{})
  57. c0.internalClose(errManual)
  58. <-c0.closed
  59. if err := m0.closedError(); err != errManual {
  60. t.Fatal("Connection should be closed")
  61. }
  62. // None of these should panic, some should return an error
  63. if c0.ping() {
  64. t.Error("Ping should not return true")
  65. }
  66. ctx := context.Background()
  67. c0.Index(ctx, "default", nil)
  68. c0.Index(ctx, "default", nil)
  69. if _, err := c0.Request(ctx, "default", "foo", 0, 0, 0, nil, 0, false); err == nil {
  70. t.Error("Request should return an error")
  71. }
  72. }
  73. // TestCloseOnBlockingSend checks that the connection does not deadlock when
  74. // Close is called while the underlying connection is broken (send blocks).
  75. // https://github.com/syncthing/syncthing/pull/5442
  76. func TestCloseOnBlockingSend(t *testing.T) {
  77. oldCloseTimeout := CloseTimeout
  78. CloseTimeout = 100 * time.Millisecond
  79. defer func() {
  80. CloseTimeout = oldCloseTimeout
  81. }()
  82. m := newTestModel()
  83. rw := testutils.NewBlockingRW()
  84. c := NewConnection(c0ID, rw, rw, testutils.NoopCloser{}, m, new(mockedConnectionInfo), CompressionAlways).(wireFormatConnection).Connection.(*rawConnection)
  85. c.Start()
  86. defer closeAndWait(c, rw)
  87. wg := sync.WaitGroup{}
  88. wg.Add(1)
  89. go func() {
  90. c.ClusterConfig(ClusterConfig{})
  91. wg.Done()
  92. }()
  93. wg.Add(1)
  94. go func() {
  95. c.Close(errManual)
  96. wg.Done()
  97. }()
  98. // This simulates an error from ping timeout
  99. wg.Add(1)
  100. go func() {
  101. c.internalClose(ErrTimeout)
  102. wg.Done()
  103. }()
  104. done := make(chan struct{})
  105. go func() {
  106. wg.Wait()
  107. close(done)
  108. }()
  109. select {
  110. case <-done:
  111. case <-time.After(time.Second):
  112. t.Fatal("timed out before all functions returned")
  113. }
  114. }
  115. func TestCloseRace(t *testing.T) {
  116. indexReceived := make(chan struct{})
  117. unblockIndex := make(chan struct{})
  118. m0 := newTestModel()
  119. m0.indexFn = func(_ DeviceID, _ string, _ []FileInfo) {
  120. close(indexReceived)
  121. <-unblockIndex
  122. }
  123. m1 := newTestModel()
  124. ar, aw := io.Pipe()
  125. br, bw := io.Pipe()
  126. c0 := NewConnection(c0ID, ar, bw, testutils.NoopCloser{}, m0, new(mockedConnectionInfo), CompressionNever).(wireFormatConnection).Connection.(*rawConnection)
  127. c0.Start()
  128. defer closeAndWait(c0, ar, bw)
  129. c1 := NewConnection(c1ID, br, aw, testutils.NoopCloser{}, m1, new(mockedConnectionInfo), CompressionNever)
  130. c1.Start()
  131. defer closeAndWait(c1, ar, bw)
  132. c0.ClusterConfig(ClusterConfig{})
  133. c1.ClusterConfig(ClusterConfig{})
  134. c1.Index(context.Background(), "default", nil)
  135. select {
  136. case <-indexReceived:
  137. case <-time.After(time.Second):
  138. t.Fatal("timed out before receiving index")
  139. }
  140. go c0.internalClose(errManual)
  141. select {
  142. case <-c0.closed:
  143. case <-time.After(time.Second):
  144. t.Fatal("timed out before c0.closed was closed")
  145. }
  146. select {
  147. case <-m0.closedCh:
  148. t.Errorf("receiver.Closed called before receiver.Index")
  149. default:
  150. }
  151. close(unblockIndex)
  152. if err := m0.closedError(); err != errManual {
  153. t.Fatal("Connection should be closed")
  154. }
  155. }
  156. func TestClusterConfigFirst(t *testing.T) {
  157. m := newTestModel()
  158. rw := testutils.NewBlockingRW()
  159. c := NewConnection(c0ID, rw, &testutils.NoopRW{}, testutils.NoopCloser{}, m, new(mockedConnectionInfo), CompressionAlways).(wireFormatConnection).Connection.(*rawConnection)
  160. c.Start()
  161. defer closeAndWait(c, rw)
  162. select {
  163. case c.outbox <- asyncMessage{&Ping{}, nil}:
  164. t.Fatal("able to send ping before cluster config")
  165. case <-time.After(100 * time.Millisecond):
  166. // Allow some time for c.writerLoop to setup after c.Start
  167. }
  168. c.ClusterConfig(ClusterConfig{})
  169. done := make(chan struct{})
  170. if ok := c.send(context.Background(), &Ping{}, done); !ok {
  171. t.Fatal("send ping after cluster config returned false")
  172. }
  173. select {
  174. case <-done:
  175. case <-time.After(time.Second):
  176. t.Fatal("timed out before ping was sent")
  177. }
  178. done = make(chan struct{})
  179. go func() {
  180. c.internalClose(errManual)
  181. close(done)
  182. }()
  183. select {
  184. case <-done:
  185. case <-time.After(5 * time.Second):
  186. t.Fatal("Close didn't return before timeout")
  187. }
  188. if err := m.closedError(); err != errManual {
  189. t.Fatal("Connection should be closed")
  190. }
  191. }
  192. // TestCloseTimeout checks that calling Close times out and proceeds, if sending
  193. // the close message does not succeed.
  194. func TestCloseTimeout(t *testing.T) {
  195. oldCloseTimeout := CloseTimeout
  196. CloseTimeout = 100 * time.Millisecond
  197. defer func() {
  198. CloseTimeout = oldCloseTimeout
  199. }()
  200. m := newTestModel()
  201. rw := testutils.NewBlockingRW()
  202. c := NewConnection(c0ID, rw, rw, testutils.NoopCloser{}, m, new(mockedConnectionInfo), CompressionAlways).(wireFormatConnection).Connection.(*rawConnection)
  203. c.Start()
  204. defer closeAndWait(c, rw)
  205. done := make(chan struct{})
  206. go func() {
  207. c.Close(errManual)
  208. close(done)
  209. }()
  210. select {
  211. case <-done:
  212. case <-time.After(5 * CloseTimeout):
  213. t.Fatal("timed out before Close returned")
  214. }
  215. }
  216. func TestMarshalIndexMessage(t *testing.T) {
  217. if testing.Short() {
  218. quickCfg.MaxCount = 10
  219. }
  220. f := func(m1 Index) bool {
  221. if len(m1.Files) == 0 {
  222. m1.Files = nil
  223. }
  224. for i, f := range m1.Files {
  225. if len(f.BlocksHash) == 0 {
  226. m1.Files[i].BlocksHash = nil
  227. }
  228. if len(f.VersionHash) == 0 {
  229. m1.Files[i].VersionHash = nil
  230. }
  231. if len(f.Blocks) == 0 {
  232. m1.Files[i].Blocks = nil
  233. } else {
  234. for j := range f.Blocks {
  235. f.Blocks[j].Offset = 0
  236. if len(f.Blocks[j].Hash) == 0 {
  237. f.Blocks[j].Hash = nil
  238. }
  239. }
  240. }
  241. if len(f.Version.Counters) == 0 {
  242. m1.Files[i].Version.Counters = nil
  243. }
  244. if len(f.Encrypted) == 0 {
  245. m1.Files[i].Encrypted = nil
  246. }
  247. }
  248. return testMarshal(t, "index", &m1, &Index{})
  249. }
  250. if err := quick.Check(f, quickCfg); err != nil {
  251. t.Error(err)
  252. }
  253. }
  254. func TestMarshalRequestMessage(t *testing.T) {
  255. if testing.Short() {
  256. quickCfg.MaxCount = 10
  257. }
  258. f := func(m1 Request) bool {
  259. if len(m1.Hash) == 0 {
  260. m1.Hash = nil
  261. }
  262. return testMarshal(t, "request", &m1, &Request{})
  263. }
  264. if err := quick.Check(f, quickCfg); err != nil {
  265. t.Error(err)
  266. }
  267. }
  268. func TestMarshalResponseMessage(t *testing.T) {
  269. if testing.Short() {
  270. quickCfg.MaxCount = 10
  271. }
  272. f := func(m1 Response) bool {
  273. if len(m1.Data) == 0 {
  274. m1.Data = nil
  275. }
  276. return testMarshal(t, "response", &m1, &Response{})
  277. }
  278. if err := quick.Check(f, quickCfg); err != nil {
  279. t.Error(err)
  280. }
  281. }
  282. func TestMarshalClusterConfigMessage(t *testing.T) {
  283. if testing.Short() {
  284. quickCfg.MaxCount = 10
  285. }
  286. f := func(m1 ClusterConfig) bool {
  287. if len(m1.Folders) == 0 {
  288. m1.Folders = nil
  289. }
  290. for i := range m1.Folders {
  291. if len(m1.Folders[i].Devices) == 0 {
  292. m1.Folders[i].Devices = nil
  293. }
  294. for j := range m1.Folders[i].Devices {
  295. if len(m1.Folders[i].Devices[j].Addresses) == 0 {
  296. m1.Folders[i].Devices[j].Addresses = nil
  297. }
  298. if len(m1.Folders[i].Devices[j].EncryptionPasswordToken) == 0 {
  299. m1.Folders[i].Devices[j].EncryptionPasswordToken = nil
  300. }
  301. }
  302. }
  303. return testMarshal(t, "clusterconfig", &m1, &ClusterConfig{})
  304. }
  305. if err := quick.Check(f, quickCfg); err != nil {
  306. t.Error(err)
  307. }
  308. }
  309. func TestMarshalCloseMessage(t *testing.T) {
  310. if testing.Short() {
  311. quickCfg.MaxCount = 10
  312. }
  313. f := func(m1 Close) bool {
  314. return testMarshal(t, "close", &m1, &Close{})
  315. }
  316. if err := quick.Check(f, quickCfg); err != nil {
  317. t.Error(err)
  318. }
  319. }
  320. func TestMarshalFDPU(t *testing.T) {
  321. if testing.Short() {
  322. quickCfg.MaxCount = 10
  323. }
  324. f := func(m1 FileDownloadProgressUpdate) bool {
  325. if len(m1.Version.Counters) == 0 {
  326. m1.Version.Counters = nil
  327. }
  328. if len(m1.BlockIndexes) == 0 {
  329. m1.BlockIndexes = nil
  330. }
  331. return testMarshal(t, "fdpu", &m1, &FileDownloadProgressUpdate{})
  332. }
  333. if err := quick.Check(f, quickCfg); err != nil {
  334. t.Error(err)
  335. }
  336. }
  337. func TestUnmarshalFDPUv16v17(t *testing.T) {
  338. var fdpu FileDownloadProgressUpdate
  339. m0, _ := hex.DecodeString("08cda1e2e3011278f3918787f3b89b8af2958887f0aa9389f3a08588f3aa8f96f39aa8a5f48b9188f19286a0f3848da4f3aba799f3beb489f0a285b9f487b684f2a3bda2f48598b4f2938a89f2a28badf187a0a2f2aebdbdf4849494f4808fbbf2b3a2adf2bb95bff0a6ada4f198ab9af29a9c8bf1abb793f3baabb2f188a6ba1a0020bb9390f60220f6d9e42220b0c7e2b2fdffffffff0120fdb2dfcdfbffffffff0120cedab1d50120bd8784c0feffffffff0120ace99591fdffffffff0120eed7d09af9ffffffff01")
  340. if err := fdpu.Unmarshal(m0); err != nil {
  341. t.Fatal("Unmarshalling message from v0.14.16:", err)
  342. }
  343. m1, _ := hex.DecodeString("0880f1969905128401f099b192f0abb1b9f3b280aff19e9aa2f3b89e84f484b39df1a7a6b0f1aea4b1f0adac94f3b39caaf1939281f1928a8af0abb1b0f0a8b3b3f3a88e94f2bd85acf29c97a9f2969da6f0b7a188f1908ea2f09a9c9bf19d86a6f29aada8f389bb95f0bf9d88f1a09d89f1b1a4b5f29b9eabf298a59df1b2a589f2979ebdf0b69880f18986b21a440a1508c7d8fb8897ca93d90910e8c4d8e8f2f8f0ccee010a1508afa8ffd8c085b393c50110e5bdedc3bddefe9b0b0a1408a1bedddba4cac5da3c10b8e5d9958ca7e3ec19225ae2f88cb2f8ffffffff018ceda99cfbffffffff01b9c298a407e295e8e9fcffffffff01f3b9ade5fcffffffff01c08bfea9fdffffffff01a2c2e5e1ffffffffff0186dcc5dafdffffffff01e9ffc7e507c9d89db8fdffffffff01")
  344. if err := fdpu.Unmarshal(m1); err != nil {
  345. t.Fatal("Unmarshalling message from v0.14.16:", err)
  346. }
  347. }
  348. func testMarshal(t *testing.T, prefix string, m1, m2 message) bool {
  349. buf, err := m1.Marshal()
  350. if err != nil {
  351. t.Fatal(err)
  352. }
  353. err = m2.Unmarshal(buf)
  354. if err != nil {
  355. t.Fatal(err)
  356. }
  357. bs1, _ := json.MarshalIndent(m1, "", " ")
  358. bs2, _ := json.MarshalIndent(m2, "", " ")
  359. if !bytes.Equal(bs1, bs2) {
  360. ioutil.WriteFile(prefix+"-1.txt", bs1, 0644)
  361. ioutil.WriteFile(prefix+"-2.txt", bs2, 0644)
  362. return false
  363. }
  364. return true
  365. }
  366. func TestLZ4Compression(t *testing.T) {
  367. c := new(rawConnection)
  368. for i := 0; i < 10; i++ {
  369. dataLen := 150 + rand.Intn(150)
  370. data := make([]byte, dataLen)
  371. _, err := io.ReadFull(rand.Reader, data[100:])
  372. if err != nil {
  373. t.Fatal(err)
  374. }
  375. comp, err := c.lz4Compress(data)
  376. if err != nil {
  377. t.Errorf("compressing %d bytes: %v", dataLen, err)
  378. continue
  379. }
  380. res, err := c.lz4Decompress(comp)
  381. if err != nil {
  382. t.Errorf("decompressing %d bytes to %d: %v", len(comp), dataLen, err)
  383. continue
  384. }
  385. if len(res) != len(data) {
  386. t.Errorf("Incorrect len %d != expected %d", len(res), len(data))
  387. }
  388. if !bytes.Equal(data, res) {
  389. t.Error("Incorrect decompressed data")
  390. }
  391. t.Logf("OK #%d, %d -> %d -> %d", i, dataLen, len(comp), dataLen)
  392. }
  393. }
  394. func TestStressLZ4CompressGrows(t *testing.T) {
  395. c := new(rawConnection)
  396. success := 0
  397. for i := 0; i < 100; i++ {
  398. // Create a slize that is precisely one min block size, fill it with
  399. // random data. This shouldn't compress at all, so will in fact
  400. // become larger when LZ4 does its thing.
  401. data := make([]byte, MinBlockSize)
  402. if _, err := rand.Reader.Read(data); err != nil {
  403. t.Fatal("randomness failure")
  404. }
  405. comp, err := c.lz4Compress(data)
  406. if err != nil {
  407. t.Fatal("unexpected compression error: ", err)
  408. }
  409. if len(comp) < len(data) {
  410. // data size should grow. We must have been really unlucky in
  411. // the random generation, try again.
  412. continue
  413. }
  414. // Putting it into the buffer pool shouldn't panic because the block
  415. // should come from there to begin with.
  416. BufferPool.Put(comp)
  417. success++
  418. }
  419. if success == 0 {
  420. t.Fatal("unable to find data that grows when compressed")
  421. }
  422. }
  423. func TestCheckFilename(t *testing.T) {
  424. cases := []struct {
  425. name string
  426. ok bool
  427. }{
  428. // Valid filenames
  429. {"foo", true},
  430. {"foo/bar/baz", true},
  431. {"foo/bar:baz", true}, // colon is ok in general, will be filtered on windows
  432. {`\`, true}, // path separator on the wire is forward slash, so as above
  433. {`\.`, true},
  434. {`\..`, true},
  435. {".foo", true},
  436. {"foo..", true},
  437. // Invalid filenames
  438. {"foo/..", false},
  439. {"foo/../bar", false},
  440. {"../foo/../bar", false},
  441. {"", false},
  442. {".", false},
  443. {"..", false},
  444. {"/", false},
  445. {"/.", false},
  446. {"/..", false},
  447. {"/foo", false},
  448. {"./foo", false},
  449. {"foo./", false},
  450. {"foo/.", false},
  451. {"foo/", false},
  452. }
  453. for _, tc := range cases {
  454. err := checkFilename(tc.name)
  455. if (err == nil) != tc.ok {
  456. t.Errorf("Unexpected result for checkFilename(%q): %v", tc.name, err)
  457. }
  458. }
  459. }
  460. func TestCheckConsistency(t *testing.T) {
  461. cases := []struct {
  462. fi FileInfo
  463. ok bool
  464. }{
  465. {
  466. // valid
  467. fi: FileInfo{
  468. Name: "foo",
  469. Type: FileInfoTypeFile,
  470. Blocks: []BlockInfo{{Size: 1234, Offset: 0, Hash: []byte{1, 2, 3, 4}}},
  471. },
  472. ok: true,
  473. },
  474. {
  475. // deleted with blocks
  476. fi: FileInfo{
  477. Name: "foo",
  478. Deleted: true,
  479. Type: FileInfoTypeFile,
  480. Blocks: []BlockInfo{{Size: 1234, Offset: 0, Hash: []byte{1, 2, 3, 4}}},
  481. },
  482. ok: false,
  483. },
  484. {
  485. // no blocks
  486. fi: FileInfo{
  487. Name: "foo",
  488. Type: FileInfoTypeFile,
  489. },
  490. ok: false,
  491. },
  492. {
  493. // directory with blocks
  494. fi: FileInfo{
  495. Name: "foo",
  496. Type: FileInfoTypeDirectory,
  497. Blocks: []BlockInfo{{Size: 1234, Offset: 0, Hash: []byte{1, 2, 3, 4}}},
  498. },
  499. ok: false,
  500. },
  501. }
  502. for _, tc := range cases {
  503. err := checkFileInfoConsistency(tc.fi)
  504. if tc.ok && err != nil {
  505. t.Errorf("Unexpected error %v (want nil) for %v", err, tc.fi)
  506. }
  507. if !tc.ok && err == nil {
  508. t.Errorf("Unexpected nil error for %v", tc.fi)
  509. }
  510. }
  511. }
  512. func TestBlockSize(t *testing.T) {
  513. cases := []struct {
  514. fileSize int64
  515. blockSize int
  516. }{
  517. {1 << KiB, 128 << KiB},
  518. {1 << MiB, 128 << KiB},
  519. {499 << MiB, 256 << KiB},
  520. {500 << MiB, 512 << KiB},
  521. {501 << MiB, 512 << KiB},
  522. {1 << GiB, 1 << MiB},
  523. {2 << GiB, 2 << MiB},
  524. {3 << GiB, 2 << MiB},
  525. {500 << GiB, 16 << MiB},
  526. {50000 << GiB, 16 << MiB},
  527. }
  528. for _, tc := range cases {
  529. size := BlockSize(tc.fileSize)
  530. if size != tc.blockSize {
  531. t.Errorf("BlockSize(%d), size=%d, expected %d", tc.fileSize, size, tc.blockSize)
  532. }
  533. }
  534. }
  535. var blockSize int
  536. func BenchmarkBlockSize(b *testing.B) {
  537. for i := 0; i < b.N; i++ {
  538. blockSize = BlockSize(16 << 30)
  539. }
  540. }
  541. func TestLocalFlagBits(t *testing.T) {
  542. var f FileInfo
  543. if f.IsIgnored() || f.MustRescan() || f.IsInvalid() {
  544. t.Error("file should have no weird bits set by default")
  545. }
  546. f.SetIgnored()
  547. if !f.IsIgnored() || f.MustRescan() || !f.IsInvalid() {
  548. t.Error("file should be ignored and invalid")
  549. }
  550. f.SetMustRescan()
  551. if f.IsIgnored() || !f.MustRescan() || !f.IsInvalid() {
  552. t.Error("file should be must-rescan and invalid")
  553. }
  554. f.SetUnsupported()
  555. if f.IsIgnored() || f.MustRescan() || !f.IsInvalid() {
  556. t.Error("file should be invalid")
  557. }
  558. }
  559. func TestIsEquivalent(t *testing.T) {
  560. b := func(v bool) *bool {
  561. return &v
  562. }
  563. type testCase struct {
  564. a FileInfo
  565. b FileInfo
  566. ignPerms *bool // nil means should not matter, we'll test both variants
  567. ignBlocks *bool
  568. ignFlags uint32
  569. eq bool
  570. }
  571. cases := []testCase{
  572. // Empty FileInfos are equivalent
  573. {eq: true},
  574. // Various basic attributes, all of which cause ineqality when
  575. // they differ
  576. {
  577. a: FileInfo{Name: "foo"},
  578. b: FileInfo{Name: "bar"},
  579. eq: false,
  580. },
  581. {
  582. a: FileInfo{Type: FileInfoTypeFile},
  583. b: FileInfo{Type: FileInfoTypeDirectory},
  584. eq: false,
  585. },
  586. {
  587. a: FileInfo{Size: 1234},
  588. b: FileInfo{Size: 2345},
  589. eq: false,
  590. },
  591. {
  592. a: FileInfo{Deleted: false},
  593. b: FileInfo{Deleted: true},
  594. eq: false,
  595. },
  596. {
  597. a: FileInfo{RawInvalid: false},
  598. b: FileInfo{RawInvalid: true},
  599. eq: false,
  600. },
  601. {
  602. a: FileInfo{ModifiedS: 1234},
  603. b: FileInfo{ModifiedS: 2345},
  604. eq: false,
  605. },
  606. {
  607. a: FileInfo{ModifiedNs: 1234},
  608. b: FileInfo{ModifiedNs: 2345},
  609. eq: false,
  610. },
  611. // Special handling of local flags and invalidity. "MustRescan"
  612. // files are never equivalent to each other. Otherwise, equivalence
  613. // is based just on whether the file becomes IsInvalid() or not, not
  614. // the specific reason or flag bits.
  615. {
  616. a: FileInfo{LocalFlags: FlagLocalMustRescan},
  617. b: FileInfo{LocalFlags: FlagLocalMustRescan},
  618. eq: false,
  619. },
  620. {
  621. a: FileInfo{RawInvalid: true},
  622. b: FileInfo{RawInvalid: true},
  623. eq: true,
  624. },
  625. {
  626. a: FileInfo{LocalFlags: FlagLocalUnsupported},
  627. b: FileInfo{LocalFlags: FlagLocalUnsupported},
  628. eq: true,
  629. },
  630. {
  631. a: FileInfo{RawInvalid: true},
  632. b: FileInfo{LocalFlags: FlagLocalUnsupported},
  633. eq: true,
  634. },
  635. {
  636. a: FileInfo{LocalFlags: 0},
  637. b: FileInfo{LocalFlags: FlagLocalReceiveOnly},
  638. eq: false,
  639. },
  640. {
  641. a: FileInfo{LocalFlags: 0},
  642. b: FileInfo{LocalFlags: FlagLocalReceiveOnly},
  643. ignFlags: FlagLocalReceiveOnly,
  644. eq: true,
  645. },
  646. // Difference in blocks is not OK
  647. {
  648. a: FileInfo{Blocks: []BlockInfo{{Hash: []byte{1, 2, 3, 4}}}},
  649. b: FileInfo{Blocks: []BlockInfo{{Hash: []byte{2, 3, 4, 5}}}},
  650. ignBlocks: b(false),
  651. eq: false,
  652. },
  653. // ... unless we say it is
  654. {
  655. a: FileInfo{Blocks: []BlockInfo{{Hash: []byte{1, 2, 3, 4}}}},
  656. b: FileInfo{Blocks: []BlockInfo{{Hash: []byte{2, 3, 4, 5}}}},
  657. ignBlocks: b(true),
  658. eq: true,
  659. },
  660. // Difference in permissions is not OK.
  661. {
  662. a: FileInfo{Permissions: 0444},
  663. b: FileInfo{Permissions: 0666},
  664. ignPerms: b(false),
  665. eq: false,
  666. },
  667. // ... unless we say it is
  668. {
  669. a: FileInfo{Permissions: 0666},
  670. b: FileInfo{Permissions: 0444},
  671. ignPerms: b(true),
  672. eq: true,
  673. },
  674. // These attributes are not checked at all
  675. {
  676. a: FileInfo{NoPermissions: false},
  677. b: FileInfo{NoPermissions: true},
  678. eq: true,
  679. },
  680. {
  681. a: FileInfo{Version: Vector{Counters: []Counter{{ID: 1, Value: 42}}}},
  682. b: FileInfo{Version: Vector{Counters: []Counter{{ID: 42, Value: 1}}}},
  683. eq: true,
  684. },
  685. {
  686. a: FileInfo{Sequence: 1},
  687. b: FileInfo{Sequence: 2},
  688. eq: true,
  689. },
  690. // The block size is not checked (but this would fail the blocks
  691. // check in real world)
  692. {
  693. a: FileInfo{RawBlockSize: 1},
  694. b: FileInfo{RawBlockSize: 2},
  695. eq: true,
  696. },
  697. // The symlink target is checked for symlinks
  698. {
  699. a: FileInfo{Type: FileInfoTypeSymlink, SymlinkTarget: "a"},
  700. b: FileInfo{Type: FileInfoTypeSymlink, SymlinkTarget: "b"},
  701. eq: false,
  702. },
  703. // ... but not for non-symlinks
  704. {
  705. a: FileInfo{Type: FileInfoTypeFile, SymlinkTarget: "a"},
  706. b: FileInfo{Type: FileInfoTypeFile, SymlinkTarget: "b"},
  707. eq: true,
  708. },
  709. }
  710. if runtime.GOOS == "windows" {
  711. // On windows we only check the user writable bit of the permission
  712. // set, so these are equivalent.
  713. cases = append(cases, testCase{
  714. a: FileInfo{Permissions: 0777},
  715. b: FileInfo{Permissions: 0600},
  716. ignPerms: b(false),
  717. eq: true,
  718. })
  719. }
  720. for i, tc := range cases {
  721. // Check the standard attributes with all permutations of the
  722. // special ignore flags, unless the value of those flags are given
  723. // in the tests.
  724. for _, ignPerms := range []bool{true, false} {
  725. for _, ignBlocks := range []bool{true, false} {
  726. if tc.ignPerms != nil && *tc.ignPerms != ignPerms {
  727. continue
  728. }
  729. if tc.ignBlocks != nil && *tc.ignBlocks != ignBlocks {
  730. continue
  731. }
  732. if res := tc.a.isEquivalent(tc.b, 0, ignPerms, ignBlocks, tc.ignFlags); res != tc.eq {
  733. 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)
  734. }
  735. if res := tc.b.isEquivalent(tc.a, 0, ignPerms, ignBlocks, tc.ignFlags); res != tc.eq {
  736. 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)
  737. }
  738. }
  739. }
  740. }
  741. }
  742. func TestSha256OfEmptyBlock(t *testing.T) {
  743. // every block size should have a correct entry in sha256OfEmptyBlock
  744. for blockSize := MinBlockSize; blockSize <= MaxBlockSize; blockSize *= 2 {
  745. expected := sha256.Sum256(make([]byte, blockSize))
  746. if sha256OfEmptyBlock[blockSize] != expected {
  747. t.Error("missing or wrong hash for block of size", blockSize)
  748. }
  749. }
  750. }
  751. // TestClusterConfigAfterClose checks that ClusterConfig does not deadlock when
  752. // ClusterConfig is called on a closed connection.
  753. func TestClusterConfigAfterClose(t *testing.T) {
  754. m := newTestModel()
  755. rw := testutils.NewBlockingRW()
  756. c := NewConnection(c0ID, rw, rw, testutils.NoopCloser{}, m, new(mockedConnectionInfo), CompressionAlways).(wireFormatConnection).Connection.(*rawConnection)
  757. c.Start()
  758. defer closeAndWait(c, rw)
  759. c.internalClose(errManual)
  760. done := make(chan struct{})
  761. go func() {
  762. c.ClusterConfig(ClusterConfig{})
  763. close(done)
  764. }()
  765. select {
  766. case <-done:
  767. case <-time.After(time.Second):
  768. t.Fatal("timed out before Cluster Config returned")
  769. }
  770. }
  771. func TestDispatcherToCloseDeadlock(t *testing.T) {
  772. // Verify that we don't deadlock when calling Close() from within one of
  773. // the model callbacks (ClusterConfig).
  774. m := newTestModel()
  775. rw := testutils.NewBlockingRW()
  776. c := NewConnection(c0ID, rw, &testutils.NoopRW{}, testutils.NoopCloser{}, m, new(mockedConnectionInfo), CompressionAlways).(wireFormatConnection).Connection.(*rawConnection)
  777. m.ccFn = func(devID DeviceID, cc ClusterConfig) {
  778. c.Close(errManual)
  779. }
  780. c.Start()
  781. defer closeAndWait(c, rw)
  782. c.inbox <- &ClusterConfig{}
  783. select {
  784. case <-c.dispatcherLoopStopped:
  785. case <-time.After(time.Second):
  786. t.Fatal("timed out before dispatcher loop terminated")
  787. }
  788. }
  789. func TestBlocksEqual(t *testing.T) {
  790. blocksOne := []BlockInfo{{Hash: []byte{1, 2, 3, 4}}}
  791. blocksTwo := []BlockInfo{{Hash: []byte{5, 6, 7, 8}}}
  792. hashOne := []byte{42, 42, 42, 42}
  793. hashTwo := []byte{29, 29, 29, 29}
  794. cases := []struct {
  795. b1 []BlockInfo
  796. h1 []byte
  797. b2 []BlockInfo
  798. h2 []byte
  799. eq bool
  800. }{
  801. {blocksOne, hashOne, blocksOne, hashOne, true}, // everything equal
  802. {blocksOne, hashOne, blocksTwo, hashTwo, false}, // nothing equal
  803. {blocksOne, hashOne, blocksOne, nil, true}, // blocks compared
  804. {blocksOne, nil, blocksOne, nil, true}, // blocks compared
  805. {blocksOne, nil, blocksTwo, nil, false}, // blocks compared
  806. {blocksOne, hashOne, blocksTwo, hashOne, true}, // hashes equal, blocks not looked at
  807. {blocksOne, hashOne, blocksOne, hashTwo, true}, // hashes different, blocks compared
  808. {blocksOne, hashOne, blocksTwo, hashTwo, false}, // hashes different, blocks compared
  809. {blocksOne, hashOne, nil, nil, false}, // blocks is different from no blocks
  810. {blocksOne, nil, nil, nil, false}, // blocks is different from no blocks
  811. {nil, hashOne, nil, nil, true}, // nil blocks are equal, even of one side has a hash
  812. }
  813. for _, tc := range cases {
  814. f1 := FileInfo{Blocks: tc.b1, BlocksHash: tc.h1}
  815. f2 := FileInfo{Blocks: tc.b2, BlocksHash: tc.h2}
  816. if !f1.BlocksEqual(f1) {
  817. t.Error("f1 is always equal to itself", f1)
  818. }
  819. if !f2.BlocksEqual(f2) {
  820. t.Error("f2 is always equal to itself", f2)
  821. }
  822. if res := f1.BlocksEqual(f2); res != tc.eq {
  823. t.Log("f1", f1.BlocksHash, f1.Blocks)
  824. t.Log("f2", f2.BlocksHash, f2.Blocks)
  825. t.Errorf("f1.BlocksEqual(f2) == %v but should be %v", res, tc.eq)
  826. }
  827. if res := f2.BlocksEqual(f1); res != tc.eq {
  828. t.Log("f1", f1.BlocksHash, f1.Blocks)
  829. t.Log("f2", f2.BlocksHash, f2.Blocks)
  830. t.Errorf("f2.BlocksEqual(f1) == %v but should be %v", res, tc.eq)
  831. }
  832. }
  833. }
  834. func TestIndexIDString(t *testing.T) {
  835. // Index ID is a 64 bit, zero padded hex integer.
  836. var i IndexID = 42
  837. if i.String() != "0x000000000000002A" {
  838. t.Error(i.String())
  839. }
  840. }
  841. func closeAndWait(c Connection, closers ...io.Closer) {
  842. for _, closer := range closers {
  843. closer.Close()
  844. }
  845. var raw *rawConnection
  846. switch i := c.(type) {
  847. case wireFormatConnection:
  848. raw = i.Connection.(*rawConnection)
  849. case *rawConnection:
  850. raw = i
  851. }
  852. raw.internalClose(ErrClosed)
  853. raw.loopWG.Wait()
  854. }