|
|
@ -9,10 +9,10 @@ import ( |
|
|
|
|
|
|
|
func TestCompactFileChunks(t *testing.T) { |
|
|
|
chunks := []*filer_pb.FileChunk{ |
|
|
|
{Offset:10, Size:100, FileId:"abc", Mtime:50}, |
|
|
|
{Offset:100, Size:100, FileId:"def", Mtime:100}, |
|
|
|
{Offset:200, Size:100, FileId:"ghi", Mtime:200}, |
|
|
|
{Offset:110, Size:200, FileId:"jkl", Mtime:300}, |
|
|
|
{Offset: 10, Size: 100, FileId: "abc", Mtime: 50}, |
|
|
|
{Offset: 100, Size: 100, FileId: "def", Mtime: 100}, |
|
|
|
{Offset: 200, Size: 100, FileId: "ghi", Mtime: 200}, |
|
|
|
{Offset: 110, Size: 200, FileId: "jkl", Mtime: 300}, |
|
|
|
} |
|
|
|
|
|
|
|
compacted, garbarge := CompactFileChunks(chunks) |
|
|
@ -144,3 +144,135 @@ func TestIntervalMerging(t *testing.T) { |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
func TestChunksReading(t *testing.T) { |
|
|
|
|
|
|
|
testcases := []struct { |
|
|
|
Chunks []*filer_pb.FileChunk |
|
|
|
Offset int64 |
|
|
|
Size int |
|
|
|
Expected []*filer_pb.FileChunk |
|
|
|
}{ |
|
|
|
// case 0: normal
|
|
|
|
{ |
|
|
|
Chunks: []*filer_pb.FileChunk{ |
|
|
|
{Offset: 0, Size: 100, FileId: "abc", Mtime: 123}, |
|
|
|
{Offset: 100, Size: 100, FileId: "asdf", Mtime: 134}, |
|
|
|
{Offset: 200, Size: 100, FileId: "fsad", Mtime: 353}, |
|
|
|
}, |
|
|
|
Offset: 0, |
|
|
|
Size: 250, |
|
|
|
Expected: []*filer_pb.FileChunk{ |
|
|
|
{Offset: 0, Size: 100, FileId: "abc"}, |
|
|
|
{Offset: 0, Size: 100, FileId: "asdf"}, |
|
|
|
{Offset: 0, Size: 50, FileId: "fsad"}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
// case 1: updates overwrite full chunks
|
|
|
|
{ |
|
|
|
Chunks: []*filer_pb.FileChunk{ |
|
|
|
{Offset: 0, Size: 100, FileId: "abc", Mtime: 123}, |
|
|
|
{Offset: 0, Size: 200, FileId: "asdf", Mtime: 134}, |
|
|
|
}, |
|
|
|
Offset: 50, |
|
|
|
Size: 100, |
|
|
|
Expected: []*filer_pb.FileChunk{ |
|
|
|
{Offset: 50, Size: 100, FileId: "asdf"}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
// case 2: updates overwrite part of previous chunks
|
|
|
|
{ |
|
|
|
Chunks: []*filer_pb.FileChunk{ |
|
|
|
{Offset: 0, Size: 100, FileId: "abc", Mtime: 123}, |
|
|
|
{Offset: 0, Size: 50, FileId: "asdf", Mtime: 134}, |
|
|
|
}, |
|
|
|
Offset: 25, |
|
|
|
Size: 50, |
|
|
|
Expected: []*filer_pb.FileChunk{ |
|
|
|
{Offset: 25, Size: 25, FileId: "asdf"}, |
|
|
|
{Offset: 0, Size: 25, FileId: "abc"}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
// case 3: updates overwrite full chunks
|
|
|
|
{ |
|
|
|
Chunks: []*filer_pb.FileChunk{ |
|
|
|
{Offset: 0, Size: 100, FileId: "abc", Mtime: 123}, |
|
|
|
{Offset: 0, Size: 200, FileId: "asdf", Mtime: 134}, |
|
|
|
{Offset: 50, Size: 250, FileId: "xxxx", Mtime: 154}, |
|
|
|
}, |
|
|
|
Offset: 0, |
|
|
|
Size: 200, |
|
|
|
Expected: []*filer_pb.FileChunk{ |
|
|
|
{Offset: 0, Size: 50, FileId: "asdf"}, |
|
|
|
{Offset: 0, Size: 150, FileId: "xxxx"}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
// case 4: updates far away from prev chunks
|
|
|
|
{ |
|
|
|
Chunks: []*filer_pb.FileChunk{ |
|
|
|
{Offset: 0, Size: 100, FileId: "abc", Mtime: 123}, |
|
|
|
{Offset: 0, Size: 200, FileId: "asdf", Mtime: 134}, |
|
|
|
{Offset: 250, Size: 250, FileId: "xxxx", Mtime: 154}, |
|
|
|
}, |
|
|
|
Offset: 0, |
|
|
|
Size: 400, |
|
|
|
Expected: []*filer_pb.FileChunk{ |
|
|
|
{Offset: 0, Size: 200, FileId: "asdf"}, |
|
|
|
// {Offset: 0, Size: 150, FileId: "xxxx"}, // missing intervals should not happen
|
|
|
|
}, |
|
|
|
}, |
|
|
|
// case 5: updates overwrite full chunks
|
|
|
|
{ |
|
|
|
Chunks: []*filer_pb.FileChunk{ |
|
|
|
{Offset: 0, Size: 100, FileId: "abc", Mtime: 123}, |
|
|
|
{Offset: 0, Size: 200, FileId: "asdf", Mtime: 184}, |
|
|
|
{Offset: 70, Size: 150, FileId: "abc", Mtime: 143}, |
|
|
|
{Offset: 80, Size: 100, FileId: "xxxx", Mtime: 134}, |
|
|
|
}, |
|
|
|
Offset: 0, |
|
|
|
Size: 220, |
|
|
|
Expected: []*filer_pb.FileChunk{ |
|
|
|
{Offset: 0, Size: 200, FileId: "asdf"}, |
|
|
|
{Offset: 0, Size: 20, FileId: "abc"}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
// case 6: same updates
|
|
|
|
{ |
|
|
|
Chunks: []*filer_pb.FileChunk{ |
|
|
|
{Offset: 0, Size: 100, FileId: "abc", Mtime: 123}, |
|
|
|
{Offset: 0, Size: 100, FileId: "abc", Mtime: 123}, |
|
|
|
{Offset: 0, Size: 100, FileId: "abc", Mtime: 123}, |
|
|
|
}, |
|
|
|
Offset: 0, |
|
|
|
Size: 100, |
|
|
|
Expected: []*filer_pb.FileChunk{ |
|
|
|
{Offset: 0, Size: 100, FileId: "abc"}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
for i, testcase := range testcases { |
|
|
|
log.Printf("++++++++++ read test case %d ++++++++++++++++++++", i) |
|
|
|
chunks := ReadFromChunks(testcase.Chunks, testcase.Offset, testcase.Size) |
|
|
|
for x, chunk := range chunks { |
|
|
|
log.Printf("read case %d, chunk %d, offset=%d, size=%d, fileId=%s", |
|
|
|
i, x, chunk.Offset, chunk.Size, chunk.FileId) |
|
|
|
if chunk.Offset != testcase.Expected[x].Offset { |
|
|
|
t.Fatalf("failed on read case %d, chunk %d, Offset %d, expect %d", |
|
|
|
i, x, chunk.Offset, testcase.Expected[x].Offset) |
|
|
|
} |
|
|
|
if chunk.Size != testcase.Expected[x].Size { |
|
|
|
t.Fatalf("failed on read case %d, chunk %d, Size %d, expect %d", |
|
|
|
i, x, chunk.Size, testcase.Expected[x].Size) |
|
|
|
} |
|
|
|
if chunk.FileId != testcase.Expected[x].FileId { |
|
|
|
t.Fatalf("failed on read case %d, chunk %d, FileId %s, expect %s", |
|
|
|
i, x, chunk.FileId, testcase.Expected[x].FileId) |
|
|
|
} |
|
|
|
} |
|
|
|
if len(chunks) != len(testcase.Expected) { |
|
|
|
t.Fatalf("failed to read test case %d, len %d expected %d", i, len(chunks), len(testcase.Expected)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |