keys_test.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. package diskv_test
  2. import (
  3. "reflect"
  4. "runtime"
  5. "strings"
  6. "testing"
  7. "github.com/peterbourgon/diskv"
  8. )
  9. var (
  10. keysTestData = map[string]string{
  11. "ab01cd01": "When we started building CoreOS",
  12. "ab01cd02": "we looked at all the various components available to us",
  13. "ab01cd03": "re-using the best tools",
  14. "ef01gh04": "and building the ones that did not exist",
  15. "ef02gh05": "We believe strongly in the Unix philosophy",
  16. "xxxxxxxx": "tools should be independently useful",
  17. }
  18. prefixes = []string{
  19. "", // all
  20. "a",
  21. "ab",
  22. "ab0",
  23. "ab01",
  24. "ab01cd0",
  25. "ab01cd01",
  26. "ab01cd01x", // none
  27. "b", // none
  28. "b0", // none
  29. "0", // none
  30. "01", // none
  31. "e",
  32. "ef",
  33. "efx", // none
  34. "ef01gh0",
  35. "ef01gh04",
  36. "ef01gh05",
  37. "ef01gh06", // none
  38. }
  39. )
  40. func TestKeysFlat(t *testing.T) {
  41. transform := func(s string) []string {
  42. if s == "" {
  43. t.Fatalf(`transform should not be called with ""`)
  44. }
  45. return []string{}
  46. }
  47. d := diskv.New(diskv.Options{
  48. BasePath: "test-data",
  49. Transform: transform,
  50. })
  51. defer d.EraseAll()
  52. for k, v := range keysTestData {
  53. d.Write(k, []byte(v))
  54. }
  55. checkKeys(t, d.Keys(nil), keysTestData)
  56. }
  57. func TestKeysNested(t *testing.T) {
  58. d := diskv.New(diskv.Options{
  59. BasePath: "test-data",
  60. Transform: blockTransform(2),
  61. })
  62. defer d.EraseAll()
  63. for k, v := range keysTestData {
  64. d.Write(k, []byte(v))
  65. }
  66. checkKeys(t, d.Keys(nil), keysTestData)
  67. }
  68. func TestKeysPrefixFlat(t *testing.T) {
  69. d := diskv.New(diskv.Options{
  70. BasePath: "test-data",
  71. })
  72. defer d.EraseAll()
  73. for k, v := range keysTestData {
  74. d.Write(k, []byte(v))
  75. }
  76. for _, prefix := range prefixes {
  77. checkKeys(t, d.KeysPrefix(prefix, nil), filterPrefix(keysTestData, prefix))
  78. }
  79. }
  80. func TestKeysPrefixNested(t *testing.T) {
  81. d := diskv.New(diskv.Options{
  82. BasePath: "test-data",
  83. Transform: blockTransform(2),
  84. })
  85. defer d.EraseAll()
  86. for k, v := range keysTestData {
  87. d.Write(k, []byte(v))
  88. }
  89. for _, prefix := range prefixes {
  90. checkKeys(t, d.KeysPrefix(prefix, nil), filterPrefix(keysTestData, prefix))
  91. }
  92. }
  93. func TestKeysCancel(t *testing.T) {
  94. d := diskv.New(diskv.Options{
  95. BasePath: "test-data",
  96. })
  97. defer d.EraseAll()
  98. for k, v := range keysTestData {
  99. d.Write(k, []byte(v))
  100. }
  101. var (
  102. cancel = make(chan struct{})
  103. received = 0
  104. cancelAfter = len(keysTestData) / 2
  105. )
  106. for key := range d.Keys(cancel) {
  107. received++
  108. if received >= cancelAfter {
  109. close(cancel)
  110. runtime.Gosched() // allow walker to detect cancel
  111. }
  112. t.Logf("received %d: %q", received, key)
  113. }
  114. if want, have := cancelAfter, received; want != have {
  115. t.Errorf("want %d, have %d")
  116. }
  117. }
  118. func checkKeys(t *testing.T, c <-chan string, want map[string]string) {
  119. for k := range c {
  120. if _, ok := want[k]; !ok {
  121. t.Errorf("%q yielded but not expected", k)
  122. continue
  123. }
  124. delete(want, k)
  125. t.Logf("%q yielded OK", k)
  126. }
  127. if len(want) != 0 {
  128. t.Errorf("%d expected key(s) not yielded: %s", len(want), strings.Join(flattenKeys(want), ", "))
  129. }
  130. }
  131. func blockTransform(blockSize int) func(string) []string {
  132. return func(s string) []string {
  133. var (
  134. sliceSize = len(s) / blockSize
  135. pathSlice = make([]string, sliceSize)
  136. )
  137. for i := 0; i < sliceSize; i++ {
  138. from, to := i*blockSize, (i*blockSize)+blockSize
  139. pathSlice[i] = s[from:to]
  140. }
  141. return pathSlice
  142. }
  143. }
  144. func filterPrefix(in map[string]string, prefix string) map[string]string {
  145. out := map[string]string{}
  146. for k, v := range in {
  147. if strings.HasPrefix(k, prefix) {
  148. out[k] = v
  149. }
  150. }
  151. return out
  152. }
  153. func TestFilterPrefix(t *testing.T) {
  154. input := map[string]string{
  155. "all": "",
  156. "and": "",
  157. "at": "",
  158. "available": "",
  159. "best": "",
  160. "building": "",
  161. "components": "",
  162. "coreos": "",
  163. "did": "",
  164. "exist": "",
  165. "looked": "",
  166. "not": "",
  167. "ones": "",
  168. "re-using": "",
  169. "started": "",
  170. "that": "",
  171. "the": "",
  172. "to": "",
  173. "tools": "",
  174. "us": "",
  175. "various": "",
  176. "we": "",
  177. "when": "",
  178. }
  179. for prefix, want := range map[string]map[string]string{
  180. "a": map[string]string{"all": "", "and": "", "at": "", "available": ""},
  181. "al": map[string]string{"all": ""},
  182. "all": map[string]string{"all": ""},
  183. "alll": map[string]string{},
  184. "c": map[string]string{"components": "", "coreos": ""},
  185. "co": map[string]string{"components": "", "coreos": ""},
  186. "com": map[string]string{"components": ""},
  187. } {
  188. have := filterPrefix(input, prefix)
  189. if !reflect.DeepEqual(want, have) {
  190. t.Errorf("%q: want %v, have %v", prefix, flattenKeys(want), flattenKeys(have))
  191. }
  192. }
  193. }
  194. func flattenKeys(m map[string]string) []string {
  195. a := make([]string, 0, len(m))
  196. for k := range m {
  197. a = append(a, k)
  198. }
  199. return a
  200. }