filesystem_storage_test.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package filesystem
  2. import (
  3. "context"
  4. "io/ioutil"
  5. "os"
  6. "reflect"
  7. "sort"
  8. "testing"
  9. "time"
  10. "github.com/kopia/kopia/repo/blob"
  11. "github.com/kopia/kopia/internal/blobtesting"
  12. )
  13. func TestFileStorage(t *testing.T) {
  14. t.Parallel()
  15. ctx := context.Background()
  16. // Test varioush shard configurations.
  17. for _, shardSpec := range [][]int{
  18. {0},
  19. {1},
  20. {3, 3},
  21. {2},
  22. {1, 1},
  23. {1, 2},
  24. {2, 2, 2},
  25. } {
  26. path, _ := ioutil.TempDir("", "r-fs")
  27. defer os.RemoveAll(path)
  28. r, err := New(ctx, &Options{
  29. Path: path,
  30. DirectoryShards: shardSpec,
  31. })
  32. if r == nil || err != nil {
  33. t.Errorf("unexpected result: %v %v", r, err)
  34. }
  35. blobtesting.VerifyStorage(ctx, t, r)
  36. blobtesting.AssertConnectionInfoRoundTrips(ctx, t, r)
  37. if err := r.Close(ctx); err != nil {
  38. t.Fatalf("err: %v", err)
  39. }
  40. }
  41. }
  42. const (
  43. t1 = "392ee1bc299db9f235e046a62625afb84902"
  44. t2 = "2a7ff4f29eddbcd4c18fa9e73fec20bbb71f"
  45. t3 = "0dae5918f83e6a24c8b3e274ca1026e43f24"
  46. )
  47. func TestFileStorageTouch(t *testing.T) {
  48. t.Parallel()
  49. ctx := context.Background()
  50. path, _ := ioutil.TempDir("", "r-fs")
  51. defer os.RemoveAll(path)
  52. r, err := New(ctx, &Options{
  53. Path: path,
  54. })
  55. if r == nil || err != nil {
  56. t.Errorf("unexpected result: %v %v", r, err)
  57. }
  58. fs := r.(*fsStorage)
  59. assertNoError(t, fs.PutBlob(ctx, t1, []byte{1}))
  60. time.Sleep(1 * time.Second) // sleep a bit to accommodate Apple filesystems with low timestamp resolution
  61. assertNoError(t, fs.PutBlob(ctx, t2, []byte{1}))
  62. time.Sleep(1 * time.Second)
  63. assertNoError(t, fs.PutBlob(ctx, t3, []byte{1}))
  64. verifyBlobTimestampOrder(t, fs, t1, t2, t3)
  65. assertNoError(t, fs.TouchBlob(ctx, t2, 1*time.Hour)) // has no effect, all timestamps are very new
  66. verifyBlobTimestampOrder(t, fs, t1, t2, t3)
  67. assertNoError(t, fs.TouchBlob(ctx, t1, 0)) // moves t1 to the top of the pile
  68. verifyBlobTimestampOrder(t, fs, t2, t3, t1)
  69. time.Sleep(1 * time.Second)
  70. assertNoError(t, fs.TouchBlob(ctx, t2, 0)) // moves t2 to the top of the pile
  71. verifyBlobTimestampOrder(t, fs, t3, t1, t2)
  72. time.Sleep(1 * time.Second)
  73. assertNoError(t, fs.TouchBlob(ctx, t1, 0)) // moves t1 to the top of the pile
  74. verifyBlobTimestampOrder(t, fs, t3, t2, t1)
  75. }
  76. func verifyBlobTimestampOrder(t *testing.T, st blob.Storage, want ...blob.ID) {
  77. blobs, err := blob.ListAllBlobs(context.Background(), st, "")
  78. if err != nil {
  79. t.Errorf("error listing blobs: %v", err)
  80. return
  81. }
  82. sort.Slice(blobs, func(i, j int) bool {
  83. return blobs[i].Timestamp.Before(blobs[j].Timestamp)
  84. })
  85. var got []blob.ID
  86. for _, b := range blobs {
  87. got = append(got, b.BlobID)
  88. }
  89. if !reflect.DeepEqual(got, want) {
  90. t.Errorf("incorrect blob order: %v, wanted %v", blobs, want)
  91. }
  92. }
  93. func assertNoError(t *testing.T, err error) {
  94. t.Helper()
  95. if err != nil {
  96. t.Errorf("err: %v", err)
  97. }
  98. }