コード例 #1
0
ファイル: batch_test.go プロジェクト: nporsche/cockroach
// TestBatchScanMaxWithDeleted verifies that if a deletion
// in the updates map shadows an entry from the engine, the
// max on a scan is still reached.
func TestBatchScanMaxWithDeleted(t *testing.T) {
	defer leaktest.AfterTest(t)
	stopper := stop.NewStopper()
	defer stopper.Stop()
	e := NewInMem(roachpb.Attributes{}, 1<<20, stopper)

	b := e.NewBatch()
	defer b.Close()

	// Write two values.
	if err := e.Put(roachpb.EncodedKey("a"), []byte("value1")); err != nil {
		t.Fatal(err)
	}
	if err := e.Put(roachpb.EncodedKey("b"), []byte("value2")); err != nil {
		t.Fatal(err)
	}
	// Now, delete "a" in batch.
	if err := b.Clear(roachpb.EncodedKey("a")); err != nil {
		t.Fatal(err)
	}
	// A scan with max=1 should scan "b".
	kvs, err := Scan(b, roachpb.EncodedKey(roachpb.RKeyMin), roachpb.EncodedKey(roachpb.RKeyMax), 1)
	if err != nil {
		t.Fatal(err)
	}
	if len(kvs) != 1 || !bytes.Equal(kvs[0].Key, []byte("b")) {
		t.Errorf("expected scan of \"b\"; got %v", kvs)
	}
}
コード例 #2
0
ファイル: batch_test.go プロジェクト: nporsche/cockroach
// TestBatchConcurrency verifies operation of batch when the
// underlying engine has concurrent modifications to overlapping
// keys. This should never happen with the way Cockroach uses
// batches, but worth verifying.
func TestBatchConcurrency(t *testing.T) {
	defer leaktest.AfterTest(t)
	stopper := stop.NewStopper()
	defer stopper.Stop()
	e := NewInMem(roachpb.Attributes{}, 1<<20, stopper)

	b := e.NewBatch()
	defer b.Close()

	// Write a merge to the batch.
	if err := b.Merge(roachpb.EncodedKey("a"), appender("bar")); err != nil {
		t.Fatal(err)
	}
	val, err := b.Get(roachpb.EncodedKey("a"))
	if err != nil {
		t.Fatal(err)
	}
	if !compareMergedValues(t, val, appender("bar")) {
		t.Error("mismatch of \"a\"")
	}
	// Write an engine value.
	if err := e.Put(roachpb.EncodedKey("a"), appender("foo")); err != nil {
		t.Fatal(err)
	}
	// Now, read again and verify that the merge happens on top of the mod.
	val, err = b.Get(roachpb.EncodedKey("a"))
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(val, appender("foobar")) {
		t.Error("mismatch of \"a\"")
	}
}
コード例 #3
0
ファイル: engine_test.go プロジェクト: ruo91/cockroach
func TestEngineScan1(t *testing.T) {
	defer leaktest.AfterTest(t)
	runWithAllEngines(func(engine Engine, t *testing.T) {
		testCases := []struct {
			key, value []byte
		}{
			{[]byte("dog"), []byte("woof")},
			{[]byte("cat"), []byte("meow")},
			{[]byte("server"), []byte("42")},
			{[]byte("french"), []byte("Allô?")},
			{[]byte("german"), []byte("hallo")},
			{[]byte("chinese"), []byte("你好")},
		}
		keyMap := map[string][]byte{}
		for _, c := range testCases {
			if err := engine.Put(c.key, c.value); err != nil {
				t.Errorf("could not put key %q: %v", c.key, err)
			}
			keyMap[string(c.key)] = c.value
		}
		sortedKeys := make([]string, len(testCases))
		for i, t := range testCases {
			sortedKeys[i] = string(t.key)
		}
		sort.Strings(sortedKeys)

		keyvals, err := Scan(engine, []byte("chinese"), []byte("german"), 0)
		if err != nil {
			t.Fatalf("could not run scan: %v", err)
		}
		ensureRangeEqual(t, sortedKeys[1:4], keyMap, keyvals)

		// Check an end of range which does not equal an existing key.
		keyvals, err = Scan(engine, []byte("chinese"), []byte("german1"), 0)
		if err != nil {
			t.Fatalf("could not run scan: %v", err)
		}
		ensureRangeEqual(t, sortedKeys[1:5], keyMap, keyvals)

		keyvals, err = Scan(engine, []byte("chinese"), []byte("german"), 2)
		if err != nil {
			t.Fatalf("could not run scan: %v", err)
		}
		ensureRangeEqual(t, sortedKeys[1:3], keyMap, keyvals)

		// Should return all key/value pairs in lexicographic order.
		// Note that []byte("") is the lowest key possible and is
		// a special case in engine.scan, that's why we test it here.
		startKeys := []roachpb.EncodedKey{roachpb.EncodedKey("cat"), roachpb.EncodedKey("")}
		for _, startKey := range startKeys {
			keyvals, err = Scan(engine, startKey, roachpb.EncodedKey(roachpb.RKeyMax), 0)
			if err != nil {
				t.Fatalf("could not run scan: %v", err)
			}
			ensureRangeEqual(t, sortedKeys, keyMap, keyvals)
		}
	}, t)
}
コード例 #4
0
ファイル: batch_test.go プロジェクト: nporsche/cockroach
func TestBatchMerge(t *testing.T) {
	defer leaktest.AfterTest(t)
	stopper := stop.NewStopper()
	defer stopper.Stop()
	e := NewInMem(roachpb.Attributes{}, 1<<20, stopper)

	b := e.NewBatch()
	defer b.Close()

	// Write batch put, delete & merge.
	if err := b.Put(roachpb.EncodedKey("a"), appender("a-value")); err != nil {
		t.Fatal(err)
	}
	if err := b.Clear(roachpb.EncodedKey("b")); err != nil {
		t.Fatal(err)
	}
	if err := b.Merge(roachpb.EncodedKey("c"), appender("c-value")); err != nil {
		t.Fatal(err)
	}

	// Now, merge to all three keys.
	if err := b.Merge(roachpb.EncodedKey("a"), appender("append")); err != nil {
		t.Fatal(err)
	}
	if err := b.Merge(roachpb.EncodedKey("b"), appender("append")); err != nil {
		t.Fatal(err)
	}
	if err := b.Merge(roachpb.EncodedKey("c"), appender("append")); err != nil {
		t.Fatal(err)
	}

	// Verify values.
	val, err := b.Get(roachpb.EncodedKey("a"))
	if err != nil {
		t.Fatal(err)
	}
	if !compareMergedValues(t, val, appender("a-valueappend")) {
		t.Error("mismatch of \"a\"")
	}

	val, err = b.Get(roachpb.EncodedKey("b"))
	if err != nil {
		t.Fatal(err)
	}
	if !compareMergedValues(t, val, appender("append")) {
		t.Error("mismatch of \"b\"")
	}

	val, err = b.Get(roachpb.EncodedKey("c"))
	if err != nil {
		t.Fatal(err)
	}
	if !compareMergedValues(t, val, appender("c-valueappend")) {
		t.Error("mismatch of \"c\"")
	}
}
コード例 #5
0
ファイル: engine_test.go プロジェクト: ruo91/cockroach
func TestSnapshot(t *testing.T) {
	defer leaktest.AfterTest(t)
	runWithAllEngines(func(engine Engine, t *testing.T) {
		key := []byte("a")
		val1 := []byte("1")
		if err := engine.Put(key, val1); err != nil {
			t.Fatal(err)
		}
		val, _ := engine.Get(key)
		if !bytes.Equal(val, val1) {
			t.Fatalf("the value %s in get result does not match the value %s in request",
				val, val1)
		}

		snap := engine.NewSnapshot()
		defer snap.Close()

		val2 := []byte("2")
		if err := engine.Put(key, val2); err != nil {
			t.Fatal(err)
		}
		val, _ = engine.Get(key)
		valSnapshot, error := snap.Get(key)
		if error != nil {
			t.Fatalf("error : %s", error)
		}
		if !bytes.Equal(val, val2) {
			t.Fatalf("the value %s in get result does not match the value %s in request",
				val, val2)
		}
		if !bytes.Equal(valSnapshot, val1) {
			t.Fatalf("the value %s in get result does not match the value %s in request",
				valSnapshot, val1)
		}

		keyvals, _ := Scan(engine, key, roachpb.EncodedKey(roachpb.RKeyMax), 0)
		keyvalsSnapshot, error := Scan(snap, key, roachpb.EncodedKey(roachpb.RKeyMax), 0)
		if error != nil {
			t.Fatalf("error : %s", error)
		}
		if len(keyvals) != 1 || !bytes.Equal(keyvals[0].Value, val2) {
			t.Fatalf("the value %s in get result does not match the value %s in request",
				keyvals[0].Value, val2)
		}
		if len(keyvalsSnapshot) != 1 || !bytes.Equal(keyvalsSnapshot[0].Value, val1) {
			t.Fatalf("the value %s in get result does not match the value %s in request",
				keyvalsSnapshot[0].Value, val1)
		}
	}, t)
}
コード例 #6
0
ファイル: store_test.go プロジェクト: GokulSrinivas/cockroach
// TestBootstrapOfNonEmptyStore verifies bootstrap failure if engine
// is not empty.
func TestBootstrapOfNonEmptyStore(t *testing.T) {
	defer leaktest.AfterTest(t)
	stopper := stop.NewStopper()
	defer stopper.Stop()
	eng := engine.NewInMem(roachpb.Attributes{}, 1<<20, stopper)

	// Put some random garbage into the engine.
	if err := eng.Put(roachpb.EncodedKey("foo"), []byte("bar")); err != nil {
		t.Errorf("failure putting key foo into engine: %s", err)
	}
	ctx := TestStoreContext
	manual := hlc.NewManualClock(0)
	ctx.Clock = hlc.NewClock(manual.UnixNano)
	ctx.Transport = multiraft.NewLocalRPCTransport(stopper)
	stopper.AddCloser(ctx.Transport)
	store := NewStore(ctx, eng, &roachpb.NodeDescriptor{NodeID: 1})

	// Can't init as haven't bootstrapped.
	if err := store.Start(stopper); err == nil {
		t.Error("expected failure init'ing un-bootstrapped store")
	}

	// Bootstrap should fail on non-empty engine.
	if err := store.Bootstrap(testIdent, stopper); err == nil {
		t.Error("expected bootstrap error on non-empty store")
	}
}
コード例 #7
0
ファイル: batch_test.go プロジェクト: nporsche/cockroach
func TestBatchProto(t *testing.T) {
	defer leaktest.AfterTest(t)
	stopper := stop.NewStopper()
	defer stopper.Stop()
	e := NewInMem(roachpb.Attributes{}, 1<<20, stopper)

	b := e.NewBatch()
	defer b.Close()

	kv := &roachpb.RawKeyValue{Key: roachpb.EncodedKey("a"), Value: []byte("value")}
	if _, _, err := PutProto(b, roachpb.EncodedKey("proto"), kv); err != nil {
		t.Fatal(err)
	}
	getKV := &roachpb.RawKeyValue{}
	ok, keySize, valSize, err := b.GetProto(roachpb.EncodedKey("proto"), getKV)
	if !ok || err != nil {
		t.Fatalf("expected GetProto to success ok=%t: %s", ok, err)
	}
	if keySize != 5 {
		t.Errorf("expected key size 5; got %d", keySize)
	}
	var data []byte
	if data, err = proto.Marshal(kv); err != nil {
		t.Fatal(err)
	}
	if valSize != int64(len(data)) {
		t.Errorf("expected value size %d; got %d", len(data), valSize)
	}
	if !reflect.DeepEqual(getKV, kv) {
		t.Errorf("expected %v; got %v", kv, getKV)
	}
	// Before commit, proto will not be available via engine.
	if ok, _, _, err = e.GetProto(roachpb.EncodedKey("proto"), getKV); ok || err != nil {
		t.Fatalf("expected GetProto to fail ok=%t: %s", ok, err)
	}
	// Commit and verify the proto can be read directly from the engine.
	if err := b.Commit(); err != nil {
		t.Fatal(err)
	}
	if ok, _, _, err = e.GetProto(roachpb.EncodedKey("proto"), getKV); !ok || err != nil {
		t.Fatalf("expected GetProto to success ok=%t: %s", ok, err)
	}
	if !reflect.DeepEqual(getKV, kv) {
		t.Errorf("expected %v; got %v", kv, getKV)
	}
}
コード例 #8
0
ファイル: engine_test.go プロジェクト: ruo91/cockroach
// TestEngineBatchCommit writes a batch containing 10K rows (all the
// same key) and concurrently attempts to read the value in a tight
// loop. The test verifies that either there is no value for the key
// or it contains the final value, but never a value in between.
func TestEngineBatchCommit(t *testing.T) {
	defer leaktest.AfterTest(t)
	numWrites := 10000
	key := roachpb.EncodedKey("a")
	finalVal := []byte(strconv.Itoa(numWrites - 1))

	runWithAllEngines(func(e Engine, t *testing.T) {
		// Start a concurrent read operation in a busy loop.
		readsBegun := make(chan struct{})
		readsDone := make(chan struct{})
		writesDone := make(chan struct{})
		go func() {
			for i := 0; ; i++ {
				select {
				case <-writesDone:
					close(readsDone)
					return
				default:
					val, err := e.Get(key)
					if err != nil {
						t.Fatal(err)
					}
					if val != nil && bytes.Compare(val, finalVal) != 0 {
						close(readsDone)
						t.Fatalf("key value should be empty or %q; got %q", string(finalVal), string(val))
					}
					if i == 0 {
						close(readsBegun)
					}
				}
			}
		}()
		// Wait until we've succeeded with first read.
		<-readsBegun

		// Create key/values and put them in a batch to engine.
		batch := e.NewBatch()
		defer batch.Close()
		for i := 0; i < numWrites; i++ {
			if err := batch.Put(key, []byte(strconv.Itoa(i))); err != nil {
				t.Fatal(err)
			}
		}
		if err := batch.Commit(); err != nil {
			t.Fatal(err)
		}
		close(writesDone)
		<-readsDone
	}, t)
}
コード例 #9
0
ファイル: batch_test.go プロジェクト: nporsche/cockroach
// TestBatchScanWithDelete verifies that a scan containing
// a single deleted value returns nothing.
func TestBatchScanWithDelete(t *testing.T) {
	defer leaktest.AfterTest(t)
	stopper := stop.NewStopper()
	defer stopper.Stop()
	e := NewInMem(roachpb.Attributes{}, 1<<20, stopper)

	b := e.NewBatch()
	defer b.Close()

	// Write initial value, then delete via batch.
	if err := e.Put(roachpb.EncodedKey("a"), []byte("value")); err != nil {
		t.Fatal(err)
	}
	if err := b.Clear(roachpb.EncodedKey("a")); err != nil {
		t.Fatal(err)
	}
	kvs, err := Scan(b, roachpb.EncodedKey(roachpb.RKeyMin), roachpb.EncodedKey(roachpb.RKeyMax), 0)
	if err != nil {
		t.Fatal(err)
	}
	if len(kvs) != 0 {
		t.Errorf("expected empty scan with batch-deleted value; got %v", kvs)
	}
}
コード例 #10
0
ファイル: batch_test.go プロジェクト: nporsche/cockroach
func TestBatchGet(t *testing.T) {
	defer leaktest.AfterTest(t)
	stopper := stop.NewStopper()
	defer stopper.Stop()
	e := NewInMem(roachpb.Attributes{}, 1<<20, stopper)

	b := e.NewBatch()
	defer b.Close()

	// Write initial values, then write to batch.
	if err := e.Put(roachpb.EncodedKey("b"), []byte("value")); err != nil {
		t.Fatal(err)
	}
	if err := e.Put(roachpb.EncodedKey("c"), appender("foo")); err != nil {
		t.Fatal(err)
	}
	// Write batch values.
	if err := b.Put(roachpb.EncodedKey("a"), []byte("value")); err != nil {
		t.Fatal(err)
	}
	if err := b.Clear(roachpb.EncodedKey("b")); err != nil {
		t.Fatal(err)
	}
	if err := b.Merge(roachpb.EncodedKey("c"), appender("bar")); err != nil {
		t.Fatal(err)
	}

	expValues := []roachpb.RawKeyValue{
		{Key: roachpb.EncodedKey("a"), Value: []byte("value")},
		{Key: roachpb.EncodedKey("b"), Value: nil},
		{Key: roachpb.EncodedKey("c"), Value: appender("foobar")},
	}
	for i, expKV := range expValues {
		kv, err := b.Get(expKV.Key)
		if err != nil {
			t.Fatal(err)
		}
		if !bytes.Equal(kv, expKV.Value) {
			t.Errorf("%d: expected \"value\", got %q", i, kv)
		}
	}
}
コード例 #11
0
ファイル: engine_test.go プロジェクト: ruo91/cockroach
// TestSnapshotMethods verifies that snapshots allow only read-only
// engine operations.
func TestSnapshotMethods(t *testing.T) {
	defer leaktest.AfterTest(t)
	runWithAllEngines(func(engine Engine, t *testing.T) {
		keys := [][]byte{[]byte("a"), []byte("b")}
		vals := [][]byte{[]byte("1"), []byte("2")}
		for i := range keys {
			if err := engine.Put(keys[i], vals[i]); err != nil {
				t.Fatal(err)
			}
		}
		snap := engine.NewSnapshot()
		defer snap.Close()

		// Verify Attrs.
		var attrs roachpb.Attributes
		switch engine.(type) {
		case InMem:
			attrs = inMemAttrs
		}
		if !reflect.DeepEqual(engine.Attrs(), attrs) {
			t.Errorf("attrs mismatch; expected %+v, got %+v", attrs, engine.Attrs())
		}

		// Verify Put is error.
		if err := snap.Put([]byte("c"), []byte("3")); err == nil {
			t.Error("expected error on Put to snapshot")
		}

		// Verify Get.
		valSnapshot, err := snap.Get(keys[0])
		if err != nil {
			t.Fatal(err)
		}
		if !bytes.Equal(vals[0], valSnapshot) {
			t.Fatalf("the value %s in get result does not match the value %s in snapshot",
				vals[0], valSnapshot)
		}

		// Verify Scan.
		keyvals, _ := Scan(engine, roachpb.EncodedKey(roachpb.RKeyMin), roachpb.EncodedKey(roachpb.RKeyMax), 0)
		keyvalsSnapshot, err := Scan(snap, roachpb.EncodedKey(roachpb.RKeyMin), roachpb.EncodedKey(roachpb.RKeyMax), 0)
		if err != nil {
			t.Fatal(err)
		}
		if !reflect.DeepEqual(keyvals, keyvalsSnapshot) {
			t.Fatalf("the key/values %v in scan result does not match the value %s in snapshot",
				keyvals, keyvalsSnapshot)
		}

		// Verify Iterate.
		index := 0
		if err := snap.Iterate(roachpb.EncodedKey(roachpb.RKeyMin), roachpb.EncodedKey(roachpb.RKeyMax), func(kv roachpb.RawKeyValue) (bool, error) {
			if !bytes.Equal(kv.Key, keys[index]) || !bytes.Equal(kv.Value, vals[index]) {
				t.Errorf("%d: key/value not equal between expected and snapshot: %s/%s, %s/%s",
					index, keys[index], vals[index], kv.Key, kv.Value)
			}
			index++
			return false, nil
		}); err != nil {
			t.Fatal(err)
		}

		// Verify Clear is error.
		if err := snap.Clear(keys[0]); err == nil {
			t.Error("expected error on Clear to snapshot")
		}

		// Verify Merge is error.
		if err := snap.Merge([]byte("merge-key"), appender("x")); err == nil {
			t.Error("expected error on Merge to snapshot")
		}

		// Verify Capacity.
		capacity, err := engine.Capacity()
		if err != nil {
			t.Fatal(err)
		}
		capacitySnapshot, err := snap.Capacity()
		if err != nil {
			t.Fatal(err)
		}
		// The Available fields of capacity may differ due to processes beyond our control.
		if capacity.Capacity != capacitySnapshot.Capacity {
			t.Errorf("expected capacities to be equal: %v != %v",
				capacity.Capacity, capacitySnapshot.Capacity)
		}

		// Verify ApproximateSize.
		approx, err := engine.ApproximateSize(roachpb.EncodedKey(roachpb.RKeyMin), roachpb.EncodedKey(roachpb.RKeyMax))
		if err != nil {
			t.Fatal(err)
		}
		approxSnapshot, err := snap.ApproximateSize(roachpb.EncodedKey(roachpb.RKeyMin), roachpb.EncodedKey(roachpb.RKeyMax))
		if err != nil {
			t.Fatal(err)
		}
		if approx != approxSnapshot {
			t.Errorf("expected approx sizes to be equal: %d != %d", approx, approxSnapshot)
		}

		// Write a new key to engine.
		newKey := []byte("c")
		newVal := []byte("3")
		if err := engine.Put(newKey, newVal); err != nil {
			t.Fatal(err)
		}

		// Verify NewIterator still iterates over original snapshot.
		iter := snap.NewIterator()
		iter.Seek(newKey)
		if iter.Valid() {
			t.Error("expected invalid iterator when seeking to element which shouldn't be visible to snapshot")
		}
		iter.Close()

		// Verify Commit is error.
		if err := snap.Commit(); err == nil {
			t.Error("expected error on Commit to snapshot")
		}
	}, t)
}
コード例 #12
0
ファイル: engine_test.go プロジェクト: ruo91/cockroach
func TestEngineDeleteRange(t *testing.T) {
	defer leaktest.AfterTest(t)
	runWithAllEngines(func(engine Engine, t *testing.T) {
		keys := []roachpb.EncodedKey{
			roachpb.EncodedKey("a"),
			roachpb.EncodedKey("aa"),
			roachpb.EncodedKey("aaa"),
			roachpb.EncodedKey("ab"),
			roachpb.EncodedKey("abc"),
			roachpb.EncodedKey(roachpb.RKeyMax),
		}

		insertKeys(keys, engine, t)

		// Scan all keys (non-inclusive of final key).
		verifyScan(roachpb.EncodedKey(roachpb.RKeyMin), roachpb.EncodedKey(roachpb.RKeyMax), 10, keys[0:5], engine, t)

		// Delete a range of keys
		numDeleted, err := ClearRange(engine, roachpb.EncodedKey("aa"), roachpb.EncodedKey("abc"))
		// Verify what was deleted
		if err != nil {
			t.Error("Not expecting an error")
		}
		if numDeleted != 3 {
			t.Errorf("Expected to delete 3 entries; was %v", numDeleted)
		}
		// Verify what's left
		verifyScan(roachpb.EncodedKey(roachpb.RKeyMin), roachpb.EncodedKey(roachpb.RKeyMax), 10,
			[]roachpb.EncodedKey{roachpb.EncodedKey("a"), roachpb.EncodedKey("abc")}, engine, t)
	}, t)
}
コード例 #13
0
ファイル: engine_test.go プロジェクト: ruo91/cockroach
func TestEngineScan2(t *testing.T) {
	defer leaktest.AfterTest(t)
	// TODO(Tobias): Merge this with TestEngineScan1 and remove
	// either verifyScan or the other helper function.
	runWithAllEngines(func(engine Engine, t *testing.T) {
		keys := []roachpb.EncodedKey{
			roachpb.EncodedKey("a"),
			roachpb.EncodedKey("aa"),
			roachpb.EncodedKey("aaa"),
			roachpb.EncodedKey("ab"),
			roachpb.EncodedKey("abc"),
			roachpb.EncodedKey(roachpb.RKeyMax),
		}

		insertKeys(keys, engine, t)

		// Scan all keys (non-inclusive of final key).
		verifyScan(roachpb.EncodedKey(roachpb.RKeyMin), roachpb.EncodedKey(roachpb.RKeyMax), 10, keys[0:5], engine, t)
		verifyScan(roachpb.EncodedKey("a"), roachpb.EncodedKey(roachpb.RKeyMax), 10, keys[0:5], engine, t)

		// Scan sub range.
		verifyScan(roachpb.EncodedKey("aab"), roachpb.EncodedKey("abcc"), 10, keys[3:5], engine, t)
		verifyScan(roachpb.EncodedKey("aa0"), roachpb.EncodedKey("abcc"), 10, keys[2:5], engine, t)

		// Scan with max values.
		verifyScan(roachpb.EncodedKey(roachpb.RKeyMin), roachpb.EncodedKey(roachpb.RKeyMax), 3, keys[0:3], engine, t)
		verifyScan(roachpb.EncodedKey("a0"), roachpb.EncodedKey(roachpb.RKeyMax), 3, keys[1:4], engine, t)

		// Scan with max value 0 gets all values.
		verifyScan(roachpb.EncodedKey(roachpb.RKeyMin), roachpb.EncodedKey(roachpb.RKeyMax), 0, keys[0:5], engine, t)
	}, t)
}
コード例 #14
0
ファイル: batch_test.go プロジェクト: nporsche/cockroach
func TestBatchScan(t *testing.T) {
	defer leaktest.AfterTest(t)
	stopper := stop.NewStopper()
	defer stopper.Stop()
	e := NewInMem(roachpb.Attributes{}, 1<<20, stopper)

	b := e.NewBatch()
	defer b.Close()

	existingVals := []roachpb.RawKeyValue{
		{Key: roachpb.EncodedKey("a"), Value: []byte("1")},
		{Key: roachpb.EncodedKey("b"), Value: []byte("2")},
		{Key: roachpb.EncodedKey("c"), Value: []byte("3")},
		{Key: roachpb.EncodedKey("d"), Value: []byte("4")},
		{Key: roachpb.EncodedKey("e"), Value: []byte("5")},
		{Key: roachpb.EncodedKey("f"), Value: []byte("6")},
		{Key: roachpb.EncodedKey("g"), Value: []byte("7")},
		{Key: roachpb.EncodedKey("h"), Value: []byte("8")},
		{Key: roachpb.EncodedKey("i"), Value: []byte("9")},
		{Key: roachpb.EncodedKey("j"), Value: []byte("10")},
		{Key: roachpb.EncodedKey("k"), Value: []byte("11")},
		{Key: roachpb.EncodedKey("l"), Value: []byte("12")},
		{Key: roachpb.EncodedKey("m"), Value: []byte("13")},
	}
	for _, kv := range existingVals {
		if err := e.Put(kv.Key, kv.Value); err != nil {
			t.Fatal(err)
		}
	}

	batchVals := []roachpb.RawKeyValue{
		{Key: roachpb.EncodedKey("a"), Value: []byte("b1")},
		{Key: roachpb.EncodedKey("bb"), Value: []byte("b2")},
		{Key: roachpb.EncodedKey("c"), Value: []byte("b3")},
		{Key: roachpb.EncodedKey("dd"), Value: []byte("b4")},
		{Key: roachpb.EncodedKey("e"), Value: []byte("b5")},
		{Key: roachpb.EncodedKey("ff"), Value: []byte("b6")},
		{Key: roachpb.EncodedKey("g"), Value: []byte("b7")},
		{Key: roachpb.EncodedKey("hh"), Value: []byte("b8")},
		{Key: roachpb.EncodedKey("i"), Value: []byte("b9")},
		{Key: roachpb.EncodedKey("jj"), Value: []byte("b10")},
	}
	for _, kv := range batchVals {
		if err := b.Put(kv.Key, kv.Value); err != nil {
			t.Fatal(err)
		}
	}

	scans := []struct {
		start, end roachpb.EncodedKey
		max        int64
	}{
		// Full monty.
		{start: roachpb.EncodedKey("a"), end: roachpb.EncodedKey("z"), max: 0},
		// Select ~half.
		{start: roachpb.EncodedKey("a"), end: roachpb.EncodedKey("z"), max: 9},
		// Select one.
		{start: roachpb.EncodedKey("a"), end: roachpb.EncodedKey("z"), max: 1},
		// Select half by end key.
		{start: roachpb.EncodedKey("a"), end: roachpb.EncodedKey("f0"), max: 0},
		// Start at half and select rest.
		{start: roachpb.EncodedKey("f"), end: roachpb.EncodedKey("z"), max: 0},
		// Start at last and select max=10.
		{start: roachpb.EncodedKey("m"), end: roachpb.EncodedKey("z"), max: 10},
	}

	// Scan each case using the batch and store the results.
	results := map[int][]roachpb.RawKeyValue{}
	for i, scan := range scans {
		kvs, err := Scan(b, scan.start, scan.end, scan.max)
		if err != nil {
			t.Fatal(err)
		}
		results[i] = kvs
	}

	// Now, commit batch and re-scan using engine direct to compare results.
	if err := b.Commit(); err != nil {
		t.Fatal(err)
	}
	for i, scan := range scans {
		kvs, err := Scan(e, scan.start, scan.end, scan.max)
		if err != nil {
			t.Fatal(err)
		}
		if !reflect.DeepEqual(kvs, results[i]) {
			t.Errorf("%d: expected %v; got %v", i, results[i], kvs)
		}
	}
}
コード例 #15
0
ファイル: engine_test.go プロジェクト: ruo91/cockroach
// TestEngineMerge tests that the passing through of engine merge operations
// to the goMerge function works as expected. The semantics are tested more
// exhaustively in the merge tests themselves.
func TestEngineMerge(t *testing.T) {
	defer leaktest.AfterTest(t)
	runWithAllEngines(func(engine Engine, t *testing.T) {
		testcases := []struct {
			testKey  roachpb.EncodedKey
			merges   [][]byte
			expected []byte
		}{
			{
				roachpb.EncodedKey("haste not in life"),
				[][]byte{
					appender("x"),
					appender("y"),
					appender("z"),
				},
				appender("xyz"),
			},
			{
				roachpb.EncodedKey("timeseriesmerged"),
				[][]byte{
					timeSeries(testtime, 1000, []tsSample{
						{1, 1, 5, 5, 5},
					}...),
					timeSeries(testtime, 1000, []tsSample{
						{2, 1, 5, 5, 5},
						{1, 2, 10, 7, 3},
					}...),
					timeSeries(testtime, 1000, []tsSample{
						{10, 1, 5, 5, 5},
					}...),
					timeSeries(testtime, 1000, []tsSample{
						{5, 1, 5, 5, 5},
						{3, 1, 5, 5, 5},
					}...),
				},
				timeSeries(testtime, 1000, []tsSample{
					{1, 3, 15, 7, 3},
					{2, 1, 5, 5, 5},
					{3, 1, 5, 5, 5},
					{5, 1, 5, 5, 5},
					{10, 1, 5, 5, 5},
				}...),
			},
		}
		for _, tc := range testcases {
			for i, update := range tc.merges {
				if err := engine.Merge(tc.testKey, update); err != nil {
					t.Fatalf("%d: %v", i, err)
				}
			}
			result, _ := engine.Get(tc.testKey)
			var resultV, expectedV MVCCMetadata
			if err := proto.Unmarshal(result, &resultV); err != nil {
				t.Fatal(err)
			}
			if err := proto.Unmarshal(tc.expected, &expectedV); err != nil {
				t.Fatal(err)
			}
			if !reflect.DeepEqual(resultV, expectedV) {
				t.Errorf("unexpected append-merge result: %v != %v", resultV, expectedV)
			}
		}
	}, t)
}
コード例 #16
0
ファイル: engine_test.go プロジェクト: ruo91/cockroach
func TestEngineBatch(t *testing.T) {
	defer leaktest.AfterTest(t)
	runWithAllEngines(func(engine Engine, t *testing.T) {
		numShuffles := 100
		key := roachpb.EncodedKey("a")
		// Those are randomized below.
		type data struct {
			key   roachpb.EncodedKey
			value []byte
			merge bool
		}
		batch := []data{
			{key, appender("~ockroachDB"), false},
			{key, appender("C~ckroachDB"), false},
			{key, appender("Co~kroachDB"), false},
			{key, appender("Coc~roachDB"), false},
			{key, appender("C**k~oachDB"), false},
			{key, appender("Cockr~achDB"), false},
			{key, appender("Cockro~chDB"), false},
			{key, appender("Cockroa~hDB"), false},
			{key, appender("Cockroac~DB"), false},
			{key, appender("Cockroach~B"), false},
			{key, appender("CockroachD~"), false},
			{key, nil, false},
			{key, appender("C"), true},
			{key, appender(" o"), true},
			{key, appender("  c"), true},
			{key, appender(" k"), true},
			{key, appender("r"), true},
			{key, appender(" o"), true},
			{key, appender("  a"), true},
			{key, appender(" c"), true},
			{key, appender("h"), true},
			{key, appender(" D"), true},
			{key, appender("  B"), true},
		}

		apply := func(eng Engine, d data) error {
			if d.value == nil {
				return eng.Clear(d.key)
			} else if d.merge {
				return eng.Merge(d.key, d.value)
			}
			return eng.Put(d.key, d.value)
		}

		get := func(eng Engine, key roachpb.EncodedKey) []byte {
			b, err := eng.Get(key)
			if err != nil {
				t.Fatal(err)
			}
			m := &MVCCMetadata{}
			if err := proto.Unmarshal(b, m); err != nil {
				t.Fatal(err)
			}
			if m.Value == nil {
				return nil
			}
			return m.Value.Bytes
		}

		for i := 0; i < numShuffles; i++ {
			// In each run, create an array of shuffled operations.
			shuffledIndices := rand.Perm(len(batch))
			currentBatch := make([]data, len(batch))
			for k := range currentBatch {
				currentBatch[k] = batch[shuffledIndices[k]]
			}
			// Reset the key
			if err := engine.Clear(key); err != nil {
				t.Fatal(err)
			}
			// Run it once with individual operations and remember the result.
			for i, op := range currentBatch {
				if err := apply(engine, op); err != nil {
					t.Errorf("%d: op %v: %v", i, op, err)
					continue
				}
			}
			expectedValue := get(engine, key)
			// Run the whole thing as a batch and compare.
			b := engine.NewBatch()
			if err := b.Clear(key); err != nil {
				t.Fatal(err)
			}
			for _, op := range currentBatch {
				if err := apply(b, op); err != nil {
					t.Fatal(err)
				}
			}
			// Try getting the value from the batch.
			actualValue := get(b, key)
			if !bytes.Equal(actualValue, expectedValue) {
				t.Errorf("%d: expected %s, but got %s", i, expectedValue, actualValue)
			}
			// Try using an iterator to get the value from the batch.
			iter := b.NewIterator()
			iter.Seek(key)
			if !iter.Valid() {
				if currentBatch[len(currentBatch)-1].value != nil {
					t.Errorf("%d: batch seek invalid", i)
				}
			} else if !bytes.Equal(iter.Key(), key) {
				t.Errorf("%d: batch seek expected key %s, but got %s", i, key, iter.Key())
			} else {
				m := &MVCCMetadata{}
				if err := iter.ValueProto(m); err != nil {
					t.Fatal(err)
				}
				if !bytes.Equal(m.Value.Bytes, expectedValue) {
					t.Errorf("%d: expected %s, but got %s", i, expectedValue, m.Value.Bytes)
				}
			}
			iter.Close()
			// Commit the batch and try getting the value from the engine.
			if err := b.Commit(); err != nil {
				t.Errorf("%d: %v", i, err)
				continue
			}
			actualValue = get(engine, key)
			if !bytes.Equal(actualValue, expectedValue) {
				t.Errorf("%d: expected %s, but got %s", i, expectedValue, actualValue)
			}
		}
	}, t)
}
コード例 #17
0
ファイル: batch_test.go プロジェクト: nporsche/cockroach
// TestBatchBasics verifies that all commands work in a batch, aren't
// visible until commit, and then are all visible after commit.
func TestBatchBasics(t *testing.T) {
	defer leaktest.AfterTest(t)
	stopper := stop.NewStopper()
	defer stopper.Stop()
	e := NewInMem(roachpb.Attributes{}, 1<<20, stopper)

	b := e.NewBatch()
	defer b.Close()

	if err := b.Put(roachpb.EncodedKey("a"), []byte("value")); err != nil {
		t.Fatal(err)
	}
	// Write an engine value to be deleted.
	if err := e.Put(roachpb.EncodedKey("b"), []byte("value")); err != nil {
		t.Fatal(err)
	}
	if err := b.Clear(roachpb.EncodedKey("b")); err != nil {
		t.Fatal(err)
	}
	// Write an engine value to be merged.
	if err := e.Put(roachpb.EncodedKey("c"), appender("foo")); err != nil {
		t.Fatal(err)
	}
	if err := b.Merge(roachpb.EncodedKey("c"), appender("bar")); err != nil {
		t.Fatal(err)
	}

	// Check all keys are in initial state (nothing from batch has gone
	// through to engine until commit).
	expValues := []roachpb.RawKeyValue{
		{Key: roachpb.EncodedKey("b"), Value: []byte("value")},
		{Key: roachpb.EncodedKey("c"), Value: appender("foo")},
	}
	kvs, err := Scan(e, roachpb.EncodedKey(roachpb.RKeyMin), roachpb.EncodedKey(roachpb.RKeyMax), 0)
	if err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(expValues, kvs) {
		t.Errorf("%v != %v", kvs, expValues)
	}

	// Now, merged values should be:
	expValues = []roachpb.RawKeyValue{
		{Key: roachpb.EncodedKey("a"), Value: []byte("value")},
		{Key: roachpb.EncodedKey("c"), Value: appender("foobar")},
	}
	// Scan values from batch directly.
	kvs, err = Scan(b, roachpb.EncodedKey(roachpb.RKeyMin), roachpb.EncodedKey(roachpb.RKeyMax), 0)
	if err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(expValues, kvs) {
		t.Errorf("%v != %v", kvs, expValues)
	}

	// Commit batch and verify direct engine scan yields correct values.
	if err := b.Commit(); err != nil {
		t.Fatal(err)
	}
	kvs, err = Scan(e, roachpb.EncodedKey(roachpb.RKeyMin), roachpb.EncodedKey(roachpb.RKeyMax), 0)
	if err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(expValues, kvs) {
		t.Errorf("%v != %v", kvs, expValues)
	}
}