<commit_before>// Copyright 2015, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package vitessdriver

import (
	"database/sql"
	"database/sql/driver"
	"fmt"
	"io"
	"net"
	"os"
	"reflect"
	"strings"
	"testing"
	"time"

	"google.golang.org/grpc"

	"github.com/youtube/vitess/go/vt/vtgate/grpcvtgateservice"

	topodatapb "github.com/youtube/vitess/go/vt/proto/topodata"
)

var (
	testAddress string
)

func TestMain(m *testing.M) {
	// fake service
	service := CreateFakeServer()

	// listen on a random port
	listener, err := net.Listen("tcp", ":0")
	if err != nil {
		panic(fmt.Sprintf("Cannot listen: %v", err))
	}

	// Create a gRPC server and listen on the port
	server := grpc.NewServer()
	grpcvtgateservice.RegisterForTest(server, service)
	go server.Serve(listener)

	testAddress = listener.Addr().String()
	os.Exit(m.Run())
}

func TestDriver(t *testing.T) {
	connStr := fmt.Sprintf(`{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "timeout": %d}`, testAddress, int64(30*time.Second))
	db, err := sql.Open("vitess", connStr)
	if err != nil {
		t.Fatal(err)
	}
	r, err := db.Query("request1", int64(0))
	if err != nil {
		t.Fatal(err)
	}
	count := 0
	for r.Next() {
		count++
	}
	if count != 2 {
		t.Errorf("count: %d, want 2", count)
	}
	_ = db.Close()
}

func TestDial(t *testing.T) {
	connStr := fmt.Sprintf(`{"protocol": "grpc", "address": "%s", "tablet_type": "replica", "timeout": %d}`, testAddress, int64(30*time.Second))
	c, err := drv{}.Open(connStr)
	if err != nil {
		t.Fatal(err)
	}
	wantc := &conn{
		Protocol:   "grpc",
		TabletType: "replica",
		Streaming:  false,
		Timeout:    30 * time.Second,
		tabletType: topodatapb.TabletType_REPLICA,
	}
	newc := *(c.(*conn))
	newc.Address = ""
	newc.vtgateConn = nil
	if !reflect.DeepEqual(&newc, wantc) {
		t.Errorf("conn: %+v, want %+v", &newc, wantc)
	}
	_ = c.Close()

	_, err = drv{}.Open(`{"protocol": "none"}`)
	want := "no dialer registered for VTGate protocol none"
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, want %s", err, want)
	}

	_, err = drv{}.Open(`{`)
	want = "unexpected end of JSON input"
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, want %s", err, want)
	}
}

