| package diskv |
| |
| import ( |
| "bytes" |
| "io/ioutil" |
| "sync" |
| "testing" |
| "time" |
| ) |
| |
| // ReadStream from cache shouldn't panic on a nil dereference from a nonexistent |
| // Compression :) |
| func TestIssue2A(t *testing.T) { |
| d := New(Options{ |
| BasePath: "test-issue-2a", |
| Transform: func(string) []string { return []string{} }, |
| CacheSizeMax: 1024, |
| }) |
| defer d.EraseAll() |
| |
| input := "abcdefghijklmnopqrstuvwxy" |
| key, writeBuf, sync := "a", bytes.NewBufferString(input), false |
| if err := d.WriteStream(key, writeBuf, sync); err != nil { |
| t.Fatal(err) |
| } |
| |
| for i := 0; i < 2; i++ { |
| began := time.Now() |
| rc, err := d.ReadStream(key, false) |
| if err != nil { |
| t.Fatal(err) |
| } |
| buf, err := ioutil.ReadAll(rc) |
| if err != nil { |
| t.Fatal(err) |
| } |
| if !cmpBytes(buf, []byte(input)) { |
| t.Fatalf("read #%d: '%s' != '%s'", i+1, string(buf), input) |
| } |
| rc.Close() |
| t.Logf("read #%d in %s", i+1, time.Since(began)) |
| } |
| } |
| |
| // ReadStream on a key that resolves to a directory should return an error. |
| func TestIssue2B(t *testing.T) { |
| blockTransform := func(s string) []string { |
| transformBlockSize := 3 |
| sliceSize := len(s) / transformBlockSize |
| pathSlice := make([]string, sliceSize) |
| for i := 0; i < sliceSize; i++ { |
| from, to := i*transformBlockSize, (i*transformBlockSize)+transformBlockSize |
| pathSlice[i] = s[from:to] |
| } |
| return pathSlice |
| } |
| |
| d := New(Options{ |
| BasePath: "test-issue-2b", |
| Transform: blockTransform, |
| CacheSizeMax: 0, |
| }) |
| defer d.EraseAll() |
| |
| v := []byte{'1', '2', '3'} |
| if err := d.Write("abcabc", v); err != nil { |
| t.Fatal(err) |
| } |
| |
| _, err := d.ReadStream("abc", false) |
| if err == nil { |
| t.Fatal("ReadStream('abc') should return error") |
| } |
| t.Logf("ReadStream('abc') returned error: %v", err) |
| } |
| |
| // Ensure ReadStream with direct=true isn't racy. |
| func TestIssue17(t *testing.T) { |
| var ( |
| basePath = "test-data" |
| ) |
| |
| dWrite := New(Options{ |
| BasePath: basePath, |
| CacheSizeMax: 0, |
| }) |
| defer dWrite.EraseAll() |
| |
| dRead := New(Options{ |
| BasePath: basePath, |
| CacheSizeMax: 50, |
| }) |
| |
| cases := map[string]string{ |
| "a": `1234567890`, |
| "b": `2345678901`, |
| "c": `3456789012`, |
| "d": `4567890123`, |
| "e": `5678901234`, |
| } |
| |
| for k, v := range cases { |
| if err := dWrite.Write(k, []byte(v)); err != nil { |
| t.Fatalf("during write: %s", err) |
| } |
| dRead.Read(k) // ensure it's added to cache |
| } |
| |
| var wg sync.WaitGroup |
| start := make(chan struct{}) |
| for k, v := range cases { |
| wg.Add(1) |
| go func(k, v string) { |
| <-start |
| dRead.ReadStream(k, true) |
| wg.Done() |
| }(k, v) |
| } |
| close(start) |
| wg.Wait() |
| } |