@@ -108,8 +108,9 @@ var (
108108 databaseAdmin * database.DatabaseAdminClient
109109 instanceAdmin * instance.InstanceAdminClient
110110
111- dpConfig directPathTestConfig
112- peerInfo * peer.Peer
111+ dpConfig directPathTestConfig
112+ exphConfig experimentalHostTestConfig
113+ peerInfo * peer.Peer
113114
114115 singerDBPGStatements = []string {
115116 `CREATE TABLE Singers (
@@ -403,13 +404,20 @@ func init() {
403404 flag .StringVar (& blackholeDpv4Cmd , "it.blackhole-dpv4-cmd" , "" , "Command to make LB and backend addresses blackholed over dpv4" )
404405 flag .StringVar (& allowDpv6Cmd , "it.allow-dpv6-cmd" , "" , "Command to make LB and backend addresses allowed over dpv6" )
405406 flag .StringVar (& allowDpv4Cmd , "it.allow-dpv4-cmd" , "" , "Command to make LB and backend addresses allowed over dpv4" )
407+ flag .StringVar (& exphConfig .experimentalHost , "it.experimental-host" , "" , "Experimental host integration test flag" )
408+ flag .BoolVar (& exphConfig .isPGDialect , "it.experimental-host-pg-dialect" , false , "Use PG dialect with experimental host" )
406409}
407410
408411type directPathTestConfig struct {
409412 attemptDirectPath bool
410413 directPathIPv4Only bool
411414}
412415
416+ type experimentalHostTestConfig struct {
417+ experimentalHost string
418+ isPGDialect bool
419+ }
420+
413421func parseInstanceName (inst string ) (project , instance string , err error ) {
414422 matches := validInstancePattern .FindStringSubmatch (inst )
415423 if len (matches ) == 0 {
@@ -427,6 +435,10 @@ func getInstanceConfig() string {
427435 return os .Getenv ("GCLOUD_TESTS_GOLANG_SPANNER_INSTANCE_CONFIG" )
428436}
429437
438+ func getMultiplexEnableFlag () bool {
439+ return exphConfig .experimentalHost != "" || os .Getenv ("GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS" ) != "false"
440+ }
441+
430442const (
431443 str1 = "alice"
432444 str2 = "a@example.com"
@@ -441,6 +453,16 @@ func TestMain(m *testing.M) {
441453 // PG tests are not supported in emulator
442454 continue
443455 }
456+ if exphConfig .experimentalHost != "" {
457+ // Since IT against experimental host is ran against single server instance, we need to run tests
458+ // separately for each dialect to avoid context deadlines due to resource limitations.
459+ if exphConfig .isPGDialect && dialect != adminpb .DatabaseDialect_POSTGRESQL {
460+ continue
461+ }
462+ if ! exphConfig .isPGDialect && dialect != adminpb .DatabaseDialect_GOOGLE_STANDARD_SQL {
463+ continue
464+ }
465+ }
444466 testDialect = dialect
445467 res := m .Run ()
446468 if res != 0 {
@@ -462,6 +484,11 @@ func initIntegrationTests() (cleanup func()) {
462484 return noop
463485 }
464486
487+ if exphConfig .experimentalHost != "" {
488+ testProjectID = "default"
489+ testInstanceID = "default"
490+ }
491+
465492 if testProjectID == "" {
466493 log .Println ("Integration tests skipped: GCLOUD_TESTS_GOLANG_PROJECT_ID is missing" )
467494 return noop
@@ -475,15 +502,26 @@ func initIntegrationTests() (cleanup func()) {
475502 opts = append (opts , option .WithGRPCDialOption (grpc .WithDefaultCallOptions (grpc .Peer (peerInfo ))))
476503 }
477504 var err error
478- // Create InstanceAdmin and DatabaseAdmin clients.
479- instanceAdmin , err = instance .NewInstanceAdminClient (ctx , opts ... )
480- if err != nil {
481- log .Fatalf ("cannot create instance databaseAdmin client: %v" , err )
505+
506+ if exphConfig .experimentalHost != "" {
507+ opts = append (opts , experimentalHostOptions ()... )
508+ databaseAdmin , err = database .NewDatabaseAdminClient (ctx , opts ... )
509+ } else {
510+ // Create InstanceAdmin and DatabaseAdmin clients.
511+ instanceAdmin , err = instance .NewInstanceAdminClient (ctx , opts ... )
512+ if err != nil {
513+ log .Fatalf ("cannot create instance databaseAdmin client: %v" , err )
514+ }
515+ databaseAdmin , err = database .NewDatabaseAdminClient (ctx , opts ... )
482516 }
483- databaseAdmin , err = database .NewDatabaseAdminClient (ctx , opts ... )
484517 if err != nil {
485518 log .Fatalf ("cannot create databaseAdmin client: %v" , err )
486519 }
520+ if exphConfig .experimentalHost != "" {
521+ return func () {
522+ databaseAdmin .Close ()
523+ }
524+ }
487525 var configName string
488526 if instanceConfig != "" {
489527 configName = fmt .Sprintf ("projects/%s/instanceConfigs/%s" , testProjectID , instanceConfig )
@@ -1083,6 +1121,8 @@ func deleteTestSession(ctx context.Context, t *testing.T, sessionName string) {
10831121
10841122func TestIntegration_BatchWrite (t * testing.T ) {
10851123 skipEmulatorTest (t )
1124+ // BatchWrite creates regular sessions, which cannot be used with experimental host.
1125+ skipExperimentalHostTest (t )
10861126 t .Parallel ()
10871127
10881128 ctx , cancel := context .WithTimeout (context .Background (), 5 * time .Minute )
@@ -2027,6 +2067,7 @@ func TestIntegration_NestedTransaction(t *testing.T) {
20272067func TestIntegration_CreateDBRetry (t * testing.T ) {
20282068 t .Parallel ()
20292069 skipUnsupportedPGTest (t )
2070+ skipExperimentalHostTest (t )
20302071
20312072 if databaseAdmin == nil {
20322073 t .Skip ("Integration tests skipped" )
@@ -2074,6 +2115,8 @@ func TestIntegration_CreateDBRetry(t *testing.T) {
20742115// Test client recovery on database recreation.
20752116func TestIntegration_DbRemovalRecovery (t * testing.T ) {
20762117 t .Parallel ()
2118+ // tracking the failure via b/441255724 for experimentalHost
2119+ skipExperimentalHostTest (t )
20772120
20782121 ctx , cancel := context .WithTimeout (context .Background (), 5 * time .Minute )
20792122 defer cancel ()
@@ -3330,6 +3373,7 @@ func TestIntegration_TransactionRunner(t *testing.T) {
33303373 // TODO(sakthivelmani): Enable the tests once b/422916293 is fixed
33313374 skipDirectPathTest (t )
33323375 skipEmulatorTest (t )
3376+ skipExperimentalHostTest (t )
33333377 t .Parallel ()
33343378
33353379 ctx , cancel := context .WithTimeout (context .Background (), 5 * time .Minute )
@@ -3469,8 +3513,9 @@ func TestIntegration_TransactionRunner(t *testing.T) {
34693513
34703514func TestIntegration_QueryWithRoles (t * testing.T ) {
34713515 t .Parallel ()
3472- // Database roles are not currently available in emulator
3516+ // Database roles are not currently available in emulator and experimentalHost
34733517 skipEmulatorTest (t )
3518+ skipExperimentalHostTest (t )
34743519
34753520 // Set up testing environment.
34763521 var (
@@ -3603,8 +3648,9 @@ func TestIntegration_QueryWithRoles(t *testing.T) {
36033648
36043649func TestIntegration_ReadWithRoles (t * testing.T ) {
36053650 t .Parallel ()
3606- // Database roles are not currently available in emulator
3651+ // Database roles are not currently available in emulator and experimentalHost
36073652 skipEmulatorTest (t )
3653+ skipExperimentalHostTest (t )
36083654
36093655 // Set up testing environment.
36103656 var (
@@ -3736,8 +3782,9 @@ func TestIntegration_ReadWithRoles(t *testing.T) {
37363782
37373783func TestIntegration_DMLWithRoles (t * testing.T ) {
37383784 t .Parallel ()
3739- // Database roles are not currently available in emulator
3785+ // Database roles are not currently available in emulator and experimentalHost
37403786 skipEmulatorTest (t )
3787+ skipExperimentalHostTest (t )
37413788
37423789 // Set up testing environment.
37433790 var (
@@ -3900,8 +3947,9 @@ func TestIntegration_DMLWithRoles(t *testing.T) {
39003947
39013948func TestIntegration_MutationWithRoles (t * testing.T ) {
39023949 t .Parallel ()
3903- // Database roles are not currently available in emulator
3950+ // Database roles are not currently available in emulator and experimental host
39043951 skipEmulatorTest (t )
3952+ skipExperimentalHostTest (t )
39053953
39063954 // Set up testing environment.
39073955 var (
@@ -4054,8 +4102,9 @@ func TestIntegration_MutationWithRoles(t *testing.T) {
40544102
40554103func TestIntegration_ListDatabaseRoles (t * testing.T ) {
40564104 t .Parallel ()
4057- // Database roles are not currently available in emulator
4105+ // Database roles are not currently available in emulator and experimental host
40584106 skipEmulatorTest (t )
4107+ skipExperimentalHostTest (t )
40594108
40604109 // Set up testing environment.
40614110 var (
@@ -4141,7 +4190,9 @@ func TestIntegration_BatchQuery(t *testing.T) {
41414190 t .Fatal (err )
41424191 }
41434192 defer txn .Cleanup (ctx )
4144- if partitions , err = txn .PartitionQueryWithOptions (ctx , stmt , PartitionOptions {0 , 3 }, QueryOptions {DataBoostEnabled : true }); err != nil {
4193+ // DataBoost is not available for experimental host endpoints
4194+ dataBoostAvailable := exphConfig .experimentalHost == ""
4195+ if partitions , err = txn .PartitionQueryWithOptions (ctx , stmt , PartitionOptions {0 , 3 }, QueryOptions {DataBoostEnabled : dataBoostAvailable }); err != nil {
41454196 t .Fatal (err )
41464197 }
41474198
@@ -4227,7 +4278,9 @@ func TestIntegration_BatchRead(t *testing.T) {
42274278 t .Fatal (err )
42284279 }
42294280 defer txn .Cleanup (ctx )
4230- if partitions , err = txn .PartitionReadWithOptions (ctx , "test" , AllKeys (), simpleDBTableColumns , PartitionOptions {0 , 3 }, ReadOptions {DataBoostEnabled : true }); err != nil {
4281+ // DataBoost is not available for experimental host endpoints
4282+ dataBoostAvailable := exphConfig .experimentalHost == ""
4283+ if partitions , err = txn .PartitionReadWithOptions (ctx , "test" , AllKeys (), simpleDBTableColumns , PartitionOptions {0 , 3 }, ReadOptions {DataBoostEnabled : dataBoostAvailable }); err != nil {
42314284 t .Fatal (err )
42324285 }
42334286
@@ -5343,6 +5396,7 @@ func compareErrors(got, want error) bool {
53435396
53445397func TestIntegration_Foreign_Key_Delete_Cascade_Action (t * testing.T ) {
53455398 skipEmulatorTest (t )
5399+ skipExperimentalHostTest (t )
53465400 t .Parallel ()
53475401 ctx , cancel := context .WithTimeout (context .Background (), 5 * time .Minute )
53485402 defer cancel ()
@@ -5629,6 +5683,7 @@ func TestIntegration_GFE_Latency(t *testing.T) {
56295683
56305684func TestIntegration_Bit_Reversed_Sequence (t * testing.T ) {
56315685 skipEmulatorTest (t )
5686+ skipExperimentalHostTest (t )
56325687 t .Parallel ()
56335688 ctx , cancel := context .WithTimeout (context .Background (), 5 * time .Minute )
56345689 defer cancel ()
@@ -6302,6 +6357,10 @@ func createClient(ctx context.Context, dbPath string, config ClientConfig) (clie
63026357 if dpConfig .attemptDirectPath {
63036358 opts = append (opts , option .WithGRPCDialOption (grpc .WithDefaultCallOptions (grpc .Peer (peerInfo ))))
63046359 }
6360+ if exphConfig .experimentalHost != "" {
6361+ opts = append (opts , experimentalHostOptions ()... )
6362+ config .IsExperimentalHost = true
6363+ }
63056364 client , err = makeClientWithConfig (ctx , dbPath , config , serverAddress , opts ... )
63066365 if err != nil {
63076366 return nil , fmt .Errorf ("cannot create data client on DB %v: %v" , dbPath , err )
@@ -6320,6 +6379,10 @@ func createClientWithRole(ctx context.Context, dbPath string, spc SessionPoolCon
63206379 opts = append (opts , option .WithGRPCDialOption (grpc .WithDefaultCallOptions (grpc .Peer (peerInfo ))))
63216380 }
63226381 config := ClientConfig {SessionPoolConfig : spc , DatabaseRole : role }
6382+ if exphConfig .experimentalHost != "" {
6383+ opts = append (opts , experimentalHostOptions ()... )
6384+ config .IsExperimentalHost = true
6385+ }
63236386 client , err = makeClientWithConfig (ctx , dbPath , config , serverAddress , opts ... )
63246387 if err != nil {
63256388 return nil , fmt .Errorf ("cannot create data client on DB %v: %v" , dbPath , err )
@@ -6336,7 +6399,12 @@ func createClientForProtoColumns(ctx context.Context, dbPath string, spc Session
63366399 if dpConfig .attemptDirectPath {
63376400 opts = append (opts , option .WithGRPCDialOption (grpc .WithDefaultCallOptions (grpc .Peer (peerInfo ))))
63386401 }
6339- client , err = NewClientWithConfig (ctx , dbPath , ClientConfig {SessionPoolConfig : spc }, opts ... )
6402+ config := ClientConfig {SessionPoolConfig : spc }
6403+ if exphConfig .experimentalHost != "" {
6404+ opts = append (opts , experimentalHostOptions ()... )
6405+ config .IsExperimentalHost = true
6406+ }
6407+ client , err = NewClientWithConfig (ctx , dbPath , config , opts ... )
63406408 if err != nil {
63416409 return nil , fmt .Errorf ("cannot create data client on DB %v: %v" , dbPath , err )
63426410 }
@@ -6486,6 +6554,20 @@ func skipEmulatorTest(t *testing.T) {
64866554 }
64876555}
64886556
6557+ func skipExperimentalHostTest (t * testing.T ) {
6558+ if exphConfig .experimentalHost != "" {
6559+ t .Skip ("Skipping experimental host tests." )
6560+ }
6561+ }
6562+
6563+ func experimentalHostOptions () []option.ClientOption {
6564+ return []option.ClientOption {
6565+ option .WithEndpoint (exphConfig .experimentalHost ),
6566+ option .WithoutAuthentication (),
6567+ option .WithGRPCDialOption (grpc .WithTransportCredentials (insecure .NewCredentials ())),
6568+ }
6569+ }
6570+
64896571func skipDirectPathTest (t * testing.T ) {
64906572 if directPathEnabled , found := os .LookupEnv ("GOOGLE_SPANNER_ENABLE_DIRECT_ACCESS" ); found {
64916573 if enabled , _ := strconv .ParseBool (directPathEnabled ); enabled {
0 commit comments