func TestExec(t *testing.T) {
	var testcases = []struct {
		dataSourceName string
		requestName    string
	}{
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1",
		},
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "keyspace": "ks1", "shard": "0", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1SpecificShard",
		},
	}

	for _, tc := range testcases {
		connStr := fmt.Sprintf(tc.dataSourceName, testAddress, int64(30*time.Second))
		c, err := drv{}.Open(connStr)<commit_msg>vitessdriver: Refactored tests for Open().<commit_after>// Copyright 2015, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package vitessdriver

import (
	"database/sql"
	"database/sql/driver"
	"fmt"
	"io"
	"net"
	"os"
	"reflect"
	"strings"
	"testing"
	"time"

	"google.golang.org/grpc"

	"github.com/youtube/vitess/go/vt/vtgate/grpcvtgateservice"

	topodatapb "github.com/youtube/vitess/go/vt/proto/topodata"
)

var (
	testAddress string
)

// TestMain tests the Vitess Go SQL driver.
//
// Note that the queries used in the test are not valid SQL queries and don't
// have to be. The main point here is to test the interactions against a
// vtgate implementation (here: fakeVTGateService from fakeserver_test.go).
func TestMain(m *testing.M) {
	service := CreateFakeServer()

	// listen on a random port.
	listener, err := net.Listen("tcp", ":0")
	if err != nil {
		panic(fmt.Sprintf("Cannot listen: %v", err))
	}

	// Create a gRPC server and listen on the port.
	server := grpc.NewServer()
	grpcvtgateservice.RegisterForTest(server, service)
	go server.Serve(listener)

	testAddress = listener.Addr().String()
	os.Exit(m.Run())
}

func TestDriver(t *testing.T) {
	connStr := fmt.Sprintf(`{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "timeout": %d}`, testAddress, int64(30*time.Second))
	db, err := sql.Open("vitess", connStr)
	if err != nil {
		t.Fatal(err)
	}
	r, err := db.Query("request1", int64(0))
	if err != nil {
		t.Fatal(err)
	}
	count := 0
	for r.Next() {
		count++
	}
	if count != 2 {
		t.Errorf("count: %d, want 2", count)
	}
	_ = db.Close()
}

func TestOpen(t *testing.T) {
	connStr := fmt.Sprintf(`{"address": "%s", "tablet_type": "replica", "timeout": %d}`, testAddress, int64(30*time.Second))
	c, err := drv{}.Open(connStr)
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	wantc := &conn{
		Configuration: Configuration{
			Protocol:   "grpc",
			TabletType: "replica",
			Streaming:  false,
			Timeout:    30 * time.Second,
		},
		tabletTypeProto: topodatapb.TabletType_REPLICA,
	}
	newc := *(c.(*conn))
	newc.Address = ""
	newc.vtgateConn = nil
	if !reflect.DeepEqual(&newc, wantc) {
		t.Errorf("conn: %+v, want %+v", &newc, wantc)
	}
}

func TestOpenShard(t *testing.T) {
	connStr := fmt.Sprintf(`{"address": "%s", "keyspace": "ks1", "shard": "0", "tablet_type": "replica", "timeout": %d}`, testAddress, int64(30*time.Second))
	c, err := drv{}.Open(connStr)
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	wantc := &conn{
		Configuration: Configuration{
			Protocol:   "grpc",
			Keyspace:   "ks1",
			Shard:      "0",
			TabletType: "replica",
			Streaming:  false,
			Timeout:    30 * time.Second,
		},
		tabletTypeProto: topodatapb.TabletType_REPLICA,
	}
	newc := *(c.(*conn))
	newc.Address = ""
	newc.vtgateConn = nil
	if !reflect.DeepEqual(&newc, wantc) {
		t.Errorf("conn: %+v, want %+v", &newc, wantc)
	}
}

func TestOpen_UnregisteredProtocol(t *testing.T) {
	_, err := drv{}.Open(`{"protocol": "none"}`)
	want := "no dialer registered for VTGate protocol none"
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, want %s", err, want)
	}
}

func TestOpen_InvalidJson(t *testing.T) {
	_, err := drv{}.Open(`{`)
	want := "unexpected end of JSON input"
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, want %s", err, want)
	}
}

func TestOpen_KeyspaceAndShardBelongTogether(t *testing.T) {
	_, err := drv{}.Open(`{"keyspace": "ks1"}`)
	want := "Always set both keyspace and shard or leave both empty."
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, want %s", err, want)
	}

	_, err = drv{}.Open(`{"shard": "0"}`)
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, want %s", err, want)
	}
}

func TestOpen_ValidTabletTypeRequired(t *testing.T) {
	_, err := drv{}.Open(`{"tablet_type": "foobar"}`)
	want := "unknown TabletType foobar"
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, want %s", err, want)
	}
}

func TestExec(t *testing.T) {
	var testcases = []struct {
		dataSourceName string
		requestName    string
	}{
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1",
		},
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "keyspace": "ks1", "shard": "0", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1SpecificShard",
		},
	}

	for _, tc := range testcases {
		connStr := fmt.Sprintf(tc.dataSourceName, testAddress, int64(30*time.Second))
		c, err := drv{}.Open(connStr)
{'fraction_non_alphanumeric': 0.18954162276080083, 'fraction_numerical': 0.009483667017913594, 'mean_word_length': 4.011881188118812, 'pattern_counts': {'":': 47, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '951877', 'n_tokens_mistral': 3083, 'n_tokens_neox': 2936, 'n_words': 709}