func TestPseudoRand(t *testing.T) { numbers := make(map[int]bool) // Make two random number generators and pull two numbers from each. rand1, _ := randutil.NewPseudoRand() rand2, _ := randutil.NewPseudoRand() numbers[rand1.Int()] = true numbers[rand1.Int()] = true numbers[rand2.Int()] = true numbers[rand2.Int()] = true // All four numbers should be distinct; no seed state is shared. if len(numbers) != 4 { t.Errorf("expected 4 unique numbers; got %d", len(numbers)) } }
func TestNonsortingEncodeDecimalRand(t *testing.T) { rng, _ := randutil.NewPseudoRand() const randomTrials = 200000 for i := 0; i < randomTrials; i++ { var tmp, appendTo []byte // Test with and without appending. if rng.Intn(2) == 1 { appendTo = randBuf(rng, 30) appendTo = appendTo[:rng.Intn(len(appendTo)+1)] } // Test with and without tmp buffer. if rng.Intn(2) == 1 { tmp = randBuf(rng, 100) } cur := randDecimal(rng, -20, 20) enc := EncodeNonsortingDecimal(appendTo, cur) enc = enc[len(appendTo):] res, err := DecodeNonsortingDecimal(enc, tmp) if err != nil { t.Fatal(err) } // Make sure we decode the same value we encoded. if cur.Cmp(res) != 0 { t.Fatalf("unexpected mismatch for %v, got %v", cur, res) } // Make sure we would have overestimated the value. if est := UpperBoundNonsortingDecimalSize(cur); est < len(enc) { t.Fatalf("expected estimate of %d for %v to be greater than or equal to the encoded length, found [% x]", est, cur, enc) } } }
func TestEncodeDecimalRand(t *testing.T) { rng, _ := randutil.NewPseudoRand() // Test both directions. for _, dir := range []Direction{Ascending, Descending} { var prev *inf.Dec var prevEnc []byte const randomTrials = 100000 for i := 0; i < randomTrials; i++ { cur := randDecimal(rng, -20, 20) var tmp, appendTo []byte // Test with and without appending. if rng.Intn(2) == 1 { appendTo = randBuf(rng, 30) appendTo = appendTo[:rng.Intn(len(appendTo)+1)] } // Test with and without tmp buffer. if rng.Intn(2) == 1 { tmp = randBuf(rng, 100) } var enc []byte var res *inf.Dec var err error if dir == Ascending { enc = EncodeDecimalAscending(appendTo, cur) enc = enc[len(appendTo):] _, res, err = DecodeDecimalAscending(enc, tmp) } else { enc = EncodeDecimalDescending(appendTo, cur) enc = enc[len(appendTo):] _, res, err = DecodeDecimalDescending(enc, tmp) } if err != nil { t.Fatal(err) } testPeekLength(t, enc) // Make sure we decode the same value we encoded. if cur.Cmp(res) != 0 { t.Fatalf("unexpected mismatch for %v, got %v", cur, res) } // Make sure lexicographical sorting is consistent. if prev != nil { bytesCmp := bytes.Compare(prevEnc, enc) cmpType := "same" if dir == Descending { bytesCmp *= -1 cmpType = "inverse" } if decCmp := prev.Cmp(cur); decCmp != bytesCmp { t.Fatalf("expected [% x] to compare to [% x] the %s way that %v compares to %v", prevEnc, enc, cmpType, prev, cur) } } prev = cur prevEnc = enc } } }
// TestTransactionObservedTimestamp verifies that txn.{Get,Update}ObservedTimestamp work as // advertised. func TestTransactionObservedTimestamp(t *testing.T) { var txn Transaction rng, seed := randutil.NewPseudoRand() t.Logf("running with seed %d", seed) ids := append([]int{109, 104, 102, 108, 1000}, rand.Perm(100)...) timestamps := make(map[NodeID]hlc.Timestamp, len(ids)) for i := 0; i < len(ids); i++ { timestamps[NodeID(i)] = hlc.ZeroTimestamp.Add(rng.Int63(), 0) } for i, n := range ids { nodeID := NodeID(n) if ts, ok := txn.GetObservedTimestamp(nodeID); ok { t.Fatalf("%d: false positive hit %s in %v", nodeID, ts, ids[:i+1]) } txn.UpdateObservedTimestamp(nodeID, timestamps[nodeID]) txn.UpdateObservedTimestamp(nodeID, hlc.MaxTimestamp) // should be noop if exp, act := i+1, len(txn.ObservedTimestamps); act != exp { t.Fatalf("%d: expected %d entries, got %d: %v", nodeID, exp, act, txn.ObservedTimestamps) } } for _, m := range ids { checkID := NodeID(m) exp := timestamps[checkID] if act, _ := txn.GetObservedTimestamp(checkID); !act.Equal(exp) { t.Fatalf("%d: expected %s, got %s", checkID, exp, act) } } var emptyTxn Transaction ts := hlc.ZeroTimestamp.Add(1, 2) emptyTxn.UpdateObservedTimestamp(NodeID(1), ts) if actTS, _ := emptyTxn.GetObservedTimestamp(NodeID(1)); !actTS.Equal(ts) { t.Fatalf("unexpected: %s (wanted %s)", actTS, ts) } }
func TestEncDatumNull(t *testing.T) { defer leaktest.AfterTest(t)() // Verify DNull is null. n := DatumToEncDatum(ColumnType{Kind: ColumnType_INT}, parser.DNull) if !n.IsNull() { t.Error("DNull not null") } var alloc DatumAlloc rng, _ := randutil.NewPseudoRand() // Generate random EncDatums (some of which are null), and verify that a datum // created from its encoding has the same IsNull() value. for cases := 0; cases < 100; cases++ { a := RandEncDatum(rng) for enc := range DatumEncoding_name { encoded, err := a.Encode(&alloc, DatumEncoding(enc), nil) if err != nil { t.Fatal(err) } b := EncDatumFromEncoded(ColumnType{Kind: ColumnType_INT}, DatumEncoding(enc), encoded) if a.IsNull() != b.IsNull() { t.Errorf("before: %s (null=%t) after: %s (null=%t)", a.String(), a.IsNull(), b.String(), b.IsNull()) } } } }
// TestStreamEncodeDecode generates random streams of EncDatums and passes them // through a StreamEncoder and a StreamDecoder func TestStreamEncodeDecode(t *testing.T) { defer leaktest.AfterTest(t)() rng, _ := randutil.NewPseudoRand() for test := 0; test < 100; test++ { rowLen := 1 + rng.Intn(20) info := make([]DatumInfo, rowLen) for i := range info { info[i].Type = sqlbase.RandColumnType(rng) info[i].Encoding = sqlbase.RandDatumEncoding(rng) } numRows := rng.Intn(100) rows := make(sqlbase.EncDatumRows, numRows) for i := range rows { rows[i] = make(sqlbase.EncDatumRow, rowLen) for j := range rows[i] { rows[i][j] = sqlbase.DatumToEncDatum(info[j].Type, sqlbase.RandDatum(rng, info[j].Type, true)) } } var trailerErr error if rng.Intn(10) == 0 { trailerErr = fmt.Errorf("test error %d", rng.Intn(100)) } testRowStream(t, rng, rows, trailerErr) } }
func runMVCCConditionalPut(emk engineMaker, valueSize int, createFirst bool, b *testing.B) { rng, _ := randutil.NewPseudoRand() value := roachpb.MakeValueFromBytes(randutil.RandBytes(rng, valueSize)) keyBuf := append(make([]byte, 0, 64), []byte("key-")...) eng := emk(b, fmt.Sprintf("cput_%d", valueSize)) defer eng.Close() b.SetBytes(int64(valueSize)) var expected *roachpb.Value if createFirst { for i := 0; i < b.N; i++ { key := roachpb.Key(encoding.EncodeUvarintAscending(keyBuf[:4], uint64(i))) ts := makeTS(timeutil.Now().UnixNano(), 0) if err := MVCCPut(context.Background(), eng, nil, key, ts, value, nil); err != nil { b.Fatalf("failed put: %s", err) } } expected = &value } b.ResetTimer() for i := 0; i < b.N; i++ { key := roachpb.Key(encoding.EncodeUvarintAscending(keyBuf[:4], uint64(i))) ts := makeTS(timeutil.Now().UnixNano(), 0) if err := MVCCConditionalPut(context.Background(), eng, nil, key, ts, value, expected, nil); err != nil { b.Fatalf("failed put: %s", err) } } b.StopTimer() }
func makeEncodedVals(minExp, maxExp int) [][]byte { rng, _ := randutil.NewPseudoRand() vals := make([][]byte, 10000) for i := range vals { vals[i] = EncodeDecimalAscending(nil, randDecimal(rng, minExp, maxExp)) } return vals }
// makeDecimalVals creates decimal values with exponents in // the range [minExp, maxExp]. func makeDecimalVals(minExp, maxExp int) []*inf.Dec { rng, _ := randutil.NewPseudoRand() vals := make([]*inf.Dec, 10000) for i := range vals { vals[i] = randDecimal(rng, minExp, maxExp) } return vals }
func makeIntTestDatum(count int) []Datum { rng, _ := randutil.NewPseudoRand() vals := make([]Datum, count) for i := range vals { vals[i] = NewDInt(DInt(rng.Int63())) } return vals }
func makeFloatTestDatum(count int) []Datum { rng, _ := randutil.NewPseudoRand() vals := make([]Datum, count) for i := range vals { vals[i] = NewDFloat(DFloat(rng.Float64())) } return vals }
func TestRandBytes(t *testing.T) { rand, _ := randutil.NewPseudoRand() for i := 0; i < 100; i++ { x := randutil.RandBytes(rand, i) if len(x) != i { t.Errorf("got array with unexpected length: %d (expected %d)", len(x), i) } } }
func makeBoolTestDatum(count int) []Datum { rng, _ := randutil.NewPseudoRand() vals := make([]Datum, count) for i := range vals { vals[i] = MakeDBool(DBool(rng.Int31n(2) == 0)) } return vals }
func TestRandIntInRange(t *testing.T) { rand, _ := randutil.NewPseudoRand() for i := 0; i < 100; i++ { x := randutil.RandIntInRange(rand, 20, 40) if x < 20 || x >= 40 { t.Errorf("got result out of range: %d", x) } } }
func init() { r, _ := randutil.NewPseudoRand() // 127.255.255.255 is special (broadcast), so choose values less // than 255. a := r.Intn(255) b := r.Intn(255) c := r.Intn(255) IsolatedTestAddr = NewUnresolvedAddr("tcp", fmt.Sprintf("127.%d.%d.%d:0", a, b, c)) }
func makeDecimalTestDatum(count int) []Datum { rng, _ := randutil.NewPseudoRand() vals := make([]Datum, count) for i := range vals { dd := &DDecimal{} decimal.SetFromFloat(&dd.Dec, rng.Float64()) vals[i] = dd } return vals }
func TestEncDatumCompare(t *testing.T) { defer leaktest.AfterTest(t)() a := &DatumAlloc{} rng, _ := randutil.NewPseudoRand() for kind := range ColumnType_Kind_name { kind := ColumnType_Kind(kind) // TODO(cuongdo,eisen): we don't support persistence for arrays or collated // strings yet if kind == ColumnType_COLLATEDSTRING || kind == ColumnType_INT_ARRAY { continue } typ := ColumnType{Kind: kind} // Generate two datums d1 < d2 var d1, d2 parser.Datum for { d1 = RandDatum(rng, typ, false) d2 = RandDatum(rng, typ, false) if cmp := d1.Compare(d2); cmp < 0 { break } } v1 := DatumToEncDatum(typ, d1) v2 := DatumToEncDatum(typ, d2) if val, err := v1.Compare(a, &v2); err != nil { t.Fatal(err) } else if val != -1 { t.Errorf("compare(1, 2) = %d", val) } asc := DatumEncoding_ASCENDING_KEY desc := DatumEncoding_DESCENDING_KEY noncmp := DatumEncoding_VALUE checkEncDatumCmp(t, a, &v1, &v2, asc, asc, -1, false) checkEncDatumCmp(t, a, &v2, &v1, asc, asc, +1, false) checkEncDatumCmp(t, a, &v1, &v1, asc, asc, 0, false) checkEncDatumCmp(t, a, &v2, &v2, asc, asc, 0, false) checkEncDatumCmp(t, a, &v1, &v2, desc, desc, -1, false) checkEncDatumCmp(t, a, &v2, &v1, desc, desc, +1, false) checkEncDatumCmp(t, a, &v1, &v1, desc, desc, 0, false) checkEncDatumCmp(t, a, &v2, &v2, desc, desc, 0, false) checkEncDatumCmp(t, a, &v1, &v2, noncmp, noncmp, -1, true) checkEncDatumCmp(t, a, &v2, &v1, desc, noncmp, +1, true) checkEncDatumCmp(t, a, &v1, &v1, asc, desc, 0, true) checkEncDatumCmp(t, a, &v2, &v2, desc, asc, 0, true) } }
func makeIntervalTestDatum(count int) []Datum { rng, _ := randutil.NewPseudoRand() vals := make([]Datum, count) for i := range vals { vals[i] = &DInterval{Duration: duration.Duration{Months: rng.Int63n(1000), Days: rng.Int63n(1000), Nanos: rng.Int63n(1000000), }} } return vals }
func testPutInner(ctx context.Context, t *testing.T, c cluster.Cluster, cfg cluster.TestConfig) { db, err := c.NewClient(ctx, 0) if err != nil { t.Fatal(err) } errs := make(chan error, c.NumNodes()) start := timeutil.Now() deadline := start.Add(cfg.Duration) var count int64 for i := 0; i < c.NumNodes(); i++ { go func() { r, _ := randutil.NewPseudoRand() value := randutil.RandBytes(r, 8192) for timeutil.Now().Before(deadline) { k := atomic.AddInt64(&count, 1) v := value[:r.Intn(len(value))] if err := db.Put(ctx, fmt.Sprintf("%08d", k), v); err != nil { errs <- err return } } errs <- nil }() } for i := 0; i < c.NumNodes(); { baseCount := atomic.LoadInt64(&count) select { case <-stopper.ShouldStop(): t.Fatalf("interrupted") case err := <-errs: if err != nil { t.Fatal(err) } i++ case <-time.After(1 * time.Second): // Periodically print out progress so that we know the test is still // running. loadedCount := atomic.LoadInt64(&count) log.Infof(ctx, "%d (%d/s)", loadedCount, loadedCount-baseCount) c.Assert(ctx, t) if err := cluster.Consistent(ctx, c, 0); err != nil { t.Fatal(err) } } } elapsed := timeutil.Since(start) log.Infof(ctx, "%d %.1f/sec", count, float64(count)/elapsed.Seconds()) }
// makeSmallIntTestDatum creates integers that are sufficiently // smaller than 2^64-1 that they can be added to each other for a // significant part of the test without overflow. This is meant to // test the implementation of aggregates that can use an int64 to // optimize computations small decimal values. func makeSmallIntTestDatum(count int) []Datum { rng, _ := randutil.NewPseudoRand() vals := make([]Datum, count) for i := range vals { sign := int32(1) if 0 == rng.Int31()&1 { sign = -1 } vals[i] = NewDInt(DInt(rng.Int31() * sign)) } return vals }
func BenchmarkDecodeFloat(b *testing.B) { rng, _ := randutil.NewPseudoRand() vals := make([][]byte, 10000) for i := range vals { vals[i] = EncodeFloatAscending(nil, rng.Float64()) } b.ResetTimer() for i := 0; i < b.N; i++ { _, _, _ = DecodeFloatAscending(vals[i%len(vals)]) } }
func TestEncDatumCompare(t *testing.T) { a := &DatumAlloc{} rng, _ := randutil.NewPseudoRand() for typ := range ColumnType_Kind_name { typ := ColumnType_Kind(typ) // TODO(cuongdo): we don't support persistence for arrays yet if typ == ColumnType_INT_ARRAY { continue } // Generate two datums d1 < d2 var d1, d2 parser.Datum for { d1 = RandDatum(rng, typ, false) d2 = RandDatum(rng, typ, false) if cmp := d1.Compare(d2); cmp < 0 { break } } v1 := &EncDatum{} v1.SetDatum(typ, d1) v2 := &EncDatum{} v2.SetDatum(typ, d2) if val, err := v1.Compare(a, v2); err != nil { t.Fatal(err) } else if val != -1 { t.Errorf("compare(1, 2) = %d", val) } asc := DatumEncoding_ASCENDING_KEY desc := DatumEncoding_DESCENDING_KEY noncmp := DatumEncoding_VALUE checkEncDatumCmp(t, a, v1, v2, asc, asc, -1, false) checkEncDatumCmp(t, a, v2, v1, asc, asc, +1, false) checkEncDatumCmp(t, a, v1, v1, asc, asc, 0, false) checkEncDatumCmp(t, a, v2, v2, asc, asc, 0, false) checkEncDatumCmp(t, a, v1, v2, desc, desc, -1, false) checkEncDatumCmp(t, a, v2, v1, desc, desc, +1, false) checkEncDatumCmp(t, a, v1, v1, desc, desc, 0, false) checkEncDatumCmp(t, a, v2, v2, desc, desc, 0, false) checkEncDatumCmp(t, a, v1, v2, noncmp, noncmp, -1, true) checkEncDatumCmp(t, a, v2, v1, desc, noncmp, +1, true) checkEncDatumCmp(t, a, v1, v1, asc, desc, 0, true) checkEncDatumCmp(t, a, v2, v2, desc, asc, 0, true) } }
func BenchmarkDecimalLog(b *testing.B) { rng, _ := randutil.NewPseudoRand() vals := make([]*inf.Dec, 10000) for i := range vals { vals[i] = NewDecFromFloat(math.Abs(rng.Float64())) } z := new(inf.Dec) b.ResetTimer() for i := 0; i < b.N; i++ { Log(z, vals[i%len(vals)], 16) } }
func testClusterRecoveryInner( ctx context.Context, t *testing.T, c cluster.Cluster, cfg cluster.TestConfig, ) { num := c.NumNodes() // One client for each node. initBank(t, c.PGUrl(ctx, 0)) start := timeutil.Now() state := testState{ t: t, errChan: make(chan error, num), teardown: make(chan struct{}), deadline: start.Add(cfg.Duration), clients: make([]testClient, num), } for i := 0; i < num; i++ { state.clients[i].Lock() state.initClient(ctx, t, c, i) state.clients[i].Unlock() go transferMoneyLoop(ctx, i, &state, *numAccounts, *maxTransfer) } defer func() { <-state.teardown }() // Chaos monkey. rnd, seed := randutil.NewPseudoRand() log.Warningf(ctx, "monkey starts (seed %d)", seed) pickNodes := func() []int { return rnd.Perm(num)[:rnd.Intn(num)+1] } go chaosMonkey(ctx, &state, c, true, pickNodes, 0) waitClientsStop(ctx, num, &state, stall) // Verify accounts. verifyAccounts(t, &state.clients[0]) elapsed := timeutil.Since(start) var count uint64 counts := state.counts() for _, c := range counts { count += c } log.Infof(ctx, "%d %.1f/sec", count, float64(count)/elapsed.Seconds()) }
func BenchmarkEncodeFloat(b *testing.B) { rng, _ := randutil.NewPseudoRand() vals := make([]float64, 10000) for i := range vals { vals[i] = rng.Float64() } buf := make([]byte, 0, 100) b.ResetTimer() for i := 0; i < b.N; i++ { _ = EncodeFloatAscending(buf, vals[i%len(vals)]) } }
func BenchmarkDecimalExp(b *testing.B) { rng, _ := randutil.NewPseudoRand() vals := make([]*inf.Dec, 100) for i := range vals { vals[i] = NewDecFromFloat(math.Abs(rng.Float64())) vals[i].Add(vals[i], inf.NewDec(int64(randutil.RandIntInRange(rng, 0, 100)), 0)) } z := new(inf.Dec) b.ResetTimer() for i := 0; i < b.N; i++ { Exp(z, vals[i%len(vals)], 16) } }
func testNodeRestartInner( ctx context.Context, t *testing.T, c cluster.Cluster, cfg cluster.TestConfig, ) { num := c.NumNodes() if minNum := 3; num < minNum { t.Skipf("need at least %d nodes, got %d", minNum, num) } // One client for each node. initBank(t, c.PGUrl(ctx, 0)) start := timeutil.Now() state := testState{ t: t, errChan: make(chan error, 1), teardown: make(chan struct{}), deadline: start.Add(cfg.Duration), clients: make([]testClient, 1), } clientIdx := num - 1 client := &state.clients[0] client.Lock() client.db = makePGClient(t, c.PGUrl(ctx, clientIdx)) client.Unlock() go transferMoneyLoop(ctx, 0, &state, *numAccounts, *maxTransfer) defer func() { <-state.teardown }() // Chaos monkey. rnd, seed := randutil.NewPseudoRand() log.Warningf(ctx, "monkey starts (seed %d)", seed) pickNodes := func() []int { return []int{rnd.Intn(clientIdx)} } go chaosMonkey(ctx, &state, c, false, pickNodes, clientIdx) waitClientsStop(ctx, 1, &state, stall) // Verify accounts. verifyAccounts(t, client) elapsed := timeutil.Since(start) count := atomic.LoadUint64(&client.count) log.Infof(ctx, "%d %.1f/sec", count, float64(count)/elapsed.Seconds()) }
func BenchmarkNonsortingDecodeDecimal(b *testing.B) { rng, _ := randutil.NewPseudoRand() vals := make([][]byte, 10000) for i := range vals { d := randDecimal(rng, -20, 20) vals[i] = EncodeNonsortingDecimal(nil, d) } buf := make([]byte, 0, 100) b.ResetTimer() for i := 0; i < b.N; i++ { _, _ = DecodeNonsortingDecimal(vals[i%len(vals)], buf) } }
func TestEncDatumFromBuffer(t *testing.T) { defer leaktest.AfterTest(t)() var alloc DatumAlloc rng, _ := randutil.NewPseudoRand() for test := 0; test < 20; test++ { var err error // Generate a set of random datums. ed := make([]EncDatum, 1+rng.Intn(10)) for i := range ed { ed[i] = RandEncDatum(rng) } // Encode them in a single buffer. var buf []byte enc := make([]DatumEncoding, len(ed)) for i := range ed { enc[i] = RandDatumEncoding(rng) buf, err = ed[i].Encode(&alloc, enc[i], buf) if err != nil { t.Fatal(err) } } // Decode the buffer. b := buf for i := range ed { if len(b) == 0 { t.Fatal("buffer ended early") } var decoded EncDatum decoded, b, err = EncDatumFromBuffer(ed[i].Type, enc[i], b) if err != nil { t.Fatal(err) } err = decoded.EnsureDecoded(&alloc) if err != nil { t.Fatal(err) } if decoded.Datum.Compare(ed[i].Datum) != 0 { t.Errorf("decoded datum %s doesn't equal original %s", decoded.Datum, ed[i].Datum) } } if len(b) != 0 { t.Errorf("%d leftover bytes", len(b)) } } }
func TestEncDatumCompare(t *testing.T) { a := &DatumAlloc{} rng, _ := randutil.NewPseudoRand() for typ := ColumnType_Kind(0); int(typ) < len(ColumnType_Kind_value); typ++ { // Generate two datums d1 < d2 var d1, d2 parser.Datum for { d1 = RandDatum(rng, typ, false) d2 = RandDatum(rng, typ, false) if cmp := d1.Compare(d2); cmp < 0 { break } } v1 := &EncDatum{} v1.SetDatum(typ, d1) v2 := &EncDatum{} v2.SetDatum(typ, d2) if val, err := v1.Compare(a, v2); err != nil { t.Fatal(err) } else if val != -1 { t.Errorf("compare(1, 2) = %d", val) } asc := DatumEncoding_ASCENDING_KEY desc := DatumEncoding_DESCENDING_KEY noncmp := DatumEncoding_VALUE checkEncDatumCmp(t, a, v1, v2, asc, asc, -1, false) checkEncDatumCmp(t, a, v2, v1, asc, asc, +1, false) checkEncDatumCmp(t, a, v1, v1, asc, asc, 0, false) checkEncDatumCmp(t, a, v2, v2, asc, asc, 0, false) checkEncDatumCmp(t, a, v1, v2, desc, desc, -1, false) checkEncDatumCmp(t, a, v2, v1, desc, desc, +1, false) checkEncDatumCmp(t, a, v1, v1, desc, desc, 0, false) checkEncDatumCmp(t, a, v2, v2, desc, desc, 0, false) checkEncDatumCmp(t, a, v1, v2, noncmp, noncmp, -1, true) checkEncDatumCmp(t, a, v2, v1, desc, noncmp, +1, true) checkEncDatumCmp(t, a, v1, v1, asc, desc, 0, true) checkEncDatumCmp(t, a, v2, v2, desc, asc, 0, true) } }