blob: 222e1c44414dafb77a94d77c8d538512a5c135b6 [file] [log] [blame]
package diskv_test
import (
"reflect"
"runtime"
"strings"
"testing"
"github.com/peterbourgon/diskv"
)
var (
keysTestData = map[string]string{
"ab01cd01": "When we started building CoreOS",
"ab01cd02": "we looked at all the various components available to us",
"ab01cd03": "re-using the best tools",
"ef01gh04": "and building the ones that did not exist",
"ef02gh05": "We believe strongly in the Unix philosophy",
"xxxxxxxx": "tools should be independently useful",
}
prefixes = []string{
"", // all
"a",
"ab",
"ab0",
"ab01",
"ab01cd0",
"ab01cd01",
"ab01cd01x", // none
"b", // none
"b0", // none
"0", // none
"01", // none
"e",
"ef",
"efx", // none
"ef01gh0",
"ef01gh04",
"ef01gh05",
"ef01gh06", // none
}
)
func TestKeysFlat(t *testing.T) {
transform := func(s string) []string {
if s == "" {
t.Fatalf(`transform should not be called with ""`)
}
return []string{}
}
d := diskv.New(diskv.Options{
BasePath: "test-data",
Transform: transform,
})
defer d.EraseAll()
for k, v := range keysTestData {
d.Write(k, []byte(v))
}
checkKeys(t, d.Keys(nil), keysTestData)
}
func TestKeysNested(t *testing.T) {
d := diskv.New(diskv.Options{
BasePath: "test-data",
Transform: blockTransform(2),
})
defer d.EraseAll()
for k, v := range keysTestData {
d.Write(k, []byte(v))
}
checkKeys(t, d.Keys(nil), keysTestData)
}
func TestKeysPrefixFlat(t *testing.T) {
d := diskv.New(diskv.Options{
BasePath: "test-data",
})
defer d.EraseAll()
for k, v := range keysTestData {
d.Write(k, []byte(v))
}
for _, prefix := range prefixes {
checkKeys(t, d.KeysPrefix(prefix, nil), filterPrefix(keysTestData, prefix))
}
}
func TestKeysPrefixNested(t *testing.T) {
d := diskv.New(diskv.Options{
BasePath: "test-data",
Transform: blockTransform(2),
})
defer d.EraseAll()
for k, v := range keysTestData {
d.Write(k, []byte(v))
}
for _, prefix := range prefixes {
checkKeys(t, d.KeysPrefix(prefix, nil), filterPrefix(keysTestData, prefix))
}
}
func TestKeysCancel(t *testing.T) {
d := diskv.New(diskv.Options{
BasePath: "test-data",
})
defer d.EraseAll()
for k, v := range keysTestData {
d.Write(k, []byte(v))
}
var (
cancel = make(chan struct{})
received = 0
cancelAfter = len(keysTestData) / 2
)
for key := range d.Keys(cancel) {
received++
if received >= cancelAfter {
close(cancel)
runtime.Gosched() // allow walker to detect cancel
}
t.Logf("received %d: %q", received, key)
}
if want, have := cancelAfter, received; want != have {
t.Errorf("want %d, have %d")
}
}
func checkKeys(t *testing.T, c <-chan string, want map[string]string) {
for k := range c {
if _, ok := want[k]; !ok {
t.Errorf("%q yielded but not expected", k)
continue
}
delete(want, k)
t.Logf("%q yielded OK", k)
}
if len(want) != 0 {
t.Errorf("%d expected key(s) not yielded: %s", len(want), strings.Join(flattenKeys(want), ", "))
}
}
func blockTransform(blockSize int) func(string) []string {
return func(s string) []string {
var (
sliceSize = len(s) / blockSize
pathSlice = make([]string, sliceSize)
)
for i := 0; i < sliceSize; i++ {
from, to := i*blockSize, (i*blockSize)+blockSize
pathSlice[i] = s[from:to]
}
return pathSlice
}
}
func filterPrefix(in map[string]string, prefix string) map[string]string {
out := map[string]string{}
for k, v := range in {
if strings.HasPrefix(k, prefix) {
out[k] = v
}
}
return out
}
func TestFilterPrefix(t *testing.T) {
input := map[string]string{
"all": "",
"and": "",
"at": "",
"available": "",
"best": "",
"building": "",
"components": "",
"coreos": "",
"did": "",
"exist": "",
"looked": "",
"not": "",
"ones": "",
"re-using": "",
"started": "",
"that": "",
"the": "",
"to": "",
"tools": "",
"us": "",
"various": "",
"we": "",
"when": "",
}
for prefix, want := range map[string]map[string]string{
"a": map[string]string{"all": "", "and": "", "at": "", "available": ""},
"al": map[string]string{"all": ""},
"all": map[string]string{"all": ""},
"alll": map[string]string{},
"c": map[string]string{"components": "", "coreos": ""},
"co": map[string]string{"components": "", "coreos": ""},
"com": map[string]string{"components": ""},
} {
have := filterPrefix(input, prefix)
if !reflect.DeepEqual(want, have) {
t.Errorf("%q: want %v, have %v", prefix, flattenKeys(want), flattenKeys(have))
}
}
}
func flattenKeys(m map[string]string) []string {
a := make([]string, 0, len(m))
for k := range m {
a = append(a, k)
}
return a
}