| // Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com> |
| // All rights reserved. |
| // |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package leveldb |
| |
| import ( |
| "bytes" |
| "testing" |
| |
| "github.com/syndtr/goleveldb/leveldb/comparer" |
| "github.com/syndtr/goleveldb/leveldb/memdb" |
| ) |
| |
| type tbRec struct { |
| kt kType |
| key, value []byte |
| } |
| |
| type testBatch struct { |
| rec []*tbRec |
| } |
| |
| func (p *testBatch) Put(key, value []byte) { |
| p.rec = append(p.rec, &tbRec{ktVal, key, value}) |
| } |
| |
| func (p *testBatch) Delete(key []byte) { |
| p.rec = append(p.rec, &tbRec{ktDel, key, nil}) |
| } |
| |
| func compareBatch(t *testing.T, b1, b2 *Batch) { |
| if b1.seq != b2.seq { |
| t.Errorf("invalid seq number want %d, got %d", b1.seq, b2.seq) |
| } |
| if b1.Len() != b2.Len() { |
| t.Fatalf("invalid record length want %d, got %d", b1.Len(), b2.Len()) |
| } |
| p1, p2 := new(testBatch), new(testBatch) |
| err := b1.Replay(p1) |
| if err != nil { |
| t.Fatal("error when replaying batch 1: ", err) |
| } |
| err = b2.Replay(p2) |
| if err != nil { |
| t.Fatal("error when replaying batch 2: ", err) |
| } |
| for i := range p1.rec { |
| r1, r2 := p1.rec[i], p2.rec[i] |
| if r1.kt != r2.kt { |
| t.Errorf("invalid type on record '%d' want %d, got %d", i, r1.kt, r2.kt) |
| } |
| if !bytes.Equal(r1.key, r2.key) { |
| t.Errorf("invalid key on record '%d' want %s, got %s", i, string(r1.key), string(r2.key)) |
| } |
| if r1.kt == ktVal { |
| if !bytes.Equal(r1.value, r2.value) { |
| t.Errorf("invalid value on record '%d' want %s, got %s", i, string(r1.value), string(r2.value)) |
| } |
| } |
| } |
| } |
| |
| func TestBatch_EncodeDecode(t *testing.T) { |
| b1 := new(Batch) |
| b1.seq = 10009 |
| b1.Put([]byte("key1"), []byte("value1")) |
| b1.Put([]byte("key2"), []byte("value2")) |
| b1.Delete([]byte("key1")) |
| b1.Put([]byte("k"), []byte("")) |
| b1.Put([]byte("zzzzzzzzzzz"), []byte("zzzzzzzzzzzzzzzzzzzzzzzz")) |
| b1.Delete([]byte("key10000")) |
| b1.Delete([]byte("k")) |
| buf := b1.encode() |
| b2 := new(Batch) |
| err := b2.decode(0, buf) |
| if err != nil { |
| t.Error("error when decoding batch: ", err) |
| } |
| compareBatch(t, b1, b2) |
| } |
| |
| func TestBatch_Append(t *testing.T) { |
| b1 := new(Batch) |
| b1.seq = 10009 |
| b1.Put([]byte("key1"), []byte("value1")) |
| b1.Put([]byte("key2"), []byte("value2")) |
| b1.Delete([]byte("key1")) |
| b1.Put([]byte("foo"), []byte("foovalue")) |
| b1.Put([]byte("bar"), []byte("barvalue")) |
| b2a := new(Batch) |
| b2a.seq = 10009 |
| b2a.Put([]byte("key1"), []byte("value1")) |
| b2a.Put([]byte("key2"), []byte("value2")) |
| b2a.Delete([]byte("key1")) |
| b2b := new(Batch) |
| b2b.Put([]byte("foo"), []byte("foovalue")) |
| b2b.Put([]byte("bar"), []byte("barvalue")) |
| b2a.append(b2b) |
| compareBatch(t, b1, b2a) |
| } |
| |
| func TestBatch_Size(t *testing.T) { |
| b := new(Batch) |
| for i := 0; i < 2; i++ { |
| b.Put([]byte("key1"), []byte("value1")) |
| b.Put([]byte("key2"), []byte("value2")) |
| b.Delete([]byte("key1")) |
| b.Put([]byte("foo"), []byte("foovalue")) |
| b.Put([]byte("bar"), []byte("barvalue")) |
| mem := memdb.New(&iComparer{comparer.DefaultComparer}, 0) |
| b.memReplay(mem) |
| if b.size() != mem.Size() { |
| t.Errorf("invalid batch size calculation, want=%d got=%d", mem.Size(), b.size()) |
| } |
| b.Reset() |
| } |
| } |