github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/flowinfra/server_test.go (about) 1 // Copyright 2016 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package flowinfra 12 13 import ( 14 "context" 15 "fmt" 16 "io" 17 "testing" 18 19 "github.com/cockroachdb/cockroach/pkg/base" 20 "github.com/cockroachdb/cockroach/pkg/gossip" 21 "github.com/cockroachdb/cockroach/pkg/keys" 22 "github.com/cockroachdb/cockroach/pkg/kv" 23 "github.com/cockroachdb/cockroach/pkg/rpc" 24 "github.com/cockroachdb/cockroach/pkg/sql/execinfra" 25 "github.com/cockroachdb/cockroach/pkg/sql/execinfrapb" 26 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 27 "github.com/cockroachdb/cockroach/pkg/testutils" 28 "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" 29 "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" 30 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 31 ) 32 33 func TestServer(t *testing.T) { 34 defer leaktest.AfterTest(t)() 35 36 ctx := context.Background() 37 s, sqlDB, kvDB := serverutils.StartServer(t, base.TestServerArgs{}) 38 defer s.Stopper().Stop(ctx) 39 conn, err := s.RPCContext().GRPCDialNode(s.ServingRPCAddr(), s.NodeID(), 40 rpc.DefaultClass).Connect(ctx) 41 if err != nil { 42 t.Fatal(err) 43 } 44 45 r := sqlutils.MakeSQLRunner(sqlDB) 46 47 r.Exec(t, `CREATE DATABASE test`) 48 r.Exec(t, `CREATE TABLE test.t (a INT PRIMARY KEY, b INT)`) 49 r.Exec(t, `INSERT INTO test.t VALUES (1, 10), (2, 20), (3, 30)`) 50 51 td := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "test", "t") 52 53 ts := execinfrapb.TableReaderSpec{ 54 Table: *td, 55 IndexIdx: 0, 56 Reverse: false, 57 Spans: []execinfrapb.TableReaderSpan{{Span: td.PrimaryIndexSpan(keys.SystemSQLCodec)}}, 58 } 59 post := execinfrapb.PostProcessSpec{ 60 Filter: execinfrapb.Expression{Expr: "@1 != 2"}, // a != 2 61 Projection: true, 62 OutputColumns: []uint32{0, 1}, // a 63 } 64 65 txn := kv.NewTxn(ctx, kvDB, s.NodeID()) 66 leafInputState := txn.GetLeafTxnInputState(ctx) 67 68 req := &execinfrapb.SetupFlowRequest{ 69 Version: execinfra.Version, 70 LeafTxnInputState: &leafInputState, 71 } 72 req.Flow = execinfrapb.FlowSpec{ 73 Processors: []execinfrapb.ProcessorSpec{{ 74 Core: execinfrapb.ProcessorCoreUnion{TableReader: &ts}, 75 Post: post, 76 Output: []execinfrapb.OutputRouterSpec{{ 77 Type: execinfrapb.OutputRouterSpec_PASS_THROUGH, 78 Streams: []execinfrapb.StreamEndpointSpec{{Type: execinfrapb.StreamEndpointSpec_SYNC_RESPONSE}}, 79 }}, 80 }}, 81 } 82 83 distSQLClient := execinfrapb.NewDistSQLClient(conn) 84 stream, err := distSQLClient.RunSyncFlow(ctx) 85 if err != nil { 86 t.Fatal(err) 87 } 88 if err := stream.Send(&execinfrapb.ConsumerSignal{SetupFlowRequest: req}); err != nil { 89 t.Fatal(err) 90 } 91 92 var decoder StreamDecoder 93 var rows sqlbase.EncDatumRows 94 var metas []execinfrapb.ProducerMetadata 95 for { 96 msg, err := stream.Recv() 97 if err != nil { 98 if err == io.EOF { 99 break 100 } 101 t.Fatal(err) 102 } 103 err = decoder.AddMessage(context.Background(), msg) 104 if err != nil { 105 t.Fatal(err) 106 } 107 rows, metas = testGetDecodedRows(t, &decoder, rows, metas) 108 } 109 metas = ignoreLeafTxnState(metas) 110 metas = ignoreMetricsMeta(metas) 111 if len(metas) != 0 { 112 t.Errorf("unexpected metadata: %v", metas) 113 } 114 str := rows.String(sqlbase.TwoIntCols) 115 expected := "[[1 10] [3 30]]" 116 if str != expected { 117 t.Errorf("invalid results: %s, expected %s'", str, expected) 118 } 119 120 // Verify version handling. 121 t.Run("version", func(t *testing.T) { 122 testCases := []struct { 123 version execinfrapb.DistSQLVersion 124 expectedErr string 125 }{ 126 { 127 version: execinfra.Version + 1, 128 expectedErr: "version mismatch", 129 }, 130 { 131 version: execinfra.MinAcceptedVersion - 1, 132 expectedErr: "version mismatch", 133 }, 134 { 135 version: execinfra.MinAcceptedVersion, 136 expectedErr: "", 137 }, 138 } 139 for _, tc := range testCases { 140 t.Run(fmt.Sprintf("%d", tc.version), func(t *testing.T) { 141 distSQLClient := execinfrapb.NewDistSQLClient(conn) 142 stream, err := distSQLClient.RunSyncFlow(context.Background()) 143 if err != nil { 144 t.Fatal(err) 145 } 146 req.Version = tc.version 147 if err := stream.Send(&execinfrapb.ConsumerSignal{SetupFlowRequest: req}); err != nil { 148 t.Fatal(err) 149 } 150 _, err = stream.Recv() 151 if !testutils.IsError(err, tc.expectedErr) { 152 t.Errorf("expected error '%s', got %v", tc.expectedErr, err) 153 } 154 // In the expectedErr == nil case, we leave a flow hanging; we're not 155 // consuming it. It will get canceled by the draining process. 156 }) 157 } 158 }) 159 } 160 161 // Test that a node gossips its DistSQL version information. 162 func TestDistSQLServerGossipsVersion(t *testing.T) { 163 defer leaktest.AfterTest(t)() 164 165 s, _, _ := serverutils.StartServer(t, base.TestServerArgs{}) 166 defer s.Stopper().Stop(context.Background()) 167 168 var v execinfrapb.DistSQLVersionGossipInfo 169 if err := s.GossipI().(*gossip.Gossip).GetInfoProto( 170 gossip.MakeDistSQLNodeVersionKey(s.NodeID()), &v, 171 ); err != nil { 172 t.Fatal(err) 173 } 174 175 if v.Version != execinfra.Version || v.MinAcceptedVersion != execinfra.MinAcceptedVersion { 176 t.Fatalf("node is gossipping the wrong version. Expected: [%d-%d], got [%d-%d", 177 execinfra.Version, execinfra.MinAcceptedVersion, v.Version, v.MinAcceptedVersion) 178 } 179 }