folder_test.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // Copyright (C) 2018 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 model
  7. import (
  8. "path/filepath"
  9. "runtime"
  10. "testing"
  11. "github.com/d4l3k/messagediff"
  12. "github.com/syncthing/syncthing/lib/config"
  13. )
  14. type unifySubsCase struct {
  15. in []string // input to unifySubs
  16. exists []string // paths that exist in the database
  17. out []string // expected output
  18. }
  19. func unifySubsCases() []unifySubsCase {
  20. cases := []unifySubsCase{
  21. {
  22. // 0. trailing slashes are cleaned, known paths are just passed on
  23. []string{"foo/", "bar//"},
  24. []string{"foo", "bar"},
  25. []string{"bar", "foo"}, // the output is sorted
  26. },
  27. {
  28. // 1. "foo/bar" gets trimmed as it's covered by foo
  29. []string{"foo", "bar/", "foo/bar/"},
  30. []string{"foo", "bar"},
  31. []string{"bar", "foo"},
  32. },
  33. {
  34. // 2. "" gets simplified to the empty list; ie scan all
  35. []string{"foo", ""},
  36. []string{"foo"},
  37. nil,
  38. },
  39. {
  40. // 3. "foo/bar" is unknown, but it's kept
  41. // because its parent is known
  42. []string{"foo/bar"},
  43. []string{"foo"},
  44. []string{"foo/bar"},
  45. },
  46. {
  47. // 4. two independent known paths, both are kept
  48. // "usr/lib" is not a prefix of "usr/libexec"
  49. []string{"usr/lib", "usr/libexec"},
  50. []string{"usr", "usr/lib", "usr/libexec"},
  51. []string{"usr/lib", "usr/libexec"},
  52. },
  53. {
  54. // 5. "usr/lib" is a prefix of "usr/lib/exec"
  55. []string{"usr/lib", "usr/lib/exec"},
  56. []string{"usr", "usr/lib", "usr/libexec"},
  57. []string{"usr/lib"},
  58. },
  59. {
  60. // 6. .stignore and .stfolder are special and are passed on
  61. // verbatim even though they are unknown
  62. []string{config.DefaultMarkerName, ".stignore"},
  63. []string{},
  64. []string{config.DefaultMarkerName, ".stignore"},
  65. },
  66. {
  67. // 7. but the presence of something else unknown forces an actual
  68. // scan
  69. []string{config.DefaultMarkerName, ".stignore", "foo/bar"},
  70. []string{},
  71. []string{config.DefaultMarkerName, ".stignore", "foo"},
  72. },
  73. {
  74. // 8. explicit request to scan all
  75. nil,
  76. []string{"foo"},
  77. nil,
  78. },
  79. {
  80. // 9. empty list of subs
  81. []string{},
  82. []string{"foo"},
  83. nil,
  84. },
  85. {
  86. // 10. absolute path
  87. []string{"/foo"},
  88. []string{"foo"},
  89. []string{"foo"},
  90. },
  91. }
  92. if runtime.GOOS == "windows" {
  93. // Fixup path separators
  94. for i := range cases {
  95. for j, p := range cases[i].in {
  96. cases[i].in[j] = filepath.FromSlash(p)
  97. }
  98. for j, p := range cases[i].exists {
  99. cases[i].exists[j] = filepath.FromSlash(p)
  100. }
  101. for j, p := range cases[i].out {
  102. cases[i].out[j] = filepath.FromSlash(p)
  103. }
  104. }
  105. }
  106. return cases
  107. }
  108. func unifyExists(f string, tc unifySubsCase) bool {
  109. for _, e := range tc.exists {
  110. if f == e {
  111. return true
  112. }
  113. }
  114. return false
  115. }
  116. func TestUnifySubs(t *testing.T) {
  117. cases := unifySubsCases()
  118. for i, tc := range cases {
  119. exists := func(f string) bool {
  120. return unifyExists(f, tc)
  121. }
  122. out := unifySubs(tc.in, exists)
  123. if diff, equal := messagediff.PrettyDiff(tc.out, out); !equal {
  124. t.Errorf("Case %d failed; got %v, expected %v, diff:\n%s", i, out, tc.out, diff)
  125. }
  126. }
  127. }
  128. func BenchmarkUnifySubs(b *testing.B) {
  129. cases := unifySubsCases()
  130. b.ReportAllocs()
  131. b.ResetTimer()
  132. for i := 0; i < b.N; i++ {
  133. for _, tc := range cases {
  134. exists := func(f string) bool {
  135. return unifyExists(f, tc)
  136. }
  137. unifySubs(tc.in, exists)
  138. }
  139. }
  140. }