func TestBadRequest(t *testing.T) {
	defer leaktest.AfterTest(t)
	s := server.StartTestServer(t)
	db := createTestClient(t, s.Stopper(), s.ServingAddr())
	defer s.Stop()

	// Write key "a".
	if err := db.Put("a", "value"); err != nil {
		t.Fatal(err)
	}

	if _, err := db.Scan("a", "a", 0); !testutils.IsError(err, "truncation resulted in empty batch") {
		t.Fatalf("unexpected error on scan with startkey == endkey: %v", err)
	}

	if _, err := db.ReverseScan("a", "a", 0); !testutils.IsError(err, "truncation resulted in empty batch") {
		t.Fatalf("unexpected error on reverse scan with startkey == endkey: %v", err)
	}

	if err := db.DelRange("x", "a"); !testutils.IsError(err, "truncation resulted in empty batch") {
		t.Fatalf("unexpected error on deletion on [x, a): %v", err)
	}

	if err := db.DelRange("", "z"); !testutils.IsError(err, "must be greater than LocalMax") {
		t.Fatalf("unexpected error on deletion on [KeyMin, z): %v", err)
	}

}
예제 #2
0
// TestRollbackToSavepointStatement tests that issuing a RESTART outside of a
// txn produces the proper error.
func TestRollbackToSavepointStatement(t *testing.T) {
	defer leaktest.AfterTest(t)()

	params, _ := createTestServerParams()
	s, sqlDB, _ := serverutils.StartServer(t, params)
	defer s.Stopper().Stop()

	// ROLLBACK TO SAVEPOINT without a transaction
	_, err := sqlDB.Exec("ROLLBACK TO SAVEPOINT cockroach_restart")
	if !testutils.IsError(err, "the transaction is not in a retriable state") {
		t.Fatalf("expected to fail here. err: %v", err)
	}
	// ROLLBACK TO SAVEPOINT with a wrong name
	_, err = sqlDB.Exec("ROLLBACK TO SAVEPOINT foo")
	if !testutils.IsError(err, "SAVEPOINT not supported except for COCKROACH_RESTART") {
		t.Fatalf("expected to fail here. err: %v", err)
	}

	// ROLLBACK TO SAVEPOINT in a non-retriable transaction
	tx, err := sqlDB.Begin()
	if err != nil {
		t.Fatal(err)
	}
	if _, err := tx.Exec("SAVEPOINT cockroach_restart"); err != nil {
		t.Fatal(err)
	}
	if _, err = tx.Exec("BOGUS SQL STATEMENT"); err == nil {
		t.Fatalf("expected to fail here. err: %v", err)
	}
	_, err = tx.Exec("ROLLBACK TO SAVEPOINT cockroach_restart")
	if !testutils.IsError(err,
		"SAVEPOINT COCKROACH_RESTART has not been used or a non-retriable error was encountered") {
		t.Fatalf("expected to fail here. err: %v", err)
	}
}
예제 #3
0
// Test that rando commands while in COMMIT_WAIT return a particular error.
func TestCommitWaitState(t *testing.T) {
	defer leaktest.AfterTest(t)()

	params, _ := createTestServerParams()
	s, sqlDB, _ := serverutils.StartServer(t, params)
	defer s.Stopper().Stop()
	if _, err := sqlDB.Exec(`
CREATE DATABASE t; CREATE TABLE t.test (k INT PRIMARY KEY, v TEXT);
`); err != nil {
		t.Fatal(err)
	}

	tx, err := sqlDB.Begin()
	if err != nil {
		t.Fatal(err)
	}
	if _, err := tx.Exec(
		"SAVEPOINT cockroach_restart; RELEASE cockroach_restart;"); err != nil {
		t.Fatal(err)
	}
	_, err = tx.Exec("INSERT INTO t.test (k, v) VALUES (0, 'sentinel');")
	if !testutils.IsError(err, "current transaction is committed") {
		t.Fatal(err)
	}
	// Rollback should respond with a COMMIT command tag.
	err = tx.Rollback()
	if !testutils.IsError(err, "unexpected command tag COMMIT") {
		t.Fatal(err)
	}
}
예제 #4
0
// TestRestartStatement tests that issuing a RESTART outside of a txn produces
// the proper error.
func TestRestartStatement(t *testing.T) {
	defer leaktest.AfterTest(t)()

	server, sqlDB, _ := setup(t)
	defer cleanup(server, sqlDB)

	// RESTART without a transaction
	_, err := sqlDB.Exec("RESTART TRANSACTION")
	if !testutils.IsError(err, "the transaction is not in a retriable state") {
		t.Fatal("expected to fail here. err: ", err)
	}

	// RESTART in a non-retriable transaction
	tx, err := sqlDB.Begin()
	if err != nil {
		t.Fatal(err)
	}
	if _, err := tx.Exec("RETRY INTENT"); err != nil {
		t.Fatal(err)
	}
	if _, err = tx.Exec("BOGUS SQL STATEMENT"); err == nil {
		t.Fatalf("expected to fail here. err: %s", err)
	}
	_, err = tx.Exec("RESTART TRANSACTION")
	if !testutils.IsError(err,
		"RETRY INTENT has not been used or a non-retriable error was encountered") {
		t.Fatal("expected to fail here. err: ", err)
	}
}
예제 #5
0
// Test that rando commands while in COMMIT_WAIT return a particular error.
func TestCommitWaitState(t *testing.T) {
	defer leaktest.AfterTest(t)()

	server, sqlDB, _ := setup(t)
	defer cleanup(server, sqlDB)
	if _, err := sqlDB.Exec(`
CREATE DATABASE t; CREATE TABLE t.test (k INT PRIMARY KEY, v TEXT);
`); err != nil {
		t.Fatal(err)
	}

	tx, err := sqlDB.Begin()
	if err != nil {
		t.Fatal(err)
	}
	if _, err := tx.Exec("RETRY INTENT; RELEASE;"); err != nil {
		t.Fatal(err)
	}
	_, err = tx.Exec("INSERT INTO t.test (k, v) VALUES (0, 'sentinel');")
	if !testutils.IsError(err, "current transaction is committed") {
		t.Fatal(err)
	}
	// Rollback should respond with a COMMIT command tag.
	err = tx.Rollback()
	if !testutils.IsError(err, "unexpected command tag COMMIT") {
		t.Fatal(err)
	}
}
예제 #6
0
// TestBatchError verifies that Range returns an error if a request has an invalid range.
func TestBatchError(t *testing.T) {
	testCases := []struct {
		req    [2]string
		errMsg string
	}{
		{
			req:    [2]string{"\xff\xff\xff\xff", "a"},
			errMsg: "must be less than KeyMax",
		},
		{
			req:    [2]string{"a", "\xff\xff\xff\xff"},
			errMsg: "must be less than or equal to KeyMax",
		},
	}

	for i, c := range testCases {
		var ba roachpb.BatchRequest
		ba.Add(&roachpb.ScanRequest{Span: roachpb.Span{Key: roachpb.Key(c.req[0]), EndKey: roachpb.Key(c.req[1])}})
		if _, err := Range(ba); !testutils.IsError(err, c.errMsg) {
			t.Errorf("%d: unexpected error %v", i, err)
		}
	}

	// Test a case where a non-range request has an end key.
	var ba roachpb.BatchRequest
	ba.Add(&roachpb.GetRequest{Span: roachpb.Span{Key: roachpb.Key("a"), EndKey: roachpb.Key("b")}})
	if _, err := Range(ba); !testutils.IsError(err, "end key specified for non-range operation") {
		t.Errorf("unexpected error %v", err)
	}
}
func TestApplySnapshotDenyPreemptive(t *testing.T) {
	defer leaktest.AfterTest(t)()

	var tc testContext
	tc.Start(t)
	defer tc.Stop()

	key := roachpb.RKey("a")
	realRng := tc.store.LookupReplica(key, nil)

	// Use Raft to get a nontrivial term for our snapshot.
	if pErr := realRng.redirectOnOrAcquireLease(context.Background()); pErr != nil {
		t.Fatal(pErr)
	}

	snap, err := realRng.GetSnapshot()
	if err != nil {
		t.Fatal(err)
	}

	// Make sure that the Term is behind our first range term (raftInitialLogTerm)
	snap.Metadata.Term--

	// Create an uninitialized version of the first range. This is only ok
	// because in the case we test, there's an error (and so we don't clobber
	// our actual first range in the Store). If we want snapshots to apply
	// successfully during tests, we need to adapt the snapshots to a new
	// RangeID first and generally do a lot more work.
	rng, err := NewReplica(&roachpb.RangeDescriptor{RangeID: 1}, tc.store, 0)
	if err != nil {
		t.Fatal(err)
	}

	if _, err := rng.applySnapshot(snap, raftpb.HardState{}); !testutils.IsError(
		err, "cannot apply preemptive snapshot from past term",
	) {
		t.Fatal(err)
	}

	// Do something that extends the Raft log past what we have in the
	// snapshot.
	put := putArgs(roachpb.Key("a"), []byte("foo"))
	if _, pErr := tc.SendWrapped(&put); pErr != nil {
		t.Fatal(pErr)
	}
	snap.Metadata.Term++ // restore the "real" term of the snapshot

	if _, err := rng.applySnapshot(snap, raftpb.HardState{}); !testutils.IsError(
		err, "would erase acknowledged log entries",
	) {
		t.Fatal(err)
	}

}
예제 #8
0
// TestKVDBInternalMethods verifies no internal methods are available
// HTTP DB interface.
func TestKVDBInternalMethods(t *testing.T) {
	defer leaktest.AfterTest(t)
	t.Skip("test broken & disabled; obsolete after after #2271")
	s := server.StartTestServer(t)
	defer s.Stop()

	testCases := []proto.Request{
		&proto.HeartbeatTxnRequest{},
		&proto.GCRequest{},
		&proto.PushTxnRequest{},
		&proto.RangeLookupRequest{},
		&proto.ResolveIntentRequest{},
		&proto.ResolveIntentRangeRequest{},
		&proto.MergeRequest{},
		&proto.TruncateLogRequest{},
		&proto.LeaderLeaseRequest{},

		&proto.EndTransactionRequest{
			InternalCommitTrigger: &proto.InternalCommitTrigger{},
		},
	}
	// Verify internal methods experience bad request errors.
	db := createTestClient(t, s.Stopper(), s.ServingAddr())
	for i, args := range testCases {
		args.Header().Key = proto.Key("a")
		if proto.IsRange(args) {
			args.Header().EndKey = args.Header().Key.Next()
		}
		b := &client.Batch{}
		b.InternalAddCall(proto.Call{Args: args, Reply: args.CreateReply()})
		err := db.Run(b).GoError()
		if err == nil {
			t.Errorf("%d: unexpected success calling %s", i, args.Method())
		} else if !testutils.IsError(err, "(couldn't find method|contains commit trigger)") {
			t.Errorf("%d: expected missing method %s; got %s", i, args.Method(), err)
		}

		// Verify same but within a Batch request.
		ba := &proto.BatchRequest{}
		ba.Add(args)
		b = &client.Batch{}
		b.InternalAddCall(proto.Call{Args: ba, Reply: &proto.BatchResponse{}})

		if err := db.Run(b).GoError(); err == nil {
			t.Errorf("%d: unexpected success calling %s", i, args.Method())
		} else if !testutils.IsError(err, "(contains an internal request|contains commit trigger)") {
			t.Errorf("%d: expected disallowed method error %s; got %s", i, args.Method(), err)
		}
	}
}
예제 #9
0
func TestEvalExprError(t *testing.T) {
	testData := []struct {
		expr     string
		expected string
	}{
		{`1 % 0`, `zero modulus`},
		{`1 / 0`, `division by zero`},
		{`'2010-09-28 12:00:00.1'::date`, `parsing time "2010-09-28 12:00:00.1": extra text`},
		{`'2010-09-28 12:00.1 MST'::timestamp`, `parsing time "2010-09-28 12:00.1 MST" as "2006-01-02 15:04:05.999999999 MST": cannot parse ".1 MST" as ":"`},
		{`'11h2m'::interval / 0`, `division by zero`},
		{`'hello' || b'world'`, `unsupported binary operator: <string> || <bytes>`},
		{`b'\xff\xfe\xfd'::string`, `invalid utf8: "\xff\xfe\xfd"`},
		// TODO(pmattis): Check for overflow.
		// {`~0 + 1`, `0`},
	}
	for _, d := range testData {
		q, err := ParseTraditional("SELECT " + d.expr)
		if err != nil {
			t.Fatalf("%s: %v", d.expr, err)
		}
		expr := q[0].(*Select).Exprs[0].Expr
		if _, err := defaultContext.EvalExpr(expr); !testutils.IsError(err, regexp.QuoteMeta(d.expected)) {
			t.Errorf("%s: expected %s, but found %v", d.expr, d.expected, err)
		}
	}
}
예제 #10
0
func TestTypeCheckSameTypedExprsError(t *testing.T) {
	floatConst := func(s string) Expr {
		return &NumVal{Value: constant.MakeFromLiteral(s, token.FLOAT, 0), OrigString: s}
	}

	floatIntMismatchErr := `expected .* to be of type (float|int), found type (float|int)`
	paramErr := `could not determine data type of parameter .*`

	testData := []struct {
		args        MapArgs
		desired     Datum
		exprs       []Expr
		expectedErr string
	}{
		{nil, nil, []Expr{NewDInt(1), floatConst("1.1")}, floatIntMismatchErr},
		{nil, nil, []Expr{NewDInt(1), NewDFloat(1)}, floatIntMismatchErr},
		{MapArgs{"a": TypeInt}, nil, []Expr{NewDFloat(1.1), ValArg{"a"}}, floatIntMismatchErr},
		{MapArgs{"a": TypeInt}, nil, []Expr{floatConst("1.1"), ValArg{"a"}}, floatIntMismatchErr},
		{MapArgs{"a": TypeFloat, "b": TypeInt}, nil, []Expr{ValArg{"b"}, ValArg{"a"}}, floatIntMismatchErr},
		{nil, nil, []Expr{ValArg{"b"}, ValArg{"a"}}, paramErr},
	}
	for i, d := range testData {
		forEachPerm(d.exprs, 0, func(exprs []Expr) {
			if _, _, err := typeCheckSameTypedExprs(d.args, d.desired, exprs...); !testutils.IsError(err, d.expectedErr) {
				t.Errorf("%d: expected %s, but found %v", i, d.expectedErr, err)
			}
		})
	}
}
예제 #11
0
func TestScanError(t *testing.T) {
	testData := []struct {
		sql string
		err string
	}{
		{`1e`, "invalid floating point literal"},
		{`1e-`, "invalid floating point literal"},
		{`1e+`, "invalid floating point literal"},
		{`0x`, "invalid hexadecimal literal"},
		{`1x`, "invalid hexadecimal literal"},
		{`1.x`, "invalid hexadecimal literal"},
		{`1.0x`, "invalid hexadecimal literal"},
		{`0x0x`, "invalid hexadecimal literal"},
		{`00x0x`, "invalid hexadecimal literal"},
		{`9223372036854775809`, "integer value out of range"},
		{`$9223372036854775809`, "integer value out of range"},
	}
	for _, d := range testData {
		s := makeScanner(d.sql, Traditional)
		var lval sqlSymType
		id := s.Lex(&lval)
		if id != ERROR {
			t.Errorf("%s: expected ERROR, but found %d", d.sql, id)
		}
		if !testutils.IsError(errors.New(lval.str), d.err) {
			t.Errorf("%s: expected %s, but found %s", d.sql, d.err, lval.str)
		}
	}
}
예제 #12
0
func TestTxnAbortCount(t *testing.T) {
	defer leaktest.AfterTest(t)()
	_, sender, cleanupFn := setupMetricsTest(t)
	defer cleanupFn()

	value := []byte("value")
	db := client.NewDB(sender)

	intentionalErrText := "intentional error to cause abort"
	// Test aborted transaction.
	if err := db.Txn(func(txn *client.Txn) error {
		key := []byte("key-abort")

		if err := txn.SetIsolation(roachpb.SNAPSHOT); err != nil {
			return err
		}

		if err := txn.Put(key, value); err != nil {
			t.Fatal(err)
		}

		return errors.New(intentionalErrText)
	}); !testutils.IsError(err, intentionalErrText) {
		t.Fatalf("unexpected error: %s", err)
	}
	teardownHeartbeats(sender)
	checkTxnMetrics(t, sender, "abort txn", 0, 0, 0, 1, 0)
}
예제 #13
0
// TestTxnCoordSenderErrorWithIntent validates that if a transactional request
// returns an error but also indicates a Writing transaction, the coordinator
// tracks it just like a successful request.
func TestTxnCoordSenderErrorWithIntent(t *testing.T) {
	defer leaktest.AfterTest(t)
	stopper := stop.NewStopper()
	manual := hlc.NewManualClock(0)
	clock := hlc.NewClock(manual.UnixNano)
	clock.SetMaxOffset(20)

	ts := NewTxnCoordSender(senderFn(func(_ context.Context, ba roachpb.BatchRequest) (*roachpb.BatchResponse, *roachpb.Error) {
		txn := ba.Txn.Clone()
		txn.Writing = true
		return nil, roachpb.NewError(roachpb.NewTransactionRetryError(txn))
	}), clock, false, nil, stopper)
	defer stopper.Stop()

	var ba roachpb.BatchRequest
	key := roachpb.Key("test")
	ba.Add(&roachpb.BeginTransactionRequest{Span: roachpb.Span{Key: key}})
	ba.Add(&roachpb.PutRequest{Span: roachpb.Span{Key: key}})
	ba.Add(&roachpb.EndTransactionRequest{})
	ba.Txn = &roachpb.Transaction{Name: "test"}
	if _, pErr := ts.Send(context.Background(), ba); !testutils.IsError(pErr.GoError(), "retry txn") {
		t.Fatalf("unexpected error: %v", pErr)
	}

	defer teardownHeartbeats(ts)
	ts.Lock()
	defer ts.Unlock()
	if len(ts.txns) != 1 {
		t.Fatalf("expected transaction to be tracked")
	}
}
예제 #14
0
// Tests that a retryable error for an inner txn doesn't cause the outer txn to
// be retried.
func TestWrongTxnRetry(t *testing.T) {
	defer leaktest.AfterTest(t)()
	db := NewDB(newTestSender(nil, nil))

	var retries int
	txnClosure := func(outerTxn *Txn) error {
		log.Infof(context.Background(), "outer retry")
		retries++
		// Ensure the KV transaction is created.
		if err := outerTxn.Put("a", "b"); err != nil {
			t.Fatal(err)
		}
		var execOpt TxnExecOptions
		execOpt.AutoRetry = false
		err := outerTxn.Exec(
			execOpt,
			func(innerTxn *Txn, opt *TxnExecOptions) error {
				// Ensure the KV transaction is created.
				if err := innerTxn.Put("x", "y"); err != nil {
					t.Fatal(err)
				}
				return roachpb.NewErrorWithTxn(&roachpb.TransactionPushError{
					PusheeTxn: outerTxn.Proto}, &innerTxn.Proto).GoError()
			})
		return err
	}

	if err := db.Txn(context.TODO(), txnClosure); !testutils.IsError(err, "failed to push") {
		t.Fatal(err)
	}
	if retries != 1 {
		t.Fatalf("unexpected retries: %d", retries)
	}
}
예제 #15
0
// TestAuthentication tests authentication for the KV endpoint.
func TestAuthentication(t *testing.T) {
	defer leaktest.AfterTest(t)()
	s, _, _ := serverutils.StartServer(t, base.TestServerArgs{})
	defer s.Stopper().Stop()

	var b1 client.Batch
	b1.Put("a", "b")

	// Create a node user client and call Run() on it which lets us build our own
	// request, specifying the user.
	db1 := createTestClientForUser(t, s.Stopper(), s.ServingAddr(), security.NodeUser)
	if err := db1.Run(&b1); err != nil {
		t.Fatal(err)
	}

	var b2 client.Batch
	b2.Put("c", "d")

	// Try again, but this time with certs for a non-node user (even the root
	// user has no KV permissions).
	db2 := createTestClientForUser(t, s.Stopper(), s.ServingAddr(), security.RootUser)
	if err := db2.Run(&b2); !testutils.IsError(err, "is not allowed") {
		t.Fatal(err)
	}
}
예제 #16
0
func TestVerifyClockOffset(t *testing.T) {
	defer leaktest.AfterTest(t)()

	clock := hlc.NewClock(hlc.NewManualClock(123).UnixNano)
	clock.SetMaxOffset(50 * time.Nanosecond)
	monitor := newRemoteClockMonitor(clock, time.Hour)

	for idx, tc := range []struct {
		offsets       []RemoteOffset
		expectedError bool
	}{
		// no error if no offsets.
		{[]RemoteOffset{}, false},
		// no error when a majority of offsets are under the maximum offset.
		{[]RemoteOffset{{Offset: 20, Uncertainty: 10}, {Offset: 58, Uncertainty: 20}, {Offset: 71, Uncertainty: 25}, {Offset: 91, Uncertainty: 31}}, false},
		// error when less than a majority of offsets are under the maximum offset.
		{[]RemoteOffset{{Offset: 20, Uncertainty: 10}, {Offset: 58, Uncertainty: 20}, {Offset: 85, Uncertainty: 25}, {Offset: 91, Uncertainty: 31}}, true},
	} {
		monitor.mu.offsets = make(map[string]RemoteOffset)
		for i, offset := range tc.offsets {
			monitor.mu.offsets[strconv.Itoa(i)] = offset
		}

		if tc.expectedError {
			if err := monitor.VerifyClockOffset(); !testutils.IsError(err, errOffsetGreaterThanMaxOffset) {
				t.Errorf("%d: unexpected error %v", idx, err)
			}
		} else {
			if err := monitor.VerifyClockOffset(); err != nil {
				t.Errorf("%d: unexpected error %s", idx, err)
			}
		}
	}
}
예제 #17
0
// verifyError checks that either no error was found where none was
// expected, or that an error was found when one was expected. Returns
// "true" to indicate the behavior was as expected.
func (t *logicTest) verifyError(
	sql string, pos string, expectErr string, expectErrCode string, err error) bool {
	if expectErr == "" && expectErrCode == "" && err != nil {
		return t.unexpectedError(sql, pos, err)
	}
	if expectErr != "" && !testutils.IsError(err, expectErr) {
		if err != nil {
			t.Errorf("%s: expected %q, but found\n%s", pos, expectErr, err)
		} else {
			t.Errorf("%s: expected %q, but found success", pos, expectErr)
		}
		return false
	}
	if expectErrCode != "" {
		if err != nil {
			pqErr, ok := err.(*pq.Error)
			if !ok {
				t.Errorf("%s: expected error code %q, but the error we found is not "+
					"a libpq error: %s", pos, expectErrCode, err)
				return false
			}
			if pqErr.Code != pq.ErrorCode(expectErrCode) {
				t.Errorf("%s: expected error code %q, but found code %q (%s)",
					pos, expectErrCode, pqErr.Code, pqErr.Code.Name())
				return false
			}
		} else {
			t.Errorf("%s: expected error code %q, but found success",
				pos, expectErrCode)
			return false
		}
	}
	return true
}
예제 #18
0
// TestNonRetryableError verifies that a non-retryable error is propagated to the client.
func TestNonRetryableError(t *testing.T) {
	defer leaktest.AfterTest(t)()

	ctx, cmdFilters := createTestServerContext()
	server, sqlDB, _ := setupWithContext(t, &ctx)
	defer cleanup(server, sqlDB)

	testKey := []byte("test_key")
	hitError := false
	cleanupFilter := cmdFilters.AppendFilter(
		func(args storagebase.FilterArgs) *roachpb.Error {
			if req, ok := args.Req.(*roachpb.ScanRequest); ok {
				if bytes.Contains(req.Key, testKey) {
					hitError = true
					return roachpb.NewErrorWithTxn(fmt.Errorf("testError"), args.Hdr.Txn)
				}
			}
			return nil
		}, false)
	defer cleanupFilter()

	sqlDB.SetMaxOpenConns(1)
	if _, err := sqlDB.Exec(`
CREATE DATABASE t;
CREATE TABLE t.test (k TEXT PRIMARY KEY, v TEXT);
INSERT INTO t.test (k, v) VALUES ('test_key', 'test_val');
SELECT * from t.test WHERE k = 'test_key';
`); !testutils.IsError(err, "pq: testError") {
		t.Errorf("unexpected error %s", err)
	}
	if !hitError {
		t.Errorf("expected to hit error, but it didn't happen")
	}
}
예제 #19
0
func TestTxnAbandonCount(t *testing.T) {
	defer leaktest.AfterTest(t)()
	manual, sender, cleanupFn := setupMetricsTest(t)
	defer cleanupFn()
	value := []byte("value")
	db := client.NewDB(sender)

	// Test abandoned transaction by making the client timeout ridiculously short. We also set
	// the sender to heartbeat very frequently, because the heartbeat detects and tears down
	// abandoned transactions.
	sender.heartbeatInterval = 2 * time.Millisecond
	sender.clientTimeout = 1 * time.Millisecond
	if err := db.Txn(func(txn *client.Txn) error {
		key := []byte("key-abandon")

		if err := txn.SetIsolation(roachpb.SNAPSHOT); err != nil {
			return err
		}

		if err := txn.Put(key, value); err != nil {
			return err
		}

		manual.Increment(int64(sender.clientTimeout + sender.heartbeatInterval*2))

		checkTxnMetrics(t, sender, "abandon txn", 0, 0, 1, 0, 0)

		return nil
	}); !testutils.IsError(err, "writing transaction timed out") {
		t.Fatalf("unexpected error: %s", err)
	}
}
예제 #20
0
func TestEvalExprError(t *testing.T) {
	testData := []struct {
		expr     string
		expected string
	}{
		{`'1' + '2'`, `unsupported binary operator:`},
		{`'a' + 0`, `unsupported binary operator:`},
		{`1.1 # 3.1`, `unsupported binary operator:`},
		{`~0.1`, `unsupported unary operator:`},
		{`'10' > 2`, `unsupported comparison operator:`},
		{`1 IN ('a', 'b')`, `unsupported comparison operator:`},
		{`a`, `column \"a\" not found`},
		{`1 AND true`, `cannot convert int to bool`},
		{`1.0 AND true`, `cannot convert float to bool`},
		{`'a' AND true`, `cannot convert string to bool`},
		{`(1, 2) AND true`, `cannot convert tuple to bool`},
		{`lower()`, `incorrect number of arguments`},
		{`lower(1, 2)`, `incorrect number of arguments`},
		{`lower(1)`, `argument type mismatch`},
		// TODO(pmattis): Check for overflow.
		// {`~0 + 1`, `0`, nil},
	}
	for _, d := range testData {
		q, err := Parse("SELECT " + d.expr)
		if err != nil {
			t.Fatalf("%s: %v", d.expr, err)
		}
		expr := q[0].(*Select).Exprs[0].(*NonStarExpr).Expr
		if _, err := EvalExpr(expr, mapEnv{}); !testutils.IsError(err, d.expected) {
			t.Errorf("%s: expected %s, but found %v", d.expr, d.expected, err)
		}
	}
}
예제 #21
0
// TestTxnCoordIdempotentCleanup verifies that cleanupTxnLocked is idempotent.
func TestTxnCoordIdempotentCleanup(t *testing.T) {
	defer leaktest.AfterTest(t)()
	s, sender := createTestDB(t)
	defer s.Stop()
	defer teardownHeartbeats(sender)

	txn := client.NewTxn(context.Background(), *s.DB)
	ba := txn.NewBatch()
	ba.Put(roachpb.Key("a"), []byte("value"))
	if err := txn.Run(ba); err != nil {
		t.Fatal(err)
	}

	sender.Lock()
	// Clean up twice successively.
	sender.cleanupTxnLocked(context.Background(), txn.Proto)
	sender.cleanupTxnLocked(context.Background(), txn.Proto)
	sender.Unlock()

	// For good measure, try to commit (which cleans up once more if it
	// succeeds, which it may not if the previous cleanup has already
	// terminated the heartbeat goroutine)
	ba = txn.NewBatch()
	ba.AddRawRequest(&roachpb.EndTransactionRequest{})
	err := txn.Run(ba)
	if err != nil && !testutils.IsError(err, errNoState.Error()) {
		t.Fatal(err)
	}
}
예제 #22
0
func (t *logicTest) verifyError(
	pos string, expectErr string, expectErrCode string, err error) {
	if expectErr == "" && expectErrCode == "" && err != nil {
		t.Fatalf("%s: expected success, but found\n%s", pos, err)
	}
	if expectErr != "" && !testutils.IsError(err, expectErr) {
		if err != nil {
			t.Fatalf("%s: expected %q, but found\n%s", pos, expectErr, err)
		} else {
			t.Fatalf("%s: expected %q, but found success", pos, expectErr)
		}
	}
	if expectErrCode != "" {
		if err != nil {
			pqErr, ok := err.(*pq.Error)
			if !ok {
				t.Fatalf("%s: expected error code %q, but the error we found is not "+
					"a libpq error: %s", pos, expectErrCode, err)
			}
			if pqErr.Code != pq.ErrorCode(expectErrCode) {
				t.Fatalf("%s: expected error code %q, but found code %q (%s)",
					pos, expectErrCode, pqErr.Code, pqErr.Code.Name())
			}
		} else {
			t.Fatalf("%s: expected error code %q, but found success",
				pos, expectErrCode)
		}
	}
}
예제 #23
0
// Returns true on retriable errors.
func runTestTxn(t *testing.T, magicVals *filterVals, expectedErr string,
	injectReleaseError *bool, sqlDB *gosql.DB, tx *gosql.Tx) bool {
	retriesNeeded :=
		(magicVals.restartCounts["boulanger"] + magicVals.abortCounts["boulanger"]) > 0
	var err error
	if retriesNeeded {
		_, err = tx.Exec("INSERT INTO t.test (k, v) VALUES (1, 'boulanger')")
		if !testutils.IsError(err, expectedErr) {
			t.Fatalf("expected to fail here. err: %v", err)
		}
		return isRetryableErr(err)
	}
	// Now the INSERT should succeed.
	_, err = tx.Exec("DELETE FROM t.test WHERE true; INSERT INTO t.test (k, v) VALUES (0, 'sentinel');")
	if err != nil {
		t.Fatal(err)
	}

	retriesNeeded = *injectReleaseError
	if retriesNeeded {
		*injectReleaseError = false
		abortTxn(t, sqlDB, 0)
	}
	_, err = tx.Exec("RELEASE SAVEPOINT cockroach_restart")
	if retriesNeeded {
		if err == nil {
			t.Fatal("expected RELEASE to fail")
		}
	} else {
		if err != nil {
			t.Fatal(err)
		}
	}
	return isRetryableErr(err)
}
예제 #24
0
// TestNonRetryableError verifies that a non-retryable error from the
// execution of EndTransactionRequests is propagated to the client.
func TestNonRetryableErrorFromCommit(t *testing.T) {
	defer leaktest.AfterTest(t)()

	params, cmdFilters := createTestServerParams()
	s, sqlDB, _ := serverutils.StartServer(t, params)
	defer s.Stopper().Stop()

	hitError := false
	cleanupFilter := cmdFilters.AppendFilter(
		func(args storagebase.FilterArgs) *roachpb.Error {
			if req, ok := args.Req.(*roachpb.EndTransactionRequest); ok {
				if bytes.Contains(req.Key, []byte(keys.DescIDGenerator)) {
					hitError = true
					return roachpb.NewErrorWithTxn(fmt.Errorf("testError"), args.Hdr.Txn)
				}
			}
			return nil
		}, false)
	defer cleanupFilter()

	if _, err := sqlDB.Exec("CREATE DATABASE t;"); !testutils.IsError(err, "pq: testError") {
		t.Errorf("unexpected error %v", err)
	}
	if !hitError {
		t.Errorf("expected to hit error, but it didn't happen")
	}
}
예제 #25
0
// TestClientForwardUnresolved verifies that a client does not resolve a forward
// address prematurely.
func TestClientForwardUnresolved(t *testing.T) {
	defer leaktest.AfterTest(t)()
	stopper := stop.NewStopper()
	defer stopper.Stop()
	const nodeID = 1
	local := startGossip(nodeID, stopper, t)
	local.mu.Lock()
	addr := local.is.NodeAddr
	local.mu.Unlock()

	client := newClient(&addr) // never started

	newAddr := util.UnresolvedAddr{
		NetworkField: "tcp",
		AddressField: "localhost:2345",
	}
	reply := &Response{
		NodeID:          nodeID,
		Addr:            addr,
		AlternateNodeID: nodeID + 1,
		AlternateAddr:   &newAddr,
	}
	if err := client.handleResponse(local, reply); !testutils.IsError(err, "received forward") {
		t.Fatal(err)
	}
	if !proto.Equal(client.forwardAddr, &newAddr) {
		t.Fatalf("unexpected forward address %v, expected %v", client.forwardAddr, &newAddr)
	}
}
예제 #26
0
// TestCorruptedClusterID verifies that a node fails to start when a
// store's cluster ID is empty.
func TestCorruptedClusterID(t *testing.T) {
	defer leaktest.AfterTest(t)
	engineStopper := stop.NewStopper()
	e := engine.NewInMem(roachpb.Attributes{}, 1<<20, engineStopper)
	defer engineStopper.Stop()
	if _, err := bootstrapCluster([]engine.Engine{e}); err != nil {
		t.Fatal(err)
	}

	// Set the cluster ID to an empty string.
	sIdent := roachpb.StoreIdent{
		ClusterID: "",
		NodeID:    1,
		StoreID:   1,
	}
	if err := engine.MVCCPutProto(e, nil, keys.StoreIdentKey(), roachpb.ZeroTimestamp, nil, &sIdent); err != nil {
		t.Fatal(err)
	}

	engines := []engine.Engine{e}
	server, serverAddr, _, node, stopper := createTestNode(util.CreateTestAddr("tcp"), engines, nil, t)
	stopper.Stop()
	if err := node.start(server, serverAddr, engines, roachpb.Attributes{}); !testutils.IsError(err, "unidentified store") {
		t.Errorf("unexpected error %v", err)
	}
}
예제 #27
0
func TestEvalExprError(t *testing.T) {
	testData := []struct {
		expr     string
		expected string
	}{
		{`'1' + '2'`, `unsupported binary operator:`},
		{`'a' + 0`, `unsupported binary operator:`},
		{`1.1 # 3.1`, `unsupported binary operator:`},
		{`~0.1`, `unsupported unary operator:`},
		{`'10' > 2`, `unsupported comparison operator:`},
		{`a`, `column \"a\" not found`},
		// TODO(pmattis): Check for overflow.
		// {`~0 + 1`, `0`, nil},
	}
	for _, d := range testData {
		q, err := Parse("SELECT " + d.expr)
		if err != nil {
			t.Fatalf("%s: %v: %s", d.expr, err, d.expr)
		}
		expr := q[0].(*Select).Exprs[0].(*NonStarExpr).Expr
		if _, err := EvalExpr(expr, mapEnv{}); !testutils.IsError(err, d.expected) {
			t.Errorf("%s: expected %s, but found %v", d.expr, d.expected, err)
		}
	}
}
예제 #28
0
// TestCorruptedClusterID verifies that a node fails to start when a
// store's cluster ID is empty.
func TestCorruptedClusterID(t *testing.T) {
	defer leaktest.AfterTest(t)()
	engineStopper := stop.NewStopper()
	e := engine.NewInMem(roachpb.Attributes{}, 1<<20, engineStopper)
	defer engineStopper.Stop()
	if _, err := bootstrapCluster([]engine.Engine{e}, kv.NewTxnMetrics(metric.NewRegistry())); err != nil {
		t.Fatal(err)
	}

	// Set the cluster ID to the empty UUID.
	sIdent := roachpb.StoreIdent{
		ClusterID: *uuid.EmptyUUID,
		NodeID:    1,
		StoreID:   1,
	}
	if err := engine.MVCCPutProto(context.Background(), e, nil, keys.StoreIdentKey(), roachpb.ZeroTimestamp, nil, &sIdent); err != nil {
		t.Fatal(err)
	}

	engines := []engine.Engine{e}
	_, serverAddr, _, node, stopper := createTestNode(util.TestAddr, engines, nil, t)
	stopper.Stop()
	if err := node.start(serverAddr, engines, roachpb.Attributes{}); !testutils.IsError(err, "unidentified store") {
		t.Errorf("unexpected error %v", err)
	}
}
예제 #29
0
// TestRocksDBOpenWithVersions verifies the version checking in Open()
// functions correctly.
func TestRocksDBOpenWithVersions(t *testing.T) {
	defer leaktest.AfterTest(t)()

	testCases := []struct {
		hasFile     bool
		ver         Version
		expectedErr string
	}{
		{false, Version{}, ""},
		{true, Version{versionCurrent}, ""},
		{true, Version{versionMinimum}, ""},
		{true, Version{-1}, "incompatible rocksdb data version, current:1, on disk:-1, minimum:0"},
		{true, Version{2}, "incompatible rocksdb data version, current:1, on disk:2, minimum:0"},
	}

	for i, testCase := range testCases {
		err := openRocksDBWithVersion(t, testCase.hasFile, testCase.ver)
		if err == nil && len(testCase.expectedErr) == 0 {
			continue
		}
		if !testutils.IsError(err, testCase.expectedErr) {
			t.Errorf("%d: expected error '%s', actual '%s'", i, testCase.expectedErr, err)
		}
	}
}
예제 #30
0
func TestDropTableInTxn(t *testing.T) {
	defer leaktest.AfterTest(t)()
	s, sqlDB, _ := setup(t)
	defer cleanup(s, sqlDB)

	if _, err := sqlDB.Exec(`
CREATE DATABASE t;
CREATE TABLE t.kv (k CHAR PRIMARY KEY, v CHAR);
`); err != nil {
		t.Fatal(err)
	}

	tx, err := sqlDB.Begin()
	if err != nil {
		t.Fatal(err)
	}

	if _, err := tx.Exec(`DROP TABLE t.kv`); err != nil {
		t.Fatal(err)
	}

	// We might still be able to read/write in the table inside this transaction
	// until the schema changer runs, but we shouldn't be able to ALTER it.
	if _, err := tx.Exec(`ALTER TABLE t.kv ADD COLUMN w CHAR`); !testutils.IsError(err,
		`table "kv" has been deleted`) {
		t.Fatalf("different error than expected: %s", err)
	}

	// Can't commit after ALTER errored, so we ROLLBACK.
	if err := tx.Rollback(); err != nil {
		t.Fatal(err)
	}

}