예제 #1
0
func createTestServerContext() (*server.Context, *CommandFilters) {
	ctx := server.NewTestContext()
	var cmdFilters CommandFilters
	cmdFilters.AppendFilter(checkEndTransactionTrigger, true)
	ctx.TestingKnobs.StoreTestingKnobs.TestingCommandFilter = cmdFilters.runFilters
	return ctx, &cmdFilters
}
예제 #2
0
// benchmarkSelect1 is a benchmark of the simplest SQL query: SELECT 1. This
// query requires no tables, expression analysis, etc. As such, it is measuring
// the overhead of parsing and other non-table processing (e.g. reading
// requests, writing responses).
func benchmarkSelect1(b *testing.B, scheme string) {
	s := &server.TestServer{}
	s.Ctx = server.NewTestContext()
	s.Ctx.Insecure = (scheme == "http" || scheme == "rpc")
	if err := s.Start(); err != nil {
		b.Fatal(err)
	}
	defer s.Stop()

	db, err := sql.Open("cockroach",
		scheme+"://node@"+s.ServingAddr()+"?certs="+s.Ctx.Certs)
	if err != nil {
		b.Fatal(err)
	}
	defer db.Close()

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		rows, err := db.Query(`SELECT 1`)
		if err != nil {
			b.Fatal(err)
		}
		rows.Close()
	}
	b.StopTimer()
}
예제 #3
0
func TestProtocols(t *testing.T) {
	defer leaktest.AfterTest(t)

	// Test that all of the network protocols work.
	for _, scheme := range []string{"http", "https", "rpc", "rpcs"} {
		func() {
			// Start test server in insecure mode.
			s := &server.TestServer{}
			s.Ctx = server.NewTestContext()
			s.Ctx.Insecure = (scheme == "http" || scheme == "rpc")
			if err := s.Start(); err != nil {
				t.Fatalf("Could not start server: %v", err)
			}
			defer s.Stop()

			db, err := sql.Open("cockroach",
				scheme+"://node@"+s.ServingAddr()+"?certs="+s.Ctx.Certs)
			if err != nil {
				t.Fatal(err)
			}
			defer db.Close()

			if _, err := db.Exec(`SELECT 1`); err != nil {
				t.Fatal(err)
			}
		}()
	}
}
예제 #4
0
func ExampleDB_Put_insecure() {
	s := &server.TestServer{}
	s.Ctx = server.NewTestContext()
	s.Ctx.Insecure = true
	if pErr := s.Start(); pErr != nil {
		log.Fatalf("Could not start server: %v", pErr)
	}
	defer s.Stop()

	db, err := client.Open(s.Stopper(), "rpc://foo@"+s.ServingAddr())
	if err != nil {
		log.Fatal(err)
	}

	if pErr := db.Put("aa", "1"); pErr != nil {
		panic(pErr)
	}
	result, pErr := db.Get("aa")
	if pErr != nil {
		panic(pErr)
	}
	fmt.Printf("aa=%s\n", result.ValueBytes())

	// Output:
	// aa=1
}
예제 #5
0
func ExampleDB_Insecure() {
	s := &server.TestServer{}
	s.Ctx = server.NewTestContext()
	s.Ctx.Insecure = true
	if err := s.Start(); err != nil {
		log.Fatalf("Could not start server: %v", err)
	}
	log.Printf("Test server listening on %s: %s", s.Ctx.RequestScheme(), s.ServingAddr())
	defer s.Stop()

	db, err := client.Open("http://root@" + s.ServingAddr())
	if err != nil {
		log.Fatal(err)
	}

	if err := db.Put("aa", "1"); err != nil {
		panic(err)
	}
	result, err := db.Get("aa")
	if err != nil {
		panic(err)
	}
	fmt.Printf("aa=%s\n", result.ValueBytes())

	// Output:
	// aa=1
}
예제 #6
0
func (t *parallelTest) setup() {
	ctx := server.NewTestContext()
	ctx.MaxOffset = logicMaxOffset
	ctx.TestingKnobs.ExecutorTestingKnobs.WaitForGossipUpdate = true
	ctx.TestingKnobs.ExecutorTestingKnobs.CheckStmtStringChange = true
	t.srv = setupTestServerWithContext(t.T, ctx)
}
예제 #7
0
func TestInsecure(t *testing.T) {
	defer leaktest.AfterTest(t)
	// Start test server in insecure mode.
	s := &server.TestServer{}
	s.Ctx = server.NewTestContext()
	s.Ctx.Insecure = true
	if err := s.Start(); err != nil {
		t.Fatalf("Could not start server: %v", err)
	}
	t.Logf("Test server listening on %s: %s", s.Ctx.RequestScheme(), s.ServingAddr())
	defer s.Stop()

	// We can't attempt a connection through HTTPS since the client just retries forever.
	// DB connection using plain HTTP.
	db, err := sql.Open("cockroach", "http://root@"+s.ServingAddr())
	if err != nil {
		t.Fatal(err)
	}
	defer func() {
		_ = db.Close()
	}()
	if _, err := db.Exec(`SELECT 1`); err != nil {
		t.Fatal(err)
	}
}
예제 #8
0
func createTestServerContext() (*server.Context, *CommandFilters) {
	ctx := server.NewTestContext()
	var cmdFilters CommandFilters
	cmdFilters.AppendFilter(checkEndTransactionTrigger, true)
	// Disable one phase commits as they otherwise confuse the
	// various bits of machinery in sql tests which inject via
	// the testing command filter and inspect the transaction.
	ctx.TestingKnobs.StoreTestingKnobs.DisableOnePhaseCommits = true
	ctx.TestingKnobs.StoreTestingKnobs.TestingCommandFilter = cmdFilters.runFilters
	return ctx, &cmdFilters
}
예제 #9
0
func (t *parallelTest) run(dir string) {
	fmt.Printf("Running test %s\n", dir)
	// Set up database
	defer t.close()
	ctx := server.NewTestContext()
	ctx.MaxOffset = logicMaxOffset
	t.srv = setupTestServer(t.T)

	// Add the main client and set up the database.
	t.addClient(true)

	// Open the main faile.
	mainFile := filepath.Join(dir, "main")
	file, err := os.Open(mainFile)
	if err != nil {
		t.Fatal(err)
	}
	defer file.Close()
	s := newLineScanner(file)
	for s.Scan() {
		fields := strings.Fields(s.Text())
		if len(fields) == 0 {
			continue
		}
		cmd := fields[0]
		if strings.HasPrefix(cmd, "#") {
			// Skip comment lines.
			continue
		}
		switch cmd {
		case "run":
			testFiles := fields[1:]
			for len(t.clients) < len(testFiles) {
				t.addClient(false)
			}
			if testing.Verbose() || log.V(1) {
				fmt.Printf("%s:%d: running %s\n", mainFile, s.line, strings.Join(testFiles, ","))
			}
			ch := make(chan bool)
			for i, f := range testFiles {
				go t.processTestFile(filepath.Join(dir, f), t.clients[i].db, ch)
			}
			// Wait for all clients to complete.
			for range testFiles {
				<-ch
			}
		default:
			t.Fatalf("%s:%d: unknown command: %s", mainFile, s.line, cmd)
		}
	}
}
예제 #10
0
func TestLeaseManagerReacquire(testingT *testing.T) {
	defer leaktest.AfterTest(testingT)()
	t := newLeaseTest(testingT, server.NewTestContext())
	defer t.cleanup()

	const descID = keys.LeaseTableID

	// Acquire 2 leases from the same node. They should point to the same lease
	// structure.
	l1 := t.mustAcquire(1, descID, 0)
	l2 := t.mustAcquire(1, descID, 0)
	if l1 != l2 {
		t.Fatalf("expected same lease, but found %p != %p", l1, l2)
	}
	if l1.Refcount() != 2 {
		t.Fatalf("expected refcount of 2, but found %d", l1.Refcount())
	}
	t.expectLeases(descID, "/1/1")

	// Set the minimum lease duration such that the next lease acquisition will
	// require the lease to be reacquired.
	savedLeaseDuration, savedMinLeaseDuration := csql.LeaseDuration, csql.MinLeaseDuration
	defer func() {
		csql.LeaseDuration, csql.MinLeaseDuration = savedLeaseDuration, savedMinLeaseDuration
	}()
	csql.MinLeaseDuration = l1.Expiration().Sub(timeutil.Now())
	csql.LeaseDuration = 2 * csql.MinLeaseDuration

	// Another lease acquisition from the same node will result in a new lease.
	l3 := t.mustAcquire(1, descID, 0)
	if l1 == l3 {
		t.Fatalf("expected different leases, but found %p", l1)
	}
	if l3.Refcount() != 1 {
		t.Fatalf("expected refcount of 1, but found %d", l3.Refcount())
	}
	if l3.Expiration().Before(l1.Expiration()) {
		t.Fatalf("expected new lease expiration (%s) to be after old lease expiration (%s)",
			l3.Expiration(), l1.Expiration())
	}
	t.expectLeases(descID, "/1/1 /1/1")

	t.mustRelease(1, l1)
	t.mustRelease(1, l2)
	t.mustRelease(1, l3)
}
예제 #11
0
// benchmarkSelect1 is a benchmark of the simplest SQL query: SELECT 1. This
// query requires no tables, expression analysis, etc. As such, it is measuring
// the overhead of parsing and other non-table processing (e.g. reading
// requests, writing responses).
func benchmarkSelect1(b *testing.B, scheme string) {
	s := &server.TestServer{}
	s.Ctx = server.NewTestContext()
	s.Ctx.Insecure = (scheme == "http" || scheme == "rpc")
	if err := s.Start(); err != nil {
		b.Fatal(err)
	}
	defer s.Stop()

	db, err := sql.Open("cockroach",
		scheme+"://node@"+s.ServingAddr()+"?certs="+s.Ctx.Certs)
	if err != nil {
		b.Fatal(err)
	}
	defer db.Close()

	runBenchmarkSelect1(b, db)
}
예제 #12
0
func (t *logicTest) setup() {
	// TODO(pmattis): Add a flag to make it easy to run the tests against a local
	// MySQL or Postgres instance.
	ctx := server.NewTestContext()
	ctx.MaxOffset = logicMaxOffset
	t.srv = setupTestServerWithContext(t.T, ctx)

	// db may change over the lifetime of this function, with intermediate
	// values cached in t.clients and finally closed in t.close().
	t.cleanupRootUser = t.setUser(security.RootUser)

	if _, err := t.db.Exec(`
CREATE DATABASE test;
SET DATABASE = test;
`); err != nil {
		t.Fatal(err)
	}
}
예제 #13
0
// Test that if there's an error on COMMIT that needs to be reported to the user
// the txn will be rolled back. As opposed to an error on a COMMIT in an auto-retry
// txn, where we retry the txn (not tested here).
func TestErrorOnCommit(t *testing.T) {
	defer leaktest.AfterTest(t)()

	ctx := server.NewTestContext()
	ctx.TestingKnobs.SQLExecutor = &sql.ExecutorTestingKnobs{FixTxnPriority: true}
	server, sqlDB, _ := setupWithContext(t, ctx)
	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("SAVEPOINT cockroach_restart; SET TRANSACTION PRIORITY LOW;"); err != nil {
		t.Fatal(err)
	}
	if _, err = tx.Exec("INSERT INTO t.test (k, v) VALUES (0, 'sentinel');"); err != nil {
		t.Fatal(err)
	}

	abortTxn(t, sqlDB, 0)

	if err = tx.Commit(); err == nil {
		t.Fatal("expected commit to fail")
	}

	// Check that there's no error reading and we don't see any rows.
	var rows *gosql.Rows
	if rows, err = sqlDB.Query("SELECT * FROM t.test"); err != nil {
		t.Fatal(err)
	}
	if rows.Next() {
		var k int
		var v string
		_ = rows.Scan(&k, &v)
		t.Fatalf("found unexpected row: %d %s", k, v)
	}
	rows.Close()
}
예제 #14
0
func Example_insecure() {
	c := cliTest{}
	c.TestServer = &server.TestServer{}
	c.Ctx = server.NewTestContext()
	c.Ctx.Insecure = true
	if err := c.Start(); err != nil {
		log.Fatalf("Could not start server: %v", err)
	}
	defer c.Stop()

	c.Run("kv --insecure put a 1 b 2")
	c.Run("kv --insecure scan")

	// Output:
	// kv --insecure put a 1 b 2
	// kv --insecure scan
	// "a"	"1"
	// "b"	"2"
	// 2 result(s)
}
예제 #15
0
func Example_insecure() {
	c := cliTest{cleanupFunc: func() {}}
	c.TestServer = &server.TestServer{}
	c.Ctx = server.NewTestContext()
	c.Ctx.Insecure = true
	if err := c.Start(); err != nil {
		log.Fatalf("Could not start server: %v", err)
	}
	defer c.stop()

	c.Run("debug kv put --insecure a 1 b 2")
	c.Run("debug kv scan --insecure")

	// Output:
	// debug kv put --insecure a 1 b 2
	// debug kv scan --insecure
	// "a"	"1"
	// "b"	"2"
	// 2 result(s)
}
예제 #16
0
func Example_insecure() {
	c := cliTest{}
	c.TestServer = &server.TestServer{}
	c.Ctx = server.NewTestContext()
	c.Ctx.Insecure = true
	if err := c.Start(); err != nil {
		log.Fatalf("Could not start server: %v", err)
	}

	c.Run("kv --insecure put a 1 b 2")
	c.Run("kv --insecure scan")
	c.Run("quit --insecure")

	// Output:
	// kv --insecure put a 1 b 2
	// kv --insecure scan
	// "a"	"1"
	// "b"	"2"
	// quit --insecure
	// node drained and shutdown: ok
}
예제 #17
0
func ExampleDB_Put_insecure() {
	s := &server.TestServer{}
	s.Ctx = server.NewTestContext()
	s.Ctx.Insecure = true
	if pErr := s.Start(); pErr != nil {
		log.Fatalf("Could not start server: %v", pErr)
	}
	defer s.Stop()

	db := s.DB()
	if pErr := db.Put("aa", "1"); pErr != nil {
		panic(pErr)
	}
	result, pErr := db.Get("aa")
	if pErr != nil {
		panic(pErr)
	}
	fmt.Printf("aa=%s\n", result.ValueBytes())

	// Output:
	// aa=1
}
예제 #18
0
func TestLeaseManagerPublishVersionChanged(testingT *testing.T) {
	defer leaktest.AfterTest(testingT)()
	t := newLeaseTest(testingT, server.NewTestContext())
	defer t.cleanup()

	const descID = keys.LeaseTableID

	// Start two goroutines that are concurrently trying to publish a new version
	// of the descriptor. The first goroutine progresses to the update function
	// and then signals the second goroutine to start which is allowed to proceed
	// through completion. The first goroutine is then signaled and when it
	// attempts to publish the new version it will encounter an update error and
	// retry the transaction. Upon retry it will see that the descriptor version
	// has changed and have to proceed to its outer retry loop and wait for the
	// number of leases on the previous version to drop to 0.

	n1 := t.node(1)
	n2 := t.node(2)

	n1update := make(chan struct{})
	n2start := make(chan struct{})
	var wg sync.WaitGroup
	wg.Add(2)

	go func(n1update, n2start chan struct{}) {
		_, err := n1.Publish(descID, func(*sqlbase.TableDescriptor) error {
			if n2start != nil {
				// Signal node 2 to start.
				close(n2start)
				n2start = nil
			}
			// Wait for node 2 signal indicating that node 2 finished publication of
			// a new version.
			<-n1update
			return nil
		})
		if err != nil {
			panic(err)
		}
		wg.Done()
	}(n1update, n2start)

	go func(n1update, n2start chan struct{}) {
		// Wait for node 1 signal indicating that node 1 is in its update()
		// function.
		<-n2start
		_, err := n2.Publish(descID, func(*sqlbase.TableDescriptor) error {
			return nil
		})
		if err != nil {
			panic(err)
		}
		close(n1update)
		wg.Done()
	}(n1update, n2start)

	wg.Wait()

	t.mustAcquire(1, descID, 0)
	t.expectLeases(descID, "/3/1")
}
예제 #19
0
func setupClientBenchData(useSSL bool, numVersions, numKeys int, b *testing.B) (
	*server.TestServer, *client.DB) {
	const cacheSize = 8 << 30        // 8 GB
	const memtableBudget = 512 << 20 // 512 MB
	loc := fmt.Sprintf("client_bench_%d_%d", numVersions, numKeys)

	exists := true
	if _, err := os.Stat(loc); os.IsNotExist(err) {
		exists = false
	}

	s := &server.TestServer{}
	s.Ctx = server.NewTestContext()
	s.SkipBootstrap = exists
	if !useSSL {
		s.Ctx.Insecure = true
	}
	stopper := stop.NewStopper()
	s.Ctx.Engines = []engine.Engine{
		engine.NewRocksDB(roachpb.Attributes{Attrs: []string{"ssd"}}, loc,
			cacheSize, memtableBudget, stopper),
	}
	if err := s.StartWithStopper(stopper); err != nil {
		b.Fatal(err)
	}

	db, err := client.Open(s.Stopper(), fmt.Sprintf("%s://%s@%s?certs=%s",
		s.Ctx.RPCRequestScheme(), security.NodeUser, s.ServingAddr(), s.Ctx.Certs))
	if err != nil {
		b.Fatal(err)
	}

	if exists {
		return s, db
	}

	rng, _ := randutil.NewPseudoRand()
	keys := make([]roachpb.Key, numKeys)
	nvs := make([]int, numKeys)
	for t := 1; t <= numVersions; t++ {
		batch := &client.Batch{}
		for i := 0; i < numKeys; i++ {
			if t == 1 {
				keys[i] = roachpb.Key(encoding.EncodeUvarintAscending([]byte("key-"), uint64(i)))
				nvs[i] = int(rand.Int31n(int32(numVersions)) + 1)
			}
			// Only write values if this iteration is less than the random
			// number of versions chosen for this key.
			if t <= nvs[i] {
				batch.Put(roachpb.Key(keys[i]), randutil.RandBytes(rng, valueSize))
			}
			if (i+1)%1000 == 0 {
				if pErr := db.Run(batch); pErr != nil {
					b.Fatal(pErr)
				}
				batch = &client.Batch{}
			}
		}
		if len(batch.Results) != 0 {
			if pErr := db.Run(batch); pErr != nil {
				b.Fatal(pErr)
			}
		}
	}

	if r, ok := s.Ctx.Engines[0].(*engine.RocksDB); ok {
		r.CompactRange(engine.NilKey, engine.NilKey)
	}

	return s, db
}
예제 #20
0
func setupClientBenchData(useRPC, useSSL bool, numVersions, numKeys int, b *testing.B) (
	*server.TestServer, *client.DB) {
	const cacheSize = 8 << 30 // 8 GB
	loc := fmt.Sprintf("client_bench_%d_%d", numVersions, numKeys)

	exists := true
	if _, err := os.Stat(loc); os.IsNotExist(err) {
		exists = false
	}

	s := &server.TestServer{}
	s.Ctx = server.NewTestContext()
	s.Ctx.ExperimentalRPCServer = true
	s.SkipBootstrap = exists
	if !useSSL {
		s.Ctx.Insecure = true
	}
	s.Engines = []engine.Engine{engine.NewRocksDB(proto.Attributes{Attrs: []string{"ssd"}}, loc, cacheSize)}
	if err := s.Start(); err != nil {
		b.Fatal(err)
	}

	var scheme string
	if useRPC {
		scheme = "rpcs"
	} else {
		scheme = "https"
	}

	db, err := client.Open(scheme + "://root@" + s.ServingAddr() + "?certs=" + s.Ctx.Certs)
	if err != nil {
		b.Fatal(err)
	}

	if exists {
		return s, db
	}

	rng, _ := util.NewPseudoRand()
	keys := make([]proto.Key, numKeys)
	nvs := make([]int, numKeys)
	for t := 1; t <= numVersions; t++ {
		batch := &client.Batch{}
		for i := 0; i < numKeys; i++ {
			if t == 1 {
				keys[i] = proto.Key(encoding.EncodeUvarint([]byte("key-"), uint64(i)))
				nvs[i] = int(rand.Int31n(int32(numVersions)) + 1)
			}
			// Only write values if this iteration is less than the random
			// number of versions chosen for this key.
			if t <= nvs[i] {
				batch.Put(proto.Key(keys[i]), util.RandBytes(rng, valueSize))
			}
			if (i+1)%1000 == 0 {
				if err := db.Run(batch); err != nil {
					b.Fatal(err)
				}
				batch = &client.Batch{}
			}
		}
		if len(batch.Results) != 0 {
			if err := db.Run(batch); err != nil {
				b.Fatal(err)
			}
		}
	}

	if r, ok := s.Engines[0].(*engine.RocksDB); ok {
		r.CompactRange(nil, nil)
	}

	return s, db
}
예제 #21
0
func TestPGWire(t *testing.T) {
	defer leaktest.AfterTest(t)

	certUser := server.TestUser
	certPath := security.ClientCertPath(security.EmbeddedCertsDir, certUser)
	keyPath := security.ClientKeyPath(security.EmbeddedCertsDir, certUser)

	tempDir, err := ioutil.TempDir("", "TestPGWire")
	if err != nil {
		t.Fatal(err)
	}

	defer func() {
		if err := os.RemoveAll(tempDir); err != nil {
			// Not Fatal() because we might already be panicking.
			t.Error(err)
		}
	}()

	// Copy these assets to disk from embedded strings, so this test can
	// run from a standalone binary.
	tempCertPath := securitytest.RestrictedCopy(t, certPath, tempDir, "cert")
	tempKeyPath := securitytest.RestrictedCopy(t, keyPath, tempDir, "key")

	for _, insecure := range [...]bool{true, false} {
		ctx := server.NewTestContext()
		ctx.Insecure = insecure
		s := setupTestServerWithContext(t, ctx)

		host, port, err := net.SplitHostPort(s.PGAddr())
		if err != nil {
			t.Fatal(err)
		}

		basePgUrl := url.URL{
			Scheme: "postgres",
			Host:   net.JoinHostPort(host, port),
		}
		if err := trivialQuery(basePgUrl); err != nil {
			if insecure {
				if err != pq.ErrSSLNotSupported {
					t.Error(err)
				}
			} else {
				if !testutils.IsError(err, "no client certificates in request") {
					t.Error(err)
				}
			}
		}

		{
			disablePgUrl := basePgUrl
			disablePgUrl.RawQuery = "sslmode=disable"
			err := trivialQuery(disablePgUrl)
			if insecure {
				if err != nil {
					t.Error(err)
				}
			} else {
				if !testutils.IsError(err, pgwire.ErrSSLRequired) {
					t.Error(err)
				}
			}
		}

		{
			requirePgUrlNoCert := basePgUrl
			requirePgUrlNoCert.RawQuery = "sslmode=require"
			err := trivialQuery(requirePgUrlNoCert)
			if insecure {
				if err != pq.ErrSSLNotSupported {
					t.Error(err)
				}
			} else {
				if !testutils.IsError(err, "no client certificates in request") {
					t.Error(err)
				}
			}
		}

		{
			for _, optUser := range []string{certUser, security.RootUser} {
				requirePgUrlWithCert := basePgUrl
				requirePgUrlWithCert.User = url.User(optUser)
				requirePgUrlWithCert.RawQuery = fmt.Sprintf("sslmode=require&sslcert=%s&sslkey=%s",
					url.QueryEscape(tempCertPath),
					url.QueryEscape(tempKeyPath),
				)
				err := trivialQuery(requirePgUrlWithCert)
				if insecure {
					if err != pq.ErrSSLNotSupported {
						t.Error(err)
					}
				} else {
					if optUser == certUser {
						if err != nil {
							t.Error(err)
						}
					} else {
						if !testutils.IsError(err, `requested user is \w+, but certificate is for \w+`) {
							t.Error(err)
						}
					}
				}
			}
		}

		cleanupTestServer(s)
	}
}
예제 #22
0
func setupTestServer(t *testing.T) *server.TestServer {
	return setupTestServerWithContext(t, server.NewTestContext())
}
// TestPropagateTxnOnError verifies that DistSender.sendChunk properly
// propagates the txn data to a next iteration. Use txn.Writing field to
// verify that.
func TestPropagateTxnOnError(t *testing.T) {
	defer leaktest.AfterTest(t)()

	// Set up a filter to so that the first CPut operation will
	// get a ReadWithinUncertaintyIntervalError.
	targetKey := roachpb.Key("b")
	var numGets int32

	ctx := server.NewTestContext()
	ctx.TestingKnobs.StoreTestingKnobs.TestingCommandFilter =
		func(fArgs storageutils.FilterArgs) *roachpb.Error {
			_, ok := fArgs.Req.(*roachpb.ConditionalPutRequest)
			if ok && fArgs.Req.Header().Key.Equal(targetKey) {
				if atomic.AddInt32(&numGets, 1) == 1 {
					z := roachpb.ZeroTimestamp
					pErr := roachpb.NewReadWithinUncertaintyIntervalError(z, z)
					return roachpb.NewErrorWithTxn(pErr, fArgs.Hdr.Txn)
				}
			}
			return nil
		}
	s := server.StartTestServerWithContext(t, ctx)
	defer s.Stop()
	db := setupMultipleRanges(t, s, "b")

	// Set the initial value on the target key "b".
	origVal := "val"
	if pErr := db.Put(targetKey, origVal); pErr != nil {
		t.Fatal(pErr)
	}

	// The following txn creates a batch request that is split
	// into two requests: Put and CPut. The CPut operation will
	// get a ReadWithinUncertaintyIntervalError and the txn will be
	// retried.
	epoch := 0
	if pErr := db.Txn(func(txn *client.Txn) *roachpb.Error {
		epoch++
		if epoch >= 2 {
			// Writing must be true since we ran the BeginTransaction command.
			if !txn.Proto.Writing {
				t.Errorf("unexpected non-writing txn")
			}
		} else {
			// Writing must be false since we haven't run any write command.
			if txn.Proto.Writing {
				t.Errorf("unexpected writing txn")
			}
		}

		b := txn.NewBatch()
		b.Put("a", "val")
		b.CPut(targetKey, "new_val", origVal)
		pErr := txn.CommitInBatch(b)
		if epoch == 1 {
			if _, ok := pErr.GetDetail().(*roachpb.ReadWithinUncertaintyIntervalError); ok {
				if !pErr.GetTxn().Writing {
					t.Errorf("unexpected non-writing txn on error")
				}
			} else {
				t.Errorf("expected ReadWithinUncertaintyIntervalError, but got: %s", pErr)
			}
		}
		return pErr
	}); pErr != nil {
		t.Errorf("unexpected error on transactional Puts: %s", pErr)
	}

	if epoch != 2 {
		t.Errorf("unexpected epoch; the txn must be retried exactly once, but got %d", epoch)
	}
}
예제 #24
0
func setup(t *testing.T) (*testServer, *sql.DB, *client.DB) {
	return setupWithContext(t, server.NewTestContext())
}
예제 #25
0
// TODO(tschottdorf): some logic tests currently take a long time to run.
// Probably a case of heartbeats timing out or many restarts in some tests.
// Need to investigate when all moving parts are in place.
func (t *logicTest) run(path string) {
	defer t.close()

	file, err := os.Open(path)
	if err != nil {
		t.Fatal(err)
	}
	defer file.Close()

	t.lastProgress = time.Now()

	// TODO(pmattis): Add a flag to make it easy to run the tests against a local
	// MySQL or Postgres instance.
	ctx := server.NewTestContext()
	ctx.MaxOffset = logicMaxOffset
	t.srv = setupTestServer(t.T)

	// db may change over the lifetime of this function, with intermediate
	// values cached in t.clients and finally closed in t.close().
	cleanupFunc := t.setUser(security.RootUser)
	defer cleanupFunc()

	if _, err := t.db.Exec(`
CREATE DATABASE test;
SET DATABASE = test;
`); err != nil {
		t.Fatal(err)
	}

	s := newLineScanner(file)
	for s.Scan() {
		fields := strings.Fields(s.Text())
		if len(fields) == 0 {
			continue
		}
		cmd := fields[0]
		if strings.HasPrefix(cmd, "#") {
			// Skip comment lines.
			continue
		}
		switch cmd {
		case "statement":
			stmt := logicStatement{pos: fmt.Sprintf("%s:%d", path, s.line)}
			// Parse "query error <regexp>"
			if m := errorRE.FindStringSubmatch(s.Text()); m != nil {
				stmt.expectErr = m[1]
			}
			var buf bytes.Buffer
			for s.Scan() {
				line := s.Text()
				if line == "" {
					break
				}
				fmt.Fprintln(&buf, line)
			}
			stmt.sql = strings.TrimSpace(buf.String())
			if !s.skip {
				t.execStatement(stmt)
			} else {
				s.skip = false
			}
			t.success(path)

		case "query":
			query := logicQuery{pos: fmt.Sprintf("%s:%d", path, s.line)}
			// Parse "query error <regexp>"
			if m := errorRE.FindStringSubmatch(s.Text()); m != nil {
				query.expectErr = m[1]
			} else if len(fields) < 2 {
				t.Fatalf("%s: invalid test statement: %s", query.pos, s.Text())
			} else {
				// Parse "query <type-string> <sort-mode> <label>"
				// The type string specifies the number of columns and their types:
				//   - T for text
				//   - I for integer
				//   - R for floating point
				//   - B for boolean
				// The sort mode is one of:
				//   - "nosort" (default)
				//   - "rowsort"
				//   - "valuesort"
				//   - "colnames"
				//
				// The label is optional. If specified, the test runner stores a hash
				// of the results of the query under the given label. If the label is
				// reused, the test runner verifies that the results are the
				// same. This can be used to verify that two or more queries in the
				// same test script that are logically equivalent always generate the
				// same output.
				query.colTypes = fields[1]
				if len(fields) >= 3 {
					for _, opt := range strings.Split(fields[2], ",") {
						switch opt {
						case "nosort":
							query.sorter = nil

						case "rowsort":
							query.sorter = rowSort

						case "valuesort":
							query.sorter = valueSort

						case "colnames":
							query.colNames = true

						default:
							t.Fatalf("%s: unknown sort mode: %s", query.pos, opt)
						}
					}
				}
				if len(fields) >= 4 {
					query.label = fields[3]
				}
			}

			var buf bytes.Buffer
			for s.Scan() {
				line := s.Text()
				if line == "----" {
					if query.expectErr != "" {
						t.Fatalf("%s: invalid ---- delimiter after a query expecting an error: %s", query.pos, query.expectErr)
					}
					break
				}
				if strings.TrimSpace(s.Text()) == "" {
					break
				}
				fmt.Fprintln(&buf, line)
			}
			query.sql = strings.TrimSpace(buf.String())

			if query.expectErr == "" {
				// Query results are either a space separated list of values up to a
				// blank line or a line of the form "xx values hashing to yyy". The
				// latter format is used by sqllogictest when a large number of results
				// match the query.
				if s.Scan() {
					if m := resultsRE.FindStringSubmatch(s.Text()); m != nil {
						var err error
						query.expectedValues, err = strconv.Atoi(m[1])
						if err != nil {
							t.Fatal(err)
						}
						query.expectedHash = m[2]
					} else {
						for {
							results := strings.Fields(s.Text())
							if len(results) == 0 {
								break
							}
							query.expectedResults = append(query.expectedResults, results...)
							if !s.Scan() {
								break
							}
						}
						query.expectedValues = len(query.expectedResults)
					}
				}
			}

			if !s.skip {
				t.execQuery(query)
			} else {
				s.skip = false
			}
			t.success(path)

		case "halt", "hash-threshold":
			break

		case "user":
			if len(fields) < 2 {
				t.Fatalf("user command requires one argument, found: %v", fields)
			}
			if len(fields[1]) == 0 {
				t.Fatal("user command requires a non-blank argument")
			}
			cleanupUserFunc := t.setUser(fields[1])
			defer cleanupUserFunc()

		case "skipif":
			if len(fields) < 2 {
				t.Fatalf("skipif command requires one argument, found: %v", fields)
			}
			switch fields[1] {
			case "":
				t.Fatal("skipif command requires a non-blank argument")
			case "mysql":
			case "postgresql":
				s.skip = true
				continue
			default:
				t.Fatalf("unimplemented test statement: %s", s.Text())
			}

		case "onlyif":
			if len(fields) < 2 {
				t.Fatalf("onlyif command requires one argument, found: %v", fields)
			}
			switch fields[1] {
			case "":
				t.Fatal("onlyif command requires a non-blank argument")
			case "mysql":
				s.skip = true
				continue
			default:
				t.Fatalf("unimplemented test statement: %s", s.Text())
			}

		case "traceon":
			if len(fields) != 2 {
				t.Fatalf("traceon requires a filename argument, found: %v", fields)
			}
			t.traceStart(fields[1])

		case "traceoff":
			if t.traceFile == nil {
				t.Fatalf("no trace active")
			}
			t.traceStop()

		default:
			t.Fatalf("%s:%d: unknown command: %s", path, s.line, cmd)
		}
	}

	if err := s.Err(); err != nil {
		t.Fatal(err)
	}

	t.traceStop()

	fmt.Printf("%s: %d\n", path, t.progress)
}
예제 #26
0
// getFastScanContext returns a test context with fast scan.
func getFastScanContext() *server.Context {
	c := server.NewTestContext()
	c.ScanInterval = time.Millisecond
	c.ScanMaxIdleTime = time.Millisecond
	return c
}
예제 #27
0
func TestLeaseManager(testingT *testing.T) {
	defer leaktest.AfterTest(testingT)()
	t := newLeaseTest(testingT, server.NewTestContext())
	defer t.cleanup()

	const descID = keys.LeaseTableID

	// We can't acquire a lease on a non-existent table.
	expected := "descriptor ID 10000 not found"
	if _, err := t.acquire(1, 10000, 0); !testutils.IsError(err, expected) {
		t.Fatalf("expected %s, but found %v", expected, err)
	}

	l1 := t.mustAcquire(1, descID, 0)
	t.expectLeases(descID, "/1/1")
	// Node 2 never acquired a lease on descID, so we should expect an error.
	if err := t.release(2, l1); err == nil {
		t.Fatalf("expected error, but found none")
	}
	t.mustRelease(1, l1)
	t.expectLeases(descID, "/1/1")

	// It is an error to acquire a lease for a specific version that doesn't
	// exist yet.
	expected = "version 2 of table .* does not exist"
	if _, err := t.acquire(1, descID, 2); !testutils.IsError(err, expected) {
		t.Fatalf("expected %s, but found %v", expected, err)
	}

	// Publish a new version and explicitly acquire it.
	l2 := t.mustAcquire(1, descID, 0)
	t.mustPublish(1, descID)
	l3 := t.mustAcquire(1, descID, 2)
	t.expectLeases(descID, "/1/1 /2/1")

	// When the last local reference on the new version is released we don't
	// release the node lease.
	t.mustRelease(1, l3)
	t.expectLeases(descID, "/1/1 /2/1")

	// We can still acquire a local reference on the old version since it hasn't
	// expired.
	l4 := t.mustAcquire(1, descID, 1)
	t.mustRelease(1, l4)
	t.expectLeases(descID, "/1/1 /2/1")

	// When the last local reference on the old version is released the node
	// lease is also released.
	t.mustRelease(1, l2)
	t.expectLeases(descID, "/2/1")

	// It is an error to acquire a lease for an old version once a new version
	// exists and there are no local references for the old version.
	expected = "lease.go.*: table .* unable to acquire lease on old version: 1 < 2"
	if _, err := t.acquire(1, descID, 1); !testutils.IsError(err, expected) {
		t.Fatalf("expected %s, but found %v", expected, err)
	}

	// Acquire 2 node leases on version 2.
	l5 := t.mustAcquire(1, descID, 2)
	l6 := t.mustAcquire(2, descID, 2)
	// Publish version 3. This will succeed immediately.
	t.mustPublish(3, descID)

	// Start a goroutine to publish version 4 which will block until the version
	// 2 leases are released.
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		t.mustPublish(3, descID)
		wg.Done()
	}()

	// Force both nodes ahead to version 3.
	l7 := t.mustAcquire(1, descID, 3)
	l8 := t.mustAcquire(2, descID, 3)
	t.expectLeases(descID, "/2/1 /2/2 /3/1 /3/2")

	t.mustRelease(1, l5)
	t.expectLeases(descID, "/2/2 /3/1 /3/2")
	t.mustRelease(2, l6)
	t.expectLeases(descID, "/3/1 /3/2")

	// Wait for version 4 to be published.
	wg.Wait()
	l9 := t.mustAcquire(1, descID, 4)
	t.mustRelease(1, l7)
	t.mustRelease(2, l8)
	t.expectLeases(descID, "/3/2 /4/1")
	t.mustRelease(1, l9)
	t.expectLeases(descID, "/3/2 /4/1")
}