YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/yql/cql/cqlserver/cqlserver-test.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
14
#include <memory>
15
#include <string>
16
#include <vector>
17
18
#include "yb/gutil/strings/join.h"
19
#include "yb/gutil/strings/substitute.h"
20
21
#include "yb/integration-tests/yb_table_test_base.h"
22
23
#include "yb/tserver/heartbeater.h"
24
#include "yb/tserver/mini_tablet_server.h"
25
#include "yb/tserver/tablet_server.h"
26
27
#include "yb/util/bytes_formatter.h"
28
#include "yb/util/cast.h"
29
#include "yb/util/net/net_util.h"
30
#include "yb/util/net/socket.h"
31
#include "yb/util/result.h"
32
#include "yb/util/status_log.h"
33
#include "yb/util/test_util.h"
34
35
#include "yb/yql/cql/cqlserver/cql_server.h"
36
37
DECLARE_bool(cql_server_always_send_events);
38
DECLARE_bool(use_cassandra_authentication);
39
40
namespace yb {
41
namespace cqlserver {
42
43
using namespace yb::ql; // NOLINT
44
using std::string;
45
using std::unique_ptr;
46
using std::vector;
47
using strings::Substitute;
48
using yb::integration_tests::YBTableTestBase;
49
50
class TestCQLService : public YBTableTestBase {
51
 public:
52
  void SetUp() override;
53
  void TearDown() override;
54
55
  void TestSchemaChangeEvent();
56
57
 protected:
58
  void SendRequestAndExpectTimeout(const string& cmd);
59
60
  void SendRequestAndExpectResponse(const string& cmd, const string& expected_resp);
61
62
0
  int server_port() { return cql_server_port_; }
63
 private:
64
  Status SendRequestAndGetResponse(
65
      const string& cmd, size_t expected_resp_length, int timeout_in_millis = 60000);
66
67
  Socket client_sock_;
68
  unique_ptr<boost::asio::io_service> io_;
69
  unique_ptr<CQLServer> server_;
70
  int cql_server_port_ = 0;
71
  unique_ptr<FileLock> cql_port_lock_;
72
  unique_ptr<FileLock> cql_webserver_lock_;
73
  static constexpr size_t kBufLen = 1024;
74
  size_t resp_bytes_read_ = 0;
75
  uint8_t resp_[kBufLen];
76
};
77
78
0
void TestCQLService::SetUp() {
79
0
  YBTableTestBase::SetUp();
80
81
0
  CQLServerOptions opts;
82
0
  cql_server_port_ = GetFreePort(&cql_port_lock_);
83
0
  opts.rpc_opts.rpc_bind_addresses = strings::Substitute("0.0.0.0:$0", cql_server_port_);
84
  // No need to save the webserver port, as we don't plan on using it. Just use a unique free port.
85
0
  opts.webserver_opts.port = GetFreePort(&cql_webserver_lock_);
86
0
  string fs_root = GetTestPath("CQLServerTest-fsroot");
87
0
  opts.fs_opts.wal_paths = {fs_root};
88
0
  opts.fs_opts.data_paths = {fs_root};
89
90
0
  auto master_rpc_addrs = master_rpc_addresses_as_strings();
91
0
  opts.master_addresses_flag = JoinStrings(master_rpc_addrs, ",");
92
0
  auto master_addresses = std::make_shared<server::MasterAddresses>();
93
0
  for (const auto& hp_str : master_rpc_addrs) {
94
0
    HostPort hp;
95
0
    CHECK_OK(hp.ParseString(hp_str, cql_server_port_));
96
0
    master_addresses->push_back({std::move(hp)});
97
0
  }
98
0
  opts.SetMasterAddresses(master_addresses);
99
100
0
  io_.reset(new boost::asio::io_service());
101
0
  server_.reset(new CQLServer(opts, io_.get(), mini_cluster()->mini_tablet_server(0)->server()));
102
0
  LOG(INFO) << "Starting CQL server...";
103
0
  CHECK_OK(server_->Start());
104
0
  LOG(INFO) << "CQL server successfully started.";
105
106
0
  Endpoint remote(IpAddress(), server_port());
107
0
  CHECK_OK(client_sock_.Init(0));
108
0
  CHECK_OK(client_sock_.SetNoDelay(false));
109
0
  LOG(INFO) << "Connecting to CQL server " << remote;
110
0
  CHECK_OK(client_sock_.Connect(remote));
111
0
}
112
113
0
void TestCQLService::TearDown() {
114
0
  EXPECT_OK(client_sock_.Close());
115
0
  DeleteTable();
116
0
  WARN_NOT_OK(mini_cluster()->mini_tablet_server(0)->server()->heartbeater()->Stop(),
117
0
              "Failed to stop heartbeater");
118
0
  server_->Shutdown();
119
0
  YBTableTestBase::TearDown();
120
0
}
121
122
Status TestCQLService::SendRequestAndGetResponse(
123
0
    const string& cmd, size_t expected_resp_length, int timeout_in_millis) {
124
0
  LOG(INFO) << "Send CQL: {" << FormatBytesAsStr(cmd) << "}";
125
  // Send the request.
126
0
  auto bytes_written = EXPECT_RESULT(client_sock_.Write(to_uchar_ptr(cmd.c_str()), cmd.length()));
127
128
0
  EXPECT_EQ(cmd.length(), bytes_written);
129
130
  // Receive the response.
131
0
  MonoTime deadline = MonoTime::Now();
132
0
  deadline.AddDelta(MonoDelta::FromMilliseconds(timeout_in_millis));
133
0
  resp_bytes_read_ = VERIFY_RESULT(client_sock_.BlockingRecv(
134
0
      resp_, expected_resp_length, deadline));
135
0
  LOG(INFO) << "Received CQL: {" <<
136
0
      FormatBytesAsStr(reinterpret_cast<char*>(resp_), resp_bytes_read_) << "}";
137
138
0
  if (expected_resp_length != resp_bytes_read_) {
139
0
    return STATUS(IOError,
140
0
                  Substitute("Received $1 bytes instead of $2",
141
0
                             resp_bytes_read_,
142
0
                             expected_resp_length));
143
0
  }
144
145
  // Try to read 1 more byte - the read must fail (no more data in the socket).
146
0
  deadline = MonoTime::Now();
147
0
  deadline.AddDelta(MonoDelta::FromMilliseconds(200));
148
0
  auto bytes_read = client_sock_.BlockingRecv(&resp_[expected_resp_length], 1, deadline);
149
0
  EXPECT_FALSE(bytes_read.ok());
150
0
  EXPECT_TRUE(bytes_read.status().IsTimedOut());
151
152
0
  return Status::OK();
153
0
}
154
155
0
void TestCQLService::SendRequestAndExpectTimeout(const string& cmd) {
156
  // Don't expect to receive even 1 byte.
157
0
  ASSERT_TRUE(SendRequestAndGetResponse(cmd, 1).IsTimedOut());
158
0
}
159
160
0
void TestCQLService::SendRequestAndExpectResponse(const string& cmd, const string& expected_resp) {
161
0
  CHECK_OK(SendRequestAndGetResponse(cmd, expected_resp.length()));
162
0
  const string resp(reinterpret_cast<char*>(resp_), resp_bytes_read_);
163
164
0
  if (expected_resp != resp) {
165
0
    LOG(ERROR) << "Expected: {" << FormatBytesAsStr(expected_resp) <<
166
0
        "} Got: {" << FormatBytesAsStr(resp) << "}";
167
0
  }
168
169
  // Verify that the response is as expected.
170
0
  CHECK_EQ(expected_resp, resp);
171
0
}
172
173
// The following test cases test the CQL protocol marshalling/unmarshalling with hand-coded
174
// request messages and expected responses. They are good as basic and error-handling tests.
175
// These are expected to be few.
176
//
177
// TODO(Robert) - add more tests using Cassandra C++ driver when the CQL server can respond
178
// to queries.
179
0
TEST_F(TestCQLService, StartupRequest) {
180
0
  LOG(INFO) << "Test CQL STARTUP request";
181
  // Send STARTUP request using version V3
182
0
  SendRequestAndExpectResponse(
183
0
      BINARY_STRING("\x03\x00\x00\x00\x01" "\x00\x00\x00\x16"
184
0
                    "\x00\x01" "\x00\x0b" "CQL_VERSION"
185
0
                               "\x00\x05" "3.0.0"),
186
0
      BINARY_STRING("\x83\x00\x00\x00\x02" "\x00\x00\x00\x00"));
187
188
  // Send STARTUP request using version V4
189
0
  SendRequestAndExpectResponse(
190
0
      BINARY_STRING("\x04\x00\x00\x00\x01" "\x00\x00\x00\x16"
191
0
                    "\x00\x01" "\x00\x0b" "CQL_VERSION"
192
0
                               "\x00\x05" "3.0.0"),
193
0
      BINARY_STRING("\x84\x00\x00\x00\x02" "\x00\x00\x00\x00"));
194
195
  // Send STARTUP request using version V5
196
0
  SendRequestAndExpectResponse(
197
0
      BINARY_STRING("\x05\x00\x00\x00\x01" "\x00\x00\x00\x16"
198
0
                    "\x00\x01" "\x00\x0b" "CQL_VERSION"
199
0
                               "\x00\x05" "3.0.0"),
200
0
      BINARY_STRING("\x84\x00\x00\x00\x00" "\x00\x00\x00\x58"
201
0
                    "\x00\x00\x00\x0a" "\x00\x52"
202
0
                    "Invalid or unsupported protocol version 5. "
203
0
                    "Supported versions are between 3 and 4."));
204
205
  // Send STARTUP request with compression
206
0
  SendRequestAndExpectResponse(
207
0
      BINARY_STRING("\x04\x01\x00\x00\x01" "\x00\x00\x00\x16"
208
0
                    "\x00\x01" "\x00\x0b" "CQL_VERSION"
209
0
                               "\x00\x05" "3.0.0"),
210
0
      BINARY_STRING("\x84\x00\x00\x00\x00" "\x00\x00\x00\x2e"
211
0
                    "\x00\x00\x00\x0a" "\x00\x28"
212
0
                    "STARTUP request should not be compressed"));
213
0
}
214
215
0
TEST_F(TestCQLService, OptionsRequest) {
216
0
  LOG(INFO) << "Test CQL OPTIONS request";
217
  // Send OPTIONS request using version V4
218
0
  SendRequestAndExpectResponse(
219
0
      BINARY_STRING("\x04\x00\x00\x00\x05" "\x00\x00\x00\x00"),
220
0
      BINARY_STRING("\x84\x00\x00\x00\x06" "\x00\x00\x00\x3b"
221
0
                    "\x00\x02" "\x00\x0b" "COMPRESSION"
222
0
                               "\x00\x02" "\x00\x03" "lz4" "\x00\x06" "snappy"
223
0
                               "\x00\x0b" "CQL_VERSION"
224
0
                               "\x00\x02" "\x00\x05" "3.0.0" "\x00\x05" "3.4.2"));
225
0
}
226
227
0
TEST_F(TestCQLService, InvalidRequest) {
228
0
  LOG(INFO) << "Test invalid CQL request";
229
  // Send response (0x84) as request
230
0
  SendRequestAndExpectResponse(
231
0
      BINARY_STRING("\x84\x00\x00\x00\x00" "\x00\x00\x00\x22"
232
0
                    "\x00\x00\x00\x0a" "\x00\x1c" "Unsupported protocol version"),
233
0
      BINARY_STRING("\x84\x00\x00\x00\x00" "\x00\x00\x00\x13"
234
0
                    "\x00\x00\x00\x0a" "\x00\x0d" "Not a request"));
235
236
  // Send ERROR as request
237
0
  SendRequestAndExpectResponse(
238
0
      BINARY_STRING("\x04\x00\x00\x00\x00" "\x00\x00\x00\x22"
239
0
                    "\x00\x00\x00\x0a" "\x00\x1c" "Unsupported protocol version"),
240
0
      BINARY_STRING("\x84\x00\x00\x00\x00" "\x00\x00\x00\x1a"
241
0
                    "\x00\x00\x00\x0a" "\x00\x14" "Not a request opcode"));
242
243
  // Send an unknown opcode
244
0
  SendRequestAndExpectResponse(
245
0
      BINARY_STRING("\x04\x00\x00\x00\xff" "\x00\x00\x00\x22"
246
0
                    "\x00\x00\x00\x0a" "\x00\x1c" "Unsupported protocol version"),
247
0
      BINARY_STRING("\x84\x00\x00\x00\x00" "\x00\x00\x00\x14"
248
0
                    "\x00\x00\x00\x0a" "\x00\x0e" "Unknown opcode"));
249
250
  // Send truncated request
251
0
  SendRequestAndExpectResponse(
252
0
      BINARY_STRING("\x04\x00\x00\x00\x01" "\x00\x00\x00\x0f"
253
0
                    "\x00\x01" "\x00\x0b" "CQL_VERSION"),
254
0
      BINARY_STRING("\x84\x00\x00\x00\x00" "\x00\x00\x00\x1b"
255
0
                    "\x00\x00\x00\x0a" "\x00\x15" "Truncated CQL message"));
256
257
  // Send truncated string in request
258
0
  SendRequestAndExpectResponse(
259
0
      BINARY_STRING("\x04\x00\x00\x00\x01" "\x00\x00\x00\x16"
260
0
                    "\x00\x01" "\x00\x0b" "CQL_VERSION"
261
0
                               "\x00\x15" "3.0.0"),
262
0
      BINARY_STRING("\x84\x00\x00\x00\x00" "\x00\x00\x00\x1b"
263
0
                    "\x00\x00\x00\x0a" "\x00\x15" "Truncated CQL message"));
264
265
  // Send request with extra trailing bytes
266
0
  SendRequestAndExpectResponse(
267
0
      BINARY_STRING("\x04\x00\x00\x00\x01" "\x00\x00\x00\x18"
268
0
                    "\x00\x01" "\x00\x0b" "CQL_VERSION"
269
0
                               "\x00\x05" "3.0.0"
270
0
                               "\x00\0x00"),
271
0
      BINARY_STRING("\x84\x00\x00\x00\x00" "\x00\x00\x00\x1d"
272
0
                    "\x00\x00\x00\x0a" "\x00\x17" "Request length too long"));
273
0
}
274
275
0
TEST_F(TestCQLService, TestCQLServerEventConst) {
276
0
  std::unique_ptr<SchemaChangeEventResponse> response(
277
0
      new SchemaChangeEventResponse("", "", "", "", {}));
278
0
  constexpr size_t kSize = sizeof(CQLServerEvent);
279
0
  std::unique_ptr<CQLServerEvent> event(new CQLServerEvent(std::move(response)));
280
0
  auto event_list = std::make_shared<CQLServerEventList>();
281
0
  event_list->AddEvent(std::move(event));
282
0
  yb::rpc::OutboundDataPtr data(event_list);
283
0
  void* ptr = event_list.get();
284
0
  char buffer[kSize];
285
0
  memcpy(buffer, ptr, kSize);
286
0
  data->Transferred(Status::OK(), nullptr);
287
0
  ASSERT_EQ(0, memcmp(buffer, ptr, kSize));
288
0
  data->Transferred(STATUS(NetworkError, "Dummy"), nullptr);
289
0
  ASSERT_EQ(0, memcmp(buffer, ptr, kSize));
290
0
}
291
292
0
void TestCQLService::TestSchemaChangeEvent() {
293
0
  LOG(INFO) << "Test CQL SCHEMA_CHANGE event with gflag cql_server_always_send_events = " <<
294
0
      FLAGS_cql_server_always_send_events;
295
296
  // Send STARTUP request using version V4.
297
0
  SendRequestAndExpectResponse(
298
0
      BINARY_STRING("\x04\x00\x00\x00\x01" "\x00\x00\x00\x16"
299
0
                    "\x00\x01" "\x00\x0b" "CQL_VERSION"
300
0
                               "\x00\x05" "3.0.0"),
301
0
      BINARY_STRING("\x84\x00\x00\x00\x02" "\x00\x00\x00\x00"));
302
303
  // Send CREATE KEYSPACE IF NOT EXISTS "kong"
304
  //      WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1}
305
  // Expecting only one CQL message as the result: CQL RESULT (opcode=8).
306
0
  string expected_response =
307
0
      BINARY_STRING("\x84\x00\x00\x00\x08" "\x00\x00\x00\x1d" "\x00\x00\x00\x05"
308
0
                                "\x00\x07" "CREATED"
309
0
                                "\x00\x08" "KEYSPACE"
310
0
                                "\x00\x04" "kong");
311
0
  if (FLAGS_cql_server_always_send_events) {
312
    // Expecting 2 CQL messages as the result: CQL RESULT (opcode=8) + CQL EVENT (opcode=0x0c).
313
0
    expected_response +=
314
0
        BINARY_STRING("\x84\x00\xff\xff\x0c" "\x00\x00\x00\x28"
315
0
                                  "\x00\x0d" "SCHEMA_CHANGE"
316
0
                                  "\x00\x07" "CREATED"
317
0
                                  "\x00\x08" "KEYSPACE"
318
0
                                  "\x00\x04" "kong");
319
0
  }
320
321
0
  SendRequestAndExpectResponse(
322
0
      BINARY_STRING("\x04\x00\x00\x00\x07" "\x00\x00\x00\x99"
323
0
                    "\x00\x00"  "\x00\x8c" "      CREATE KEYSPACE IF NOT EXISTS \"kong\""
324
0
                                    "\x0a" "      WITH REPLICATION =         {'class': "
325
0
                                           "'SimpleStrategy', 'replication_factor': 1}"
326
0
                                    "\x0a" "      "
327
0
                                    "\x0a" "    "
328
0
                                "\x00\x01" "\x14\x00\x00\x03\xe8\x00\x08"),
329
0
      expected_response);
330
331
  // Send USE "kong"
332
0
  SendRequestAndExpectResponse(
333
0
      BINARY_STRING("\x04\x00\x00\x00\x07" "\x00\x00\x00\x11"
334
0
                    "\x00\x00"  "\x00\x0a" "USE \"kong\""
335
0
                    "\x00\x01\x00"),
336
0
      BINARY_STRING("\x84\x00\x00\x00\x08" "\x00\x00\x00\x0a" "\x00\x00\x00\x03"
337
0
                                "\x00\x04" "kong"));
338
339
  // Send CREATE TABLE IF NOT EXISTS schema_meta(
340
  //          key text, subsystem text, last_executed text, executed set<text>,
341
  //          pending set<text>, PRIMARY KEY (key, subsystem))
342
  // Expecting only one CQL message as the result: CQL RESULT (opcode=8).
343
0
  expected_response =
344
0
      BINARY_STRING("\x84\x00\x00\x00\x08" "\x00\x00\x00\x27" "\x00\x00\x00\x05"
345
0
                                "\x00\x07" "CREATED"
346
0
                                "\x00\x05" "TABLE"
347
0
                                "\x00\x04" "kong"
348
0
                                "\x00\x0b" "schema_meta");
349
0
  if (FLAGS_cql_server_always_send_events) {
350
    // Expecting 2 CQL messages as the result: CQL RESULT (opcode=8) + CQL EVENT (opcode=0x0c).
351
0
    expected_response +=
352
0
      BINARY_STRING("\x84\x00\xff\xff\x0c" "\x00\x00\x00\x32"
353
0
                                "\x00\x0d" "SCHEMA_CHANGE"
354
0
                                "\x00\x07" "CREATED"
355
0
                                "\x00\x05" "TABLE"
356
0
                                "\x00\x04" "kong"
357
0
                                "\x00\x0b" "schema_meta");
358
0
  }
359
360
0
  SendRequestAndExpectResponse(
361
0
      BINARY_STRING("\x04\x00\x00\x00\x07" "\x00\x00\x01\x0d"
362
0
                    "\x00\x00"  "\x01\x00" "      CREATE TABLE IF NOT EXISTS schema_meta("
363
0
                                    "\x0a" "        key             text,"
364
0
                                    "\x0a" "        subsystem       text,"
365
0
                                    "\x0a" "        last_executed   text,"
366
0
                                    "\x0a" "        executed        set<text>,"
367
0
                                    "\x0a" "        pending         set<text>,"
368
0
                                    "\x0a"
369
0
                                    "\x0a" "        PRIMARY KEY (key, subsystem)"
370
0
                                    "\x0a" "      )"
371
0
                                    "\x0a" "    "
372
0
                                "\x00\x01" "\x14\x00\x00\x03\xe8\x00\x08"),
373
0
      expected_response);
374
375
  // Send REGISTER request to subscribe for the events: TOPOLOGY_CHANGE, STATUS_CHANGE,
376
  //                                                    SCHEMA_CHANGE
377
0
  SendRequestAndExpectResponse(
378
0
      BINARY_STRING("\x04\x00\x00\x00\x0b" "\x00\x00\x00\x31"
379
0
                    "\x00\x03"  "\x00\x0f" "TOPOLOGY_CHANGE"
380
0
                                "\x00\x0d" "STATUS_CHANGE"
381
0
                                "\x00\x0d" "SCHEMA_CHANGE"),
382
0
      BINARY_STRING("\x84\x00\x00\x00\x02" "\x00\x00\x00\x00"));
383
384
  // Send CREATE TABLE IF NOT EXISTS schema_meta2(
385
  //          key text, subsystem text, last_executed text, executed set<text>,
386
  //          pending set<text>, PRIMARY KEY (key, subsystem))
387
0
  SendRequestAndExpectResponse(
388
0
      BINARY_STRING("\x04\x00\x00\x00\x07" "\x00\x00\x01\x0d"
389
0
                    "\x00\x00"  "\x01\x00" "      CREATE TABLE IF NOT EXISTS schema_meta2("
390
0
                                    "\x0a" "        key             text,"
391
0
                                    "\x0a" "        subsystem       text,"
392
0
                                    "\x0a" "        last_executed   text,"
393
0
                                    "\x0a" "        executed        set<text>,"
394
0
                                    "\x0a" "        pending         set<text>,"
395
0
                                    "\x0a"
396
0
                                    "\x0a" "        PRIMARY KEY (key, subsystem)"
397
0
                                    "\x0a" "      )"
398
0
                                    "\x0a" "   "
399
0
                                "\x00\x01" "\x14\x00\x00\x03\xe8\x00\x08"),
400
      // Expecting 2 CQL messages as the result: CQL RESULT (opcode=8) + CQL EVENT (opcode=0x0c).
401
0
      BINARY_STRING("\x84\x00\x00\x00\x08" "\x00\x00\x00\x28" "\x00\x00\x00\x05"
402
0
                                "\x00\x07" "CREATED"
403
0
                                "\x00\x05" "TABLE"
404
0
                                "\x00\x04" "kong"
405
0
                                "\x00\x0c" "schema_meta2"
406
0
                    "\x84\x00\xff\xff\x0c" "\x00\x00\x00\x33"
407
0
                                "\x00\x0d" "SCHEMA_CHANGE"
408
0
                                "\x00\x07" "CREATED"
409
0
                                "\x00\x05" "TABLE"
410
0
                                "\x00\x04" "kong"
411
0
                                "\x00\x0c" "schema_meta2"));
412
0
}
413
414
0
TEST_F(TestCQLService, TestSchemaChangeEvent) {
415
0
  TestSchemaChangeEvent();
416
0
}
417
418
class TestCQLServiceWithGFlag : public TestCQLService {
419
 public:
420
0
  void SetUp() override {
421
0
    FLAGS_cql_server_always_send_events = true;
422
0
    TestCQLService::SetUp();
423
0
  }
424
};
425
426
0
TEST_F(TestCQLServiceWithGFlag, TestSchemaChangeEventWithGFlag) {
427
0
  TestSchemaChangeEvent();
428
0
}
429
430
0
TEST_F(TestCQLService, TestReadSystemTable) {
431
  // Send STARTUP request using version V4.
432
0
  SendRequestAndExpectResponse(
433
0
      BINARY_STRING("\x04\x00\x00\x00\x01" "\x00\x00\x00\x16"
434
0
                    "\x00\x01" "\x00\x0b" "CQL_VERSION"
435
0
                               "\x00\x05" "3.0.0"),
436
0
      BINARY_STRING("\x84\x00\x00\x00\x02" // 0x02 = READY
437
0
                    "\x00\x00\x00\x00"));  // zero body size
438
439
0
  SendRequestAndExpectResponse(
440
0
      BINARY_STRING("\x04\x00\x00\x00\x07" // 0x07 = QUERY
441
0
                    "\x00\x00\x00\x23"     // body size
442
0
                    "\x00\x00\x00\x1c" "SELECT key FROM system.local"
443
0
                    "\x00\x01"             // consistency: 0x0001 = ONE
444
0
                    "\x00"),               // bit flags
445
0
      BINARY_STRING("\x84\x00\x00\x00\x08" // 0x08 = RESULT
446
0
                    "\x00\x00\x00\x2f"     // body size
447
0
                    "\x00\x00\x00\x02"     // 0x00000002 = ROWS
448
0
                    "\x00\x00\x00\x01"     // flags: 0x01 = Global_tables_spec
449
0
                    "\x00\x00\x00\x01"     // column count
450
0
                    "\x00\x06" "system"
451
0
                    "\x00\x05" "local"
452
0
                    "\x00\x03" "key"
453
0
                    "\x00\x0d"             // type id: 0x000D = Varchar
454
0
                    "\x00\x00\x00\x01"     // row count
455
0
                    "\x00\x00\x00\x05" "local"));
456
0
}
457
458
class TestCQLServiceWithCassAuth : public TestCQLService {
459
 public:
460
0
  void SetUp() override {
461
0
    FLAGS_use_cassandra_authentication = true;
462
0
    TestCQLService::SetUp();
463
0
  }
464
};
465
466
0
TEST_F(TestCQLServiceWithCassAuth, TestReadSystemTableNotAuthenticated) {
467
  // Send STARTUP request using version V4.
468
0
  SendRequestAndExpectResponse(
469
0
      BINARY_STRING("\x04\x00\x00\x00\x01" "\x00\x00\x00\x16"
470
0
                    "\x00\x01" "\x00\x0b" "CQL_VERSION"
471
0
                               "\x00\x05" "3.0.0"),
472
0
      BINARY_STRING("\x84\x00\x00\x00\x03" // 0x03 = AUTHENTICATE
473
0
                    "\x00\x00\x00\x31"     // body size
474
0
                    "\x00\x2F" "org.apache.cassandra.auth.PasswordAuthenticator"));
475
476
  // Try to skip authorization and query the data.
477
0
  SendRequestAndExpectResponse(
478
0
      BINARY_STRING("\x04\x00\x00\x00\x07" // 0x07 = QUERY
479
0
                    "\x00\x00\x00\x23"     // body size
480
0
                    "\x00\x00\x00\x1c" "SELECT key FROM system.local"
481
0
                    "\x00\x01"             // consistency: 0x0001 = ONE
482
0
                    "\x00"),               // bit flags
483
0
      BINARY_STRING("\x84\x00\x00\x00\x00" // 0x00 = ERROR
484
0
                    "\x00\x00\x00\x3b"     // body size
485
0
                    "\x00\x00\x00\x00"     // error code
486
0
                    "\x00\x35" "Could not execute statement by not authenticated user"));
487
0
}
488
489
0
TEST_F(TestCQLServiceWithCassAuth, TestReadSystemTableAuthenticated) {
490
  // Send STARTUP request using version V4.
491
0
  SendRequestAndExpectResponse(
492
0
      BINARY_STRING("\x04\x00\x00\x00\x01" "\x00\x00\x00\x16"
493
0
                    "\x00\x01" "\x00\x0b" "CQL_VERSION"
494
0
                               "\x00\x05" "3.0.0"),
495
0
      BINARY_STRING("\x84\x00\x00\x00\x03" // 0x03 = AUTHENTICATE
496
0
                    "\x00\x00\x00\x31"     // body size
497
0
                    "\x00\x2F" "org.apache.cassandra.auth.PasswordAuthenticator"));
498
499
  // Invalid authorization: send wrong user name.
500
0
  SendRequestAndExpectResponse(
501
0
      BINARY_STRING("\x04\x00\x00\x00\x0f" // 0x0F = AUTH_RESPONSE
502
0
                    "\x00\x00\x00\x17"     // body size
503
0
                    "\x00\x00\x00\x13" "\x00" "acssandra" "\x00" "password"),
504
0
      BINARY_STRING("\x84\x00\x00\x00\x00" // 0x00 = ERROR
505
0
                    "\x00\x00\x00\x41"     // body size
506
0
                    "\x00\x00\x01\x00"     // error code
507
0
                    "\x00\x3b" "Provided username 'acssandra' and/or password are incorrect"));
508
  // Invalid authorization: send wrong password.
509
0
  SendRequestAndExpectResponse(
510
0
      BINARY_STRING("\x04\x00\x00\x00\x0f" // 0x0F = AUTH_RESPONSE
511
0
                    "\x00\x00\x00\x17"     // body size
512
0
                    "\x00\x00\x00\x13" "\x00" "cassandra" "\x00" "password"),
513
0
      BINARY_STRING("\x84\x00\x00\x00\x00" // 0x00 = ERROR
514
0
                    "\x00\x00\x00\x41"     // body size
515
0
                    "\x00\x00\x01\x00"     // error code
516
0
                    "\x00\x3b" "Provided username 'cassandra' and/or password are incorrect"));
517
  // Invalid authorization: send null token.
518
0
  SendRequestAndExpectResponse(
519
0
      BINARY_STRING("\x04\x00\x00\x00\x0f" // 0x0F = AUTH_RESPONSE
520
0
                    "\x00\x00\x00\x04"     // body size
521
0
                    "\x00\x00\x00\x00"),
522
0
      BINARY_STRING("\x84\x00\x00\x00\x00" // 0x00 = ERROR
523
0
                    "\x00\x00\x00\x1a"     // body size
524
0
                    "\x00\x00\x00\x0a"     // error code
525
0
                    "\x00\x14" "Invalid empty token!"));
526
  // Invalid authorization: send token 'deadbeaf'.
527
0
  SendRequestAndExpectResponse(
528
0
      BINARY_STRING("\x04\x00\x00\x00\x0f" // 0x0F = AUTH_RESPONSE
529
0
                    "\x00\x00\x00\x08"     // body size
530
0
                    "\x00\x00\x00\x04" "\xde\xad\xbe\xaf"),
531
0
      BINARY_STRING("\x84\x00\x00\x00\x00" // 0x00 = ERROR
532
0
                    "\x00\x00\x00\x30"     // body size
533
0
                    "\x00\x00\x00\x0a"     // error code
534
0
                    "\x00\x2a" "Invalid format. Message must begin with \\0"));
535
  // Invalid authorization: send token '\x00deadbeaf'.
536
0
  SendRequestAndExpectResponse(
537
0
      BINARY_STRING("\x04\x00\x00\x00\x0f" // 0x0F = AUTH_RESPONSE
538
0
                    "\x00\x00\x00\x09"     // body size
539
0
                    "\x00\x00\x00\x05" "\x00\xde\xad\xbe\xaf"),
540
0
      BINARY_STRING("\x84\x00\x00\x00\x00" // 0x00 = ERROR
541
0
                    "\x00\x00\x00\x3c"     // body size
542
0
                    "\x00\x00\x00\x0a"     // error code
543
0
                    "\x00\x36" "Invalid format. Message must contain \\0 after username"));
544
545
  // Correct authorization.
546
0
  SendRequestAndExpectResponse(
547
0
      BINARY_STRING("\x04\x00\x00\x00\x0f" // 0x0F = AUTH_RESPONSE
548
0
                    "\x00\x00\x00\x18"     // body size
549
0
                    "\x00\x00\x00\x14" "\x00" "cassandra" "\x00" "cassandra"),
550
0
      BINARY_STRING("\x84\x00\x00\x00\x10" // 0x10 = AUTH_SUCCESS
551
0
                    "\x00\x00\x00\x04"     // body size
552
0
                    "\x00\x00\x00\x00"));  // empty token
553
554
  // Query the data.
555
0
  SendRequestAndExpectResponse(
556
0
      BINARY_STRING("\x04\x00\x00\x00\x07" // 0x07 = QUERY
557
0
                    "\x00\x00\x00\x23"     // body size
558
0
                    "\x00\x00\x00\x1c" "SELECT key FROM system.local"
559
0
                    "\x00\x01"             // consistency: 0x0001 = ONE
560
0
                    "\x00"),               // bit flags
561
0
      BINARY_STRING("\x84\x00\x00\x00\x08" // 0x08 = RESULT
562
0
                    "\x00\x00\x00\x2f"     // body size
563
0
                    "\x00\x00\x00\x02"     // 0x00000002 = ROWS
564
0
                    "\x00\x00\x00\x01"     // flags: 0x01 = Global_tables_spec
565
0
                    "\x00\x00\x00\x01"     // column count
566
0
                    "\x00\x06" "system"
567
0
                    "\x00\x05" "local"
568
0
                    "\x00\x03" "key"
569
0
                    "\x00\x0d"             // type id: 0x000D = Varchar
570
0
                    "\x00\x00\x00\x01"     // row count
571
0
                    "\x00\x00\x00\x05" "local"));
572
0
}
573
574
}  // namespace cqlserver
575
}  // namespace yb