perkeep/pkg/blobserver/mergedenum_test.go

169 lines
3.8 KiB
Go

/*
Copyright 2014 The Perkeep Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package blobserver
import (
"context"
"fmt"
"reflect"
"sort"
"testing"
"perkeep.org/pkg/blob"
)
var mergedTests = []struct {
name string
srcs []BlobEnumerator
after string
limit int
want []string
}{
{
name: "a first",
srcs: []BlobEnumerator{
enumBlobs("foo-a", "foo-d"),
enumBlobs("foo-b", "foo-c", "foo-e"),
},
want: []string{"foo-a", "foo-b", "foo-c", "foo-d", "foo-e"},
},
{
name: "b first",
srcs: []BlobEnumerator{
enumBlobs("foo-b", "foo-c", "foo-e"),
enumBlobs("foo-a", "foo-d"),
},
want: []string{"foo-a", "foo-b", "foo-c", "foo-d", "foo-e"},
},
{
name: "after",
srcs: []BlobEnumerator{
enumBlobs("foo-b", "foo-c", "foo-e"),
enumBlobs("foo-a", "foo-d"),
},
after: "foo-a",
want: []string{"foo-b", "foo-c", "foo-d", "foo-e"},
},
{
name: "after-sha1",
srcs: []BlobEnumerator{
enumBlobs("sha1-f1d2d2f924e986ac86fdf7b36c94bcdf32beec15"),
enumBlobs("sha1-a1d2d2f924e986ac86fdf7b36c94bcdf32beec15"),
},
after: "sha1-b1d2d2f924e986ac86fdf7b36c94bcdf32beec15",
want: []string{"sha1-f1d2d2f924e986ac86fdf7b36c94bcdf32beec15"},
},
{
name: "limit",
srcs: []BlobEnumerator{
enumBlobs("foo-b", "foo-c", "foo-e"),
enumBlobs("foo-a", "foo-d"),
},
limit: 3,
want: []string{"foo-a", "foo-b", "foo-c"},
},
{
// Illustrates deadlock bugfix from
// https://camlistore-review.googlesource.com/5946
name: "limit2",
srcs: []BlobEnumerator{
enumBlobRange("foo", 0, buffered+10),
enumBlobRange("bar", 0, buffered+10),
},
limit: buffered + 10,
want: strRange("bar", 0, buffered+10),
},
{
name: "no sources",
srcs: []BlobEnumerator{},
},
{
name: "three sources",
srcs: []BlobEnumerator{
enumBlobs("foo-a", "foo-d"),
enumBlobs("foo-b", "foo-e", "foo-e1"),
enumBlobs("foo-c", "foo-e", "foo-e2"),
},
want: []string{"foo-a", "foo-b", "foo-c", "foo-d", "foo-e", "foo-e1", "foo-e2"},
},
}
func TestMergedEnumerate(t *testing.T) {
for _, tt := range mergedTests {
ctx := context.TODO()
var got []string
ch := make(chan blob.SizedRef)
errc := make(chan error)
limit := tt.limit
if limit == 0 {
limit = 1e9
}
go func() {
errc <- MergedEnumerate(ctx, ch, tt.srcs, tt.after, limit)
}()
for sb := range ch {
got = append(got, sb.Ref.String())
}
if err := <-errc; err != nil {
t.Errorf("%s. MergedEnumerate = %v", tt.name, err)
continue
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("%s. different:\n got = %v\nwant = %v", tt.name, got, tt.want)
continue
}
}
}
func enumBlobs(v ...string) BlobEnumerator {
sort.Strings(v)
return testEnum{v}
}
func enumBlobRange(base string, start, count int) BlobEnumerator {
return testEnum{strRange(base, start, count)}
}
func strRange(base string, start, count int) []string {
v := make([]string, count)
for i := 0; i < count; i++ {
v[i] = fmt.Sprintf("%s-%04d", base, start+i)
}
return v
}
type testEnum struct {
blobs []string
}
func (te testEnum) EnumerateBlobs(ctx context.Context, dest chan<- blob.SizedRef, after string, limit int) error {
defer close(dest)
done := 0
for _, bs := range te.blobs {
if bs <= after {
continue
}
br := blob.MustParse(bs)
dest <- blob.SizedRef{br, 1}
done++
if done == limit {
break
}
}
return nil
}