YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/master/master-test.cc
Line
Count
Source (jump to first uncovered line)
1
// or more contributor license agreements.  See the NOTICE file
2
// distributed with this work for additional information
3
// regarding copyright ownership.  The ASF licenses this file
4
// to you under the Apache License, Version 2.0 (the
5
// "License"); you may not use this file except in compliance
6
// with the License.  You may obtain a copy of the License at
7
//
8
//   http://www.apache.org/licenses/LICENSE-2.0
9
//
10
// Unless required by applicable law or agreed to in writing,
11
// software distributed under the License is distributed on an
12
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
13
// KIND, either express or implied.  See the License for the
14
// specific language governing permissions and limitations
15
// under the License.
16
//
17
// The following only applies to changes made to this file as part of YugaByte development.
18
//
19
// Portions Copyright (c) YugaByte, Inc.
20
//
21
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
22
// in compliance with the License.  You may obtain a copy of the License at
23
//
24
// http://www.apache.org/licenses/LICENSE-2.0
25
//
26
// Unless required by applicable law or agreed to in writing, software distributed under the License
27
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
28
// or implied.  See the License for the specific language governing permissions and limitations
29
// under the License.
30
//
31
32
#include <algorithm>
33
#include <memory>
34
#include <sstream>
35
#include <string>
36
#include <tuple>
37
#include <vector>
38
39
#include <gtest/gtest.h>
40
41
#include "yb/common/ql_type.h"
42
#include "yb/common/schema.h"
43
#include "yb/common/wire_protocol.h"
44
45
#include "yb/gutil/casts.h"
46
#include "yb/gutil/strings/substitute.h"
47
48
#include "yb/master/call_home.h"
49
#include "yb/master/catalog_manager.h"
50
#include "yb/master/master-test-util.h"
51
#include "yb/master/master-test_base.h"
52
#include "yb/master/master.h"
53
#include "yb/master/master_client.proxy.h"
54
#include "yb/master/master_cluster.proxy.h"
55
#include "yb/master/master_ddl.proxy.h"
56
#include "yb/master/master_heartbeat.proxy.h"
57
#include "yb/master/master_error.h"
58
#include "yb/master/mini_master.h"
59
#include "yb/master/sys_catalog.h"
60
61
#include "yb/rpc/messenger.h"
62
#include "yb/rpc/proxy.h"
63
64
#include "yb/server/server_base.proxy.h"
65
66
#include "yb/util/countdown_latch.h"
67
#include "yb/util/jsonreader.h"
68
#include "yb/util/metrics.h"
69
#include "yb/util/monotime.h"
70
#include "yb/util/random_util.h"
71
#include "yb/util/status.h"
72
#include "yb/util/status_log.h"
73
#include "yb/util/test_util.h"
74
#include "yb/util/thread.h"
75
#include "yb/util/tsan_util.h"
76
#include "yb/util/user.h"
77
78
DECLARE_string(callhome_collection_level);
79
DECLARE_string(callhome_tag);
80
DECLARE_string(callhome_url);
81
DECLARE_bool(callhome_enabled);
82
DECLARE_int32(callhome_interval_secs);
83
DECLARE_double(leader_failure_max_missed_heartbeat_periods);
84
DECLARE_int32(TEST_simulate_slow_table_create_secs);
85
DECLARE_bool(TEST_return_error_if_namespace_not_found);
86
DECLARE_bool(TEST_hang_on_namespace_transition);
87
DECLARE_bool(TEST_simulate_crash_after_table_marked_deleting);
88
DECLARE_int32(TEST_sys_catalog_write_rejection_percentage);
89
DECLARE_bool(TEST_tablegroup_master_only);
90
DECLARE_bool(TEST_simulate_port_conflict_error);
91
92
METRIC_DECLARE_counter(block_cache_misses);
93
METRIC_DECLARE_counter(block_cache_hits);
94
95
namespace yb {
96
namespace master {
97
98
using strings::Substitute;
99
100
class MasterTest : public MasterTestBase {
101
};
102
103
1
TEST_F(MasterTest, TestPingServer) {
104
  // Ping the server.
105
1
  server::PingRequestPB req;
106
1
  server::PingResponsePB resp;
107
108
1
  rpc::ProxyCache proxy_cache(client_messenger_.get());
109
1
  server::GenericServiceProxy generic_proxy(&proxy_cache, mini_master_->bound_rpc_addr());
110
1
  ASSERT_OK(generic_proxy.Ping(req, &resp, ResetAndGetController()));
111
1
}
112
113
2
static void MakeHostPortPB(const std::string& host, uint32_t port, HostPortPB* pb) {
114
2
  pb->set_host(host);
115
2
  pb->set_port(port);
116
2
}
117
118
// Test that shutting down a MiniMaster without starting it does not
119
// SEGV.
120
1
TEST_F(MasterTest, TestShutdownWithoutStart) {
121
1
  MiniMaster m(Env::Default(), "/xxxx", AllocateFreePort(), AllocateFreePort(), 0);
122
1
  m.Shutdown();
123
1
}
124
125
1
TEST_F(MasterTest, TestCallHome) {
126
1
  string json;
127
1
  CountDownLatch latch(1);
128
1
  const char* tag_value = "callhome-test";
129
130
1
  auto webserver_dir = GetTestPath("webserver-docroot");
131
1
  CHECK_OK(env_->CreateDir(webserver_dir));
132
133
1
  WebserverOptions opts;
134
1
  opts.port = 0;
135
1
  opts.doc_root = webserver_dir;
136
1
  Webserver webserver(opts, "WebserverTest");
137
1
  ASSERT_OK(webserver.Start());
138
139
1
  std::vector<Endpoint> addrs;
140
1
  ASSERT_OK(webserver.GetBoundAddresses(&addrs));
141
1
  ASSERT_EQ(addrs.size(), 1);
142
1
  auto addr = addrs[0];
143
144
3
  auto handler = [&json, &latch] (const Webserver::WebRequest& req, Webserver::WebResponse* resp) {
145
3
    ASSERT_EQ(req.request_method, "POST");
146
3
    ASSERT_EQ(json, req.post_data);
147
3
    latch.CountDown();
148
3
  };
149
150
1
  webserver.RegisterPathHandler("/callhome", "callhome", handler);
151
1
  FLAGS_callhome_tag = tag_value;
152
1
  FLAGS_callhome_url = Format("http://$0/callhome", addr);
153
154
1
  set<string> low {"cluster_uuid", "node_uuid", "server_type", "version_info",
155
1
                   "timestamp", "tables", "masters",  "tservers", "tablets", "gflags"};
156
1
  std::unordered_map<string, set<string>> collection_levels;
157
1
  collection_levels["low"] = low;
158
1
  collection_levels["medium"] = low;
159
1
  collection_levels["medium"].insert({"hostname", "current_user"});
160
1
  collection_levels["high"] = collection_levels["medium"];
161
1
  collection_levels["high"].insert({"metrics", "rpcs"});
162
163
3
  for (const auto& collection_level : collection_levels) {
164
3
    LOG(INFO) << "Collection level: " << collection_level.first;
165
3
    FLAGS_callhome_collection_level = collection_level.first;
166
3
    CallHome call_home(mini_master_->master(), ServerType::MASTER);
167
3
    json = call_home.BuildJson();
168
3
    ASSERT_TRUE(!json.empty());
169
3
    JsonReader reader(json);
170
3
    ASSERT_OK(reader.Init());
171
36
    for (const auto& field : collection_level.second) {
172
36
      LOG(INFO) << "Checking json has field: " << field;
173
36
      ASSERT_TRUE(reader.root()->HasMember(field.c_str()));
174
36
    }
175
3
    LOG(INFO) << "Checking json has field: tag";
176
3
    ASSERT_TRUE(reader.root()->HasMember("tag"));
177
178
3
    string received_tag;
179
3
    ASSERT_OK(reader.ExtractString(reader.root(), "tag", &received_tag));
180
3
    ASSERT_EQ(received_tag, tag_value);
181
182
3
    if (collection_level.second.find("hostname") != collection_level.second.end()) {
183
2
      string received_hostname;
184
2
      ASSERT_OK(reader.ExtractString(reader.root(), "hostname", &received_hostname));
185
2
      ASSERT_EQ(received_hostname, mini_master_->master()->get_hostname());
186
2
    }
187
188
3
    if (collection_level.second.find("current_user") != collection_level.second.end()) {
189
2
      string received_user;
190
2
      ASSERT_OK(reader.ExtractString(reader.root(), "current_user", &received_user));
191
2
      auto expected_user = ASSERT_RESULT(GetLoggedInUser());
192
2
      ASSERT_EQ(received_user, expected_user);
193
2
    }
194
195
3
    auto count = reader.root()->MemberEnd() - reader.root()->MemberBegin();
196
3
    LOG(INFO) << "Number of elements for level " << collection_level.first << ": " << count;
197
    // The number of fields should be equal to the number of collectors plus one for the tag field.
198
3
    ASSERT_EQ(count, collection_level.second.size() + 1);
199
200
3
    call_home.SendData(json);
201
3
    ASSERT_TRUE(latch.WaitFor(MonoDelta::FromSeconds(10)));
202
3
    latch.Reset(1);
203
3
  }
204
1
}
205
206
// This tests whether the enabling/disabling of callhome is happening dynamically
207
// during runtime.
208
1
TEST_F(MasterTest, TestCallHomeFlag) {
209
1
  CountDownLatch latch(1);
210
1
  const char* tag_value = "callhome-test";
211
1
  bool disabled = false;
212
213
  // Set up the webserver.
214
1
  auto webserver_dir = GetTestPath("webserver-docroot");
215
1
  CHECK_OK(env_->CreateDir(webserver_dir));
216
217
1
  WebserverOptions opts;
218
1
  opts.port = 0;
219
1
  opts.doc_root = webserver_dir;
220
1
  Webserver webserver(opts, "WebserverTest");
221
1
  ASSERT_OK(webserver.Start());
222
223
1
  std::vector<Endpoint> addrs;
224
1
  ASSERT_OK(webserver.GetBoundAddresses(&addrs));
225
1
  ASSERT_EQ(addrs.size(), 1);
226
1
  auto addr = addrs[0];
227
228
  // By default callhome is enabled. This handler is expected to be called
229
  // before disabling the flag. Once the flag is disabled, there shouldn't be any http posts.
230
1
  auto handler = [&latch, &disabled] (const Webserver::WebRequest& req,
231
1
                                        Webserver::WebResponse* resp) {
232
1
    ASSERT_EQ(req.request_method, "POST");
233
    // After callhome is disabled, assert if we get any more POST.
234
1
    ASSERT_FALSE(disabled);
235
1
    LOG(INFO) << "Received callhome data\n" << req.post_data;
236
1
    latch.CountDown();
237
1
  };
238
239
1
  webserver.RegisterPathHandler("/callhome", "callhome", handler);
240
1
  LOG(INFO) << "Started webserver to listen for callhome post requests.";
241
242
1
  FLAGS_callhome_tag = tag_value;
243
1
  FLAGS_callhome_url = Format("http://$0/callhome", addr);
244
  // Set the interval to 3 secs.
245
1
  FLAGS_callhome_interval_secs = 3 * kTimeMultiplier;
246
  // Start with the default value i.e. callhome enabled.
247
1
  disabled = false;
248
249
1
  CallHome call_home(mini_master_->master(), ServerType::MASTER);
250
1
  call_home.ScheduleCallHome(1 * kTimeMultiplier);
251
252
  // Wait for at least one non-empty response.
253
1
  ASSERT_TRUE(latch.WaitFor(MonoDelta::FromSeconds(10 * kTimeMultiplier)));
254
255
  // Disable the callhome flag now.
256
1
  disabled = true;
257
1
  ANNOTATE_UNPROTECTED_WRITE(FLAGS_callhome_enabled) = false;
258
1
  LOG(INFO) << "Callhome disabled. No more traffic";
259
260
  // Wait for 3 cycles for no callhome posts. The handler is expected to assert
261
  // if it gets any new HTTP POST now.
262
1
  SleepFor(MonoDelta::FromSeconds(3 * FLAGS_callhome_interval_secs * kTimeMultiplier));
263
1
}
264
265
1
TEST_F(MasterTest, TestRegisterAndHeartbeat) {
266
1
  const char *kTsUUID = "my-ts-uuid";
267
268
1
  TSToMasterCommonPB common;
269
1
  common.mutable_ts_instance()->set_permanent_uuid(kTsUUID);
270
1
  common.mutable_ts_instance()->set_instance_seqno(1);
271
272
  // Try a heartbeat. The server hasn't heard of us, so should ask us to re-register.
273
1
  {
274
1
    TSHeartbeatRequestPB req;
275
1
    TSHeartbeatResponsePB resp;
276
1
    req.mutable_common()->CopyFrom(common);
277
1
    ASSERT_OK(proxy_heartbeat_->TSHeartbeat(req, &resp, ResetAndGetController()));
278
279
1
    ASSERT_TRUE(resp.needs_reregister());
280
1
    ASSERT_TRUE(resp.needs_full_tablet_report());
281
1
  }
282
283
1
  vector<shared_ptr<TSDescriptor> > descs;
284
1
  mini_master_->master()->ts_manager()->GetAllDescriptors(&descs);
285
2
  ASSERT_EQ(0, descs.size()) << "Should not have registered anything";
286
287
1
  shared_ptr<TSDescriptor> ts_desc;
288
1
  ASSERT_FALSE(mini_master_->master()->ts_manager()->LookupTSByUUID(kTsUUID, &ts_desc));
289
290
  // Register the fake TS, without sending any tablet report.
291
1
  TSRegistrationPB fake_reg;
292
1
  MakeHostPortPB("localhost", 1000, fake_reg.mutable_common()->add_private_rpc_addresses());
293
1
  MakeHostPortPB("localhost", 2000, fake_reg.mutable_common()->add_http_addresses());
294
295
1
  {
296
1
    TSHeartbeatRequestPB req;
297
1
    TSHeartbeatResponsePB resp;
298
1
    req.mutable_common()->CopyFrom(common);
299
1
    req.mutable_registration()->CopyFrom(fake_reg);
300
1
    ASSERT_OK(proxy_heartbeat_->TSHeartbeat(req, &resp, ResetAndGetController()));
301
302
1
    ASSERT_FALSE(resp.needs_reregister());
303
1
    ASSERT_TRUE(resp.needs_full_tablet_report());
304
1
    ASSERT_FALSE(resp.has_tablet_report_limit()); // No limit unless capability registered.
305
1
  }
306
307
1
  descs.clear();
308
1
  mini_master_->master()->ts_manager()->GetAllDescriptors(&descs);
309
2
  ASSERT_EQ(1, descs.size()) << "Should have registered the TS";
310
1
  TSRegistrationPB reg = descs[0]->GetRegistration();
311
2
  ASSERT_EQ(fake_reg.DebugString(), reg.DebugString()) << "Master got different registration";
312
313
1
  ASSERT_TRUE(mini_master_->master()->ts_manager()->LookupTSByUUID(kTsUUID, &ts_desc));
314
1
  ASSERT_EQ(ts_desc, descs[0]);
315
316
  // Add capabilities in next registration.
317
1
  auto cap = Capabilities();
318
1
  *fake_reg.mutable_capabilities() =
319
1
      google::protobuf::RepeatedField<CapabilityId>(cap.begin(), cap.end());
320
321
  // If the tablet server somehow lost the response to its registration RPC, it would
322
  // attempt to register again. In that case, we shouldn't reject it -- we should
323
  // just respond the same.
324
1
  {
325
1
    TSHeartbeatRequestPB req;
326
1
    TSHeartbeatResponsePB resp;
327
1
    req.mutable_common()->CopyFrom(common);
328
1
    req.mutable_registration()->CopyFrom(fake_reg);
329
1
    ASSERT_OK(proxy_heartbeat_->TSHeartbeat(req, &resp, ResetAndGetController()));
330
331
1
    ASSERT_FALSE(resp.needs_reregister());
332
1
    ASSERT_TRUE(resp.needs_full_tablet_report());
333
1
    ASSERT_TRUE(resp.has_tablet_report_limit()); // Limit given, since TS capability registered.
334
1
  }
335
336
  // Now begin sending full tablet report
337
1
  {
338
1
    TSHeartbeatRequestPB req;
339
1
    TSHeartbeatResponsePB resp;
340
1
    req.mutable_common()->CopyFrom(common);
341
1
    TabletReportPB* tr = req.mutable_tablet_report();
342
1
    tr->set_is_incremental(false);
343
1
    tr->set_sequence_number(0);
344
1
    tr->set_remaining_tablet_count(1);
345
1
    ASSERT_OK(proxy_heartbeat_->TSHeartbeat(req, &resp, ResetAndGetController()));
346
347
1
    ASSERT_FALSE(resp.needs_reregister());
348
1
    ASSERT_FALSE(resp.needs_full_tablet_report());
349
1
  }
350
351
  // ...and finish the full tablet report.
352
1
  {
353
1
    TSHeartbeatRequestPB req;
354
1
    TSHeartbeatResponsePB resp;
355
1
    req.mutable_common()->CopyFrom(common);
356
1
    TabletReportPB* tr = req.mutable_tablet_report();
357
1
    tr->set_is_incremental(false);
358
1
    tr->set_sequence_number(0);
359
1
    tr->set_remaining_tablet_count(0);
360
1
    ASSERT_OK(proxy_heartbeat_->TSHeartbeat(req, &resp, ResetAndGetController()));
361
362
1
    ASSERT_FALSE(resp.needs_reregister());
363
1
    ASSERT_FALSE(resp.needs_full_tablet_report());
364
1
  }
365
366
1
  descs.clear();
367
1
  mini_master_->master()->ts_manager()->GetAllDescriptors(&descs);
368
2
  ASSERT_EQ(1, descs.size()) << "Should still only have one TS registered";
369
370
1
  ASSERT_TRUE(mini_master_->master()->ts_manager()->LookupTSByUUID(kTsUUID, &ts_desc));
371
1
  ASSERT_EQ(ts_desc, descs[0]);
372
373
  // Ensure that the ListTabletServers shows the faked server.
374
1
  {
375
1
    ListTabletServersRequestPB req;
376
1
    ListTabletServersResponsePB resp;
377
1
    ASSERT_OK(proxy_cluster_->ListTabletServers(req, &resp, ResetAndGetController()));
378
1
    LOG(INFO) << resp.DebugString();
379
1
    ASSERT_EQ(1, resp.servers_size());
380
1
    ASSERT_EQ("my-ts-uuid", resp.servers(0).instance_id().permanent_uuid());
381
1
    ASSERT_EQ(1, resp.servers(0).instance_id().instance_seqno());
382
1
  }
383
1
}
384
385
1
TEST_F(MasterTest, TestListTablesWithoutMasterCrash) {
386
1
  FLAGS_TEST_simulate_slow_table_create_secs = 10;
387
388
1
  const char *kNamespaceName = "testnamespace";
389
1
  CreateNamespaceResponsePB resp;
390
1
  ASSERT_OK(CreateNamespace(kNamespaceName, YQLDatabase::YQL_DATABASE_CQL, &resp));
391
392
1
  auto task = [kNamespaceName, this]() {
393
1
    const char *kTableName = "testtable";
394
1
    const Schema kTableSchema({ ColumnSchema("key", INT32) }, 1);
395
1
    shared_ptr<RpcController> controller;
396
    // Set an RPC timeout for the controllers.
397
1
    controller = make_shared<RpcController>();
398
1
    controller->set_timeout(MonoDelta::FromSeconds(FLAGS_TEST_simulate_slow_table_create_secs * 2));
399
400
1
    CreateTableRequestPB req;
401
1
    CreateTableResponsePB resp;
402
403
1
    req.set_name(kTableName);
404
1
    SchemaToPB(kTableSchema, req.mutable_schema());
405
1
    req.mutable_namespace_()->set_name(kNamespaceName);
406
1
    req.mutable_partition_schema()->set_hash_schema(PartitionSchemaPB::MULTI_COLUMN_HASH_SCHEMA);
407
1
    req.mutable_schema()->mutable_table_properties()->set_num_tablets(8);
408
1
    ASSERT_OK(this->proxy_ddl_->CreateTable(req, &resp, controller.get()));
409
1
    ASSERT_FALSE(resp.has_error());
410
1
    LOG(INFO) << "Done creating table";
411
1
  };
412
413
1
  std::thread t(task);
414
415
  // Delete the namespace (by NAME).
416
1
  {
417
    // Give the CreateTable request some time to start and find the namespace.
418
1
    SleepFor(MonoDelta::FromSeconds(FLAGS_TEST_simulate_slow_table_create_secs / 2));
419
1
    DeleteNamespaceRequestPB req;
420
1
    DeleteNamespaceResponsePB resp;
421
1
    req.mutable_namespace_()->set_name(kNamespaceName);
422
1
    ASSERT_OK(proxy_ddl_->DeleteNamespace(req, &resp, ResetAndGetController()));
423
1
    SCOPED_TRACE(resp.DebugString());
424
1
    ASSERT_FALSE(resp.has_error());
425
1
  }
426
427
1
  t.join();
428
429
1
  {
430
1
    FLAGS_TEST_return_error_if_namespace_not_found = true;
431
1
    ListTablesRequestPB req;
432
1
    ListTablesResponsePB resp;
433
1
    ASSERT_OK(proxy_ddl_->ListTables(req, &resp, ResetAndGetController()));
434
1
    LOG(INFO) << "Finished first ListTables request";
435
1
    ASSERT_TRUE(resp.has_error());
436
1
    string msg = resp.error().status().message();
437
1
    ASSERT_TRUE(msg.find("Keyspace identifier not found") != string::npos);
438
439
    // After turning off this flag, ListTables should skip the table with the error.
440
1
    FLAGS_TEST_return_error_if_namespace_not_found = false;
441
1
    ASSERT_OK(proxy_ddl_->ListTables(req, &resp, ResetAndGetController()));
442
1
    LOG(INFO) << "Finished second ListTables request";
443
1
    ASSERT_FALSE(resp.has_error());
444
1
  }
445
1
}
446
447
1
TEST_F(MasterTest, TestCatalog) {
448
1
  const char *kTableName = "testtb";
449
1
  const char *kOtherTableName = "tbtest";
450
1
  const Schema kTableSchema({ ColumnSchema("key", INT32),
451
1
                              ColumnSchema("v1", UINT64),
452
1
                              ColumnSchema("v2", STRING) },
453
1
                            1);
454
455
1
  ASSERT_OK(CreateTable(kTableName, kTableSchema));
456
457
1
  ListTablesResponsePB tables;
458
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
459
1
  ASSERT_EQ(1 + kNumSystemTables, tables.tables_size());
460
1
  CheckTables(
461
1
      {
462
1
          std::make_tuple(kTableName, default_namespace_name, default_namespace_id,
463
1
              USER_TABLE_RELATION),
464
1
          EXPECTED_SYSTEM_TABLES
465
1
      }, tables);
466
467
  // Delete the table
468
1
  TableId id;
469
1
  ASSERT_OK(DeleteTableSync(default_namespace_name, kTableName, &id));
470
471
  // List tables, should show only system table
472
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
473
1
  ASSERT_EQ(kNumSystemTables, tables.tables_size());
474
1
  CheckTables(
475
1
      {
476
1
          EXPECTED_SYSTEM_TABLES
477
1
      }, tables);
478
479
  // Re-create the table
480
1
  ASSERT_OK(CreateTable(kTableName, kTableSchema));
481
482
  // Restart the master, verify the table still shows up.
483
1
  ASSERT_OK(mini_master_->Restart());
484
1
  ASSERT_OK(mini_master_->master()->WaitUntilCatalogManagerIsLeaderAndReadyForTests());
485
486
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
487
1
  ASSERT_EQ(1 + kNumSystemTables, tables.tables_size());
488
1
  CheckTables(
489
1
      {
490
1
          std::make_tuple(kTableName, default_namespace_name, default_namespace_id,
491
1
              USER_TABLE_RELATION),
492
1
          EXPECTED_SYSTEM_TABLES
493
1
      }, tables);
494
495
  // Test listing tables with a filter.
496
1
  ASSERT_OK(CreateTable(kOtherTableName, kTableSchema));
497
498
1
  {
499
1
    ListTablesRequestPB req;
500
1
    req.set_name_filter("test");
501
1
    DoListTables(req, &tables);
502
1
    ASSERT_EQ(2, tables.tables_size());
503
1
  }
504
505
1
  {
506
1
    ListTablesRequestPB req;
507
1
    req.set_name_filter("tb");
508
1
    DoListTables(req, &tables);
509
1
    ASSERT_EQ(2, tables.tables_size());
510
1
  }
511
512
1
  {
513
1
    ListTablesRequestPB req;
514
1
    req.set_name_filter(kTableName);
515
1
    DoListTables(req, &tables);
516
1
    ASSERT_EQ(1, tables.tables_size());
517
1
    ASSERT_EQ(kTableName, tables.tables(0).name());
518
1
  }
519
520
1
  {
521
1
    ListTablesRequestPB req;
522
1
    req.set_name_filter("btes");
523
1
    DoListTables(req, &tables);
524
1
    ASSERT_EQ(1, tables.tables_size());
525
1
    ASSERT_EQ(kOtherTableName, tables.tables(0).name());
526
1
  }
527
528
1
  {
529
1
    ListTablesRequestPB req;
530
1
    req.set_name_filter("randomname");
531
1
    DoListTables(req, &tables);
532
1
    ASSERT_EQ(0, tables.tables_size());
533
1
  }
534
535
1
  {
536
1
    ListTablesRequestPB req;
537
1
    req.set_name_filter("peer");
538
1
    DoListTables(req, &tables);
539
1
    ASSERT_EQ(1, tables.tables_size());
540
1
    ASSERT_EQ(kSystemPeersTableName, tables.tables(0).name());
541
1
  }
542
543
1
  {
544
1
    ListTablesRequestPB req;
545
1
    req.add_relation_type_filter(USER_TABLE_RELATION);
546
1
    DoListTables(req, &tables);
547
1
    ASSERT_EQ(2, tables.tables_size());
548
1
  }
549
550
1
  {
551
1
    ListTablesRequestPB req;
552
1
    req.add_relation_type_filter(INDEX_TABLE_RELATION);
553
1
    DoListTables(req, &tables);
554
1
    ASSERT_EQ(0, tables.tables_size());
555
1
  }
556
557
1
  {
558
1
    ListTablesRequestPB req;
559
1
    req.add_relation_type_filter(SYSTEM_TABLE_RELATION);
560
1
    DoListTables(req, &tables);
561
1
    ASSERT_EQ(kNumSystemTables, tables.tables_size());
562
1
  }
563
564
1
  {
565
1
    ListTablesRequestPB req;
566
1
    req.add_relation_type_filter(SYSTEM_TABLE_RELATION);
567
1
    req.add_relation_type_filter(USER_TABLE_RELATION);
568
1
    DoListTables(req, &tables);
569
1
    ASSERT_EQ(kNumSystemTables + 2, tables.tables_size());
570
1
  }
571
1
}
572
573
1
TEST_F(MasterTest, TestCatalogHasBlockCache) {
574
  // Restart mini_master
575
1
  ASSERT_OK(mini_master_->Restart());
576
1
  ASSERT_OK(mini_master_->master()->WaitUntilCatalogManagerIsLeaderAndReadyForTests());
577
578
  // Check prometheus metrics via webserver to verify block_cache metrics exist
579
1
  string addr = AsString(mini_master_->bound_http_addr());
580
1
  string url = strings::Substitute("http://$0/prometheus-metrics", AsString(addr));
581
1
  EasyCurl curl;
582
1
  faststring buf;
583
584
1
  ASSERT_OK(curl.FetchURL(url, &buf));
585
1
  ASSERT_STR_CONTAINS(buf.ToString(), "block_cache_misses");
586
1
  ASSERT_STR_CONTAINS(buf.ToString(), "block_cache_hits");
587
588
  // Check block cache metrics directly and verify
589
  // that the counters are greater than 0
590
1
  const auto metric_map = mini_master_->master()->metric_entity()->UnsafeMetricsMapForTests();
591
592
1
  scoped_refptr<Counter> cache_misses_counter = down_cast<Counter *>(
593
1
      FindOrDie(metric_map,
594
1
                &METRIC_block_cache_misses).get());
595
1
  scoped_refptr<Counter> cache_hits_counter = down_cast<Counter *>(
596
1
      FindOrDie(metric_map,
597
1
                &METRIC_block_cache_hits).get());
598
599
1
  ASSERT_GT(cache_misses_counter->value(), 0);
600
1
  ASSERT_GT(cache_hits_counter->value(), 0);
601
1
}
602
603
1
TEST_F(MasterTest, TestTablegroups) {
604
  // Tablegroup ID must be 32 characters in length
605
1
  const char *kTablegroupId = "test_tablegroup00000000000000000";
606
1
  const char *kTableName = "test_table";
607
1
  const Schema kTableSchema({ ColumnSchema("key", INT32) }, 1);
608
1
  const NamespaceName ns_name = "test_tablegroup_ns";
609
610
  // Create a new namespace.
611
1
  NamespaceId ns_id;
612
1
  ListNamespacesResponsePB namespaces;
613
1
  {
614
1
    CreateNamespaceResponsePB resp;
615
1
    ASSERT_OK(CreateNamespace(ns_name, YQL_DATABASE_PGSQL, &resp));
616
1
    ns_id = resp.id();
617
1
  }
618
1
  {
619
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
620
1
    ASSERT_EQ(2 + kNumSystemNamespaces, namespaces.namespaces_size());
621
1
    CheckNamespaces(
622
1
        {
623
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES,
624
1
            std::make_tuple(ns_name, ns_id)
625
1
        }, namespaces);
626
1
  }
627
628
1
  SetAtomicFlag(true, &FLAGS_TEST_tablegroup_master_only);
629
  // Create tablegroup and ensure it exists in catalog manager maps.
630
1
  ASSERT_OK(CreateTablegroup(kTablegroupId, ns_id, ns_name, "" /* tablespace_id */));
631
1
  SetAtomicFlag(false, &FLAGS_TEST_tablegroup_master_only);
632
633
1
  ListTablegroupsRequestPB req;
634
1
  ListTablegroupsResponsePB resp;
635
1
  req.set_namespace_id(ns_id);
636
1
  ASSERT_NO_FATALS(DoListTablegroups(req, &resp));
637
638
1
  bool tablegroup_found = false;
639
1
  for (auto& tg : *resp.mutable_tablegroups()) {
640
1
    if (tg.id().compare(kTablegroupId) == 0) {
641
1
      tablegroup_found = true;
642
1
    }
643
1
  }
644
1
  ASSERT_TRUE(tablegroup_found);
645
646
  // Restart the master, verify the tablegroup still shows up
647
1
  ASSERT_OK(mini_master_->Restart());
648
1
  ASSERT_OK(mini_master_->master()->WaitUntilCatalogManagerIsLeaderAndReadyForTests());
649
650
1
  ListTablegroupsResponsePB new_resp;
651
1
  ASSERT_NO_FATALS(DoListTablegroups(req, &new_resp));
652
653
1
  tablegroup_found = false;
654
1
  for (auto& tg : *new_resp.mutable_tablegroups()) {
655
1
    if (tg.id().compare(kTablegroupId) == 0) {
656
1
      tablegroup_found = true;
657
1
    }
658
1
  }
659
1
  ASSERT_TRUE(tablegroup_found);
660
661
  // Now ensure that a table can be created in the tablegroup.
662
1
  ASSERT_OK(CreateTablegroupTable(ns_id, kTableName, kTablegroupId, kTableSchema));
663
664
  // Delete the tablegroup
665
1
  ASSERT_OK(DeleteTablegroup(kTablegroupId, ns_id));
666
1
}
667
668
// Regression test for KUDU-253/KUDU-592: crash if the schema passed to CreateTable
669
// is invalid.
670
1
TEST_F(MasterTest, TestCreateTableInvalidSchema) {
671
1
  CreateTableRequestPB req;
672
1
  CreateTableResponsePB resp;
673
674
1
  req.set_name("table");
675
1
  req.mutable_namespace_()->set_name(default_namespace_name);
676
3
  for (int i = 0; i < 2; i++) {
677
2
    ColumnSchemaPB* col = req.mutable_schema()->add_columns();
678
2
    col->set_name("col");
679
2
    QLType::Create(INT32)->ToQLTypePB(col->mutable_type());
680
2
    col->set_is_key(true);
681
2
  }
682
683
1
  ASSERT_OK(proxy_ddl_->CreateTable(req, &resp, ResetAndGetController()));
684
1
  SCOPED_TRACE(resp.DebugString());
685
1
  ASSERT_TRUE(resp.has_error());
686
1
  ASSERT_EQ(AppStatusPB::INVALID_ARGUMENT, resp.error().status().code());
687
1
  ASSERT_EQ("Duplicate column name: col", resp.error().status().message());
688
1
}
689
690
1
TEST_F(MasterTest, TestTabletsDeletedWhenTableInDeletingState) {
691
1
  FLAGS_TEST_simulate_crash_after_table_marked_deleting = true;
692
1
  const char *kTableName = "testtb";
693
1
  const Schema kTableSchema({ ColumnSchema("key", INT32)},
694
1
                            1);
695
696
1
  ASSERT_OK(CreateTable(kTableName, kTableSchema));
697
1
  vector<TabletId> tablet_ids;
698
1
  {
699
1
    CatalogManager::SharedLock lock(mini_master_->catalog_manager_impl().mutex_);
700
25
    for (auto elem : *mini_master_->catalog_manager_impl().tablet_map_) {
701
25
      auto tablet = elem.second;
702
25
      if (tablet->table()->name() == kTableName) {
703
8
        tablet_ids.push_back(elem.first);
704
8
      }
705
25
    }
706
1
  }
707
708
  // Delete the table
709
1
  TableId id;
710
1
  ASSERT_OK(DeleteTable(default_namespace_name, kTableName, &id));
711
712
  // Restart the master to force a reload of the tablets.
713
1
  ASSERT_OK(mini_master_->Restart());
714
1
  ASSERT_OK(mini_master_->master()->WaitUntilCatalogManagerIsLeaderAndReadyForTests());
715
716
  // Verify that the test table's tablets are in the DELETED state.
717
1
  {
718
1
    CatalogManager::SharedLock lock(mini_master_->catalog_manager_impl().mutex_);
719
8
    for (const auto& tablet_id : tablet_ids) {
720
8
      auto iter = mini_master_->catalog_manager_impl().tablet_map_->find(tablet_id);
721
8
      ASSERT_NE(iter, mini_master_->catalog_manager_impl().tablet_map_->end());
722
8
      auto l = iter->second->LockForRead();
723
8
      ASSERT_EQ(l->pb.state(), SysTabletsEntryPB::DELETED);
724
8
    }
725
1
  }
726
1
}
727
728
// Regression test for KUDU-253/KUDU-592: crash if the GetTableLocations RPC call is
729
// invalid.
730
1
TEST_F(MasterTest, TestInvalidGetTableLocations) {
731
1
  const TableName kTableName = "test";
732
1
  Schema schema({ ColumnSchema("key", INT32) }, 1);
733
1
  ASSERT_OK(CreateTable(kTableName, schema));
734
1
  {
735
1
    GetTableLocationsRequestPB req;
736
1
    GetTableLocationsResponsePB resp;
737
1
    req.mutable_table()->set_table_name(kTableName);
738
    // Set the "start" key greater than the "end" key.
739
1
    req.set_partition_key_start("zzzz");
740
1
    req.set_partition_key_end("aaaa");
741
1
    ASSERT_OK(proxy_client_->GetTableLocations(req, &resp, ResetAndGetController()));
742
1
    SCOPED_TRACE(resp.DebugString());
743
1
    ASSERT_TRUE(resp.has_error());
744
1
    ASSERT_EQ(AppStatusPB::INVALID_ARGUMENT, resp.error().status().code());
745
1
    ASSERT_EQ("start partition key is greater than the end partition key",
746
1
              resp.error().status().message());
747
1
  }
748
1
}
749
750
1
TEST_F(MasterTest, TestInvalidPlacementInfo) {
751
1
  const TableName kTableName = "test";
752
1
  Schema schema({ColumnSchema("key", INT32)}, 1);
753
1
  GetMasterClusterConfigRequestPB config_req;
754
1
  GetMasterClusterConfigResponsePB config_resp;
755
1
  ASSERT_OK(proxy_cluster_->GetMasterClusterConfig(
756
1
      config_req, &config_resp, ResetAndGetController()));
757
1
  ASSERT_FALSE(config_resp.has_error());
758
1
  ASSERT_TRUE(config_resp.has_cluster_config());
759
1
  auto cluster_config = config_resp.cluster_config();
760
761
1
  CreateTableRequestPB req;
762
763
  // Fail due to not cloud_info.
764
1
  auto* live_replicas = cluster_config.mutable_replication_info()->mutable_live_replicas();
765
1
  live_replicas->set_num_replicas(5);
766
1
  auto* pb = live_replicas->add_placement_blocks();
767
1
  UpdateMasterClusterConfig(&cluster_config);
768
1
  Status s = DoCreateTable(kTableName, schema, &req);
769
1
  ASSERT_TRUE(s.IsInvalidArgument());
770
771
  // Fail due to min_num_replicas being more than num_replicas.
772
1
  auto* cloud_info = pb->mutable_cloud_info();
773
1
  pb->set_min_num_replicas(live_replicas->num_replicas() + 1);
774
1
  UpdateMasterClusterConfig(&cluster_config);
775
1
  s = DoCreateTable(kTableName, schema, &req);
776
1
  ASSERT_TRUE(s.IsInvalidArgument());
777
778
  // Fail because there are no TServers matching the given placement policy.
779
1
  pb->set_min_num_replicas(live_replicas->num_replicas());
780
1
  cloud_info->set_placement_cloud("fail");
781
1
  UpdateMasterClusterConfig(&cluster_config);
782
1
  s = DoCreateTable(kTableName, schema, &req);
783
1
  ASSERT_TRUE(s.IsInvalidArgument());
784
1
}
785
786
1
TEST_F(MasterTest, TestNamespaces) {
787
1
  ListNamespacesResponsePB namespaces;
788
789
  // Check default namespace.
790
1
  {
791
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
792
    // Including system namespace.
793
1
    ASSERT_EQ(1 + kNumSystemNamespaces, namespaces.namespaces_size());
794
1
    CheckNamespaces(
795
1
        {
796
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES
797
1
        }, namespaces);
798
1
  }
799
800
  // Create a new namespace.
801
1
  const NamespaceName other_ns_name = "testns";
802
1
  NamespaceId other_ns_id;
803
1
  {
804
1
    CreateNamespaceResponsePB resp;
805
1
    ASSERT_OK(CreateNamespace(other_ns_name, &resp));
806
1
    other_ns_id = resp.id();
807
1
  }
808
1
  {
809
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
810
    // Including system namespace.
811
1
    ASSERT_EQ(2 + kNumSystemNamespaces, namespaces.namespaces_size());
812
1
    CheckNamespaces(
813
1
        {
814
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES,
815
1
            std::make_tuple(other_ns_name, other_ns_id),
816
1
        }, namespaces);
817
1
  }
818
819
  // Try to create the existing namespace twice.
820
1
  {
821
1
    CreateNamespaceResponsePB resp;
822
1
    const Status s = CreateNamespace(other_ns_name, &resp);
823
2
    ASSERT_TRUE(s.IsAlreadyPresent()) << s.ToString();
824
1
    ASSERT_STR_CONTAINS(s.ToString(),
825
1
        Substitute("Keyspace '$0' already exists", other_ns_name));
826
1
  }
827
1
  {
828
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
829
    // Including system namespace.
830
1
    ASSERT_EQ(2 + kNumSystemNamespaces, namespaces.namespaces_size());
831
1
    CheckNamespaces(
832
1
        {
833
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES,
834
1
            std::make_tuple(other_ns_name, other_ns_id),
835
1
        }, namespaces);
836
1
  }
837
838
  // Delete the namespace (by ID).
839
1
  {
840
1
    DeleteNamespaceRequestPB req;
841
1
    DeleteNamespaceResponsePB resp;
842
1
    req.mutable_namespace_()->set_id(other_ns_id);
843
1
    ASSERT_OK(proxy_ddl_->DeleteNamespace(req, &resp, ResetAndGetController()));
844
1
    SCOPED_TRACE(resp.DebugString());
845
1
    ASSERT_FALSE(resp.has_error());
846
1
  }
847
1
  {
848
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
849
    // Including system namespace.
850
1
    ASSERT_EQ(1 + kNumSystemNamespaces, namespaces.namespaces_size());
851
1
    CheckNamespaces(
852
1
        {
853
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES
854
1
        }, namespaces);
855
1
  }
856
857
  // Re-create the namespace once again.
858
1
  {
859
1
    CreateNamespaceResponsePB resp;
860
1
    ASSERT_OK(CreateNamespace(other_ns_name, &resp));
861
1
    other_ns_id = resp.id();
862
1
  }
863
1
  {
864
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
865
    // Including system namespace.
866
1
    ASSERT_EQ(2 + kNumSystemNamespaces, namespaces.namespaces_size());
867
1
    CheckNamespaces(
868
1
        {
869
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES,
870
1
            std::make_tuple(other_ns_name, other_ns_id),
871
1
        }, namespaces);
872
1
  }
873
874
  // Delete the namespace (by NAME).
875
1
  {
876
1
    DeleteNamespaceRequestPB req;
877
1
    DeleteNamespaceResponsePB resp;
878
1
    req.mutable_namespace_()->set_name(other_ns_name);
879
1
    ASSERT_OK(proxy_ddl_->DeleteNamespace(req, &resp, ResetAndGetController()));
880
1
    SCOPED_TRACE(resp.DebugString());
881
1
    ASSERT_FALSE(resp.has_error());
882
1
  }
883
1
  {
884
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
885
    // Including system namespace.
886
1
    ASSERT_EQ(1 + kNumSystemNamespaces, namespaces.namespaces_size());
887
1
    CheckNamespaces(
888
1
        {
889
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES
890
1
        }, namespaces);
891
1
  }
892
893
  // Try to create the 'default' namespace.
894
1
  {
895
1
    CreateNamespaceResponsePB resp;
896
1
    const Status s = CreateNamespace(default_namespace_name, &resp);
897
2
    ASSERT_TRUE(s.IsAlreadyPresent()) << s.ToString();
898
1
    ASSERT_STR_CONTAINS(s.ToString(),
899
1
        Substitute("Keyspace '$0' already exists", default_namespace_name));
900
1
  }
901
1
  {
902
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
903
    // Including system namespace.
904
1
    ASSERT_EQ(1 + kNumSystemNamespaces, namespaces.namespaces_size());
905
1
    CheckNamespaces(
906
1
        {
907
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES
908
1
        }, namespaces);
909
1
  }
910
911
  // Try to delete a non-existing namespace - by NAME.
912
1
  {
913
1
    DeleteNamespaceRequestPB req;
914
1
    DeleteNamespaceResponsePB resp;
915
916
1
    req.mutable_namespace_()->set_name("nonexistingns");
917
1
    ASSERT_OK(proxy_ddl_->DeleteNamespace(req, &resp, ResetAndGetController()));
918
1
    SCOPED_TRACE(resp.DebugString());
919
1
    ASSERT_TRUE(resp.has_error());
920
1
    ASSERT_EQ(resp.error().code(), MasterErrorPB::NAMESPACE_NOT_FOUND);
921
1
    ASSERT_EQ(resp.error().status().code(), AppStatusPB::NOT_FOUND);
922
1
    ASSERT_STR_CONTAINS(resp.error().status().ShortDebugString(), "Keyspace name not found");
923
1
  }
924
1
  {
925
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
926
    // Including system namespace.
927
1
    ASSERT_EQ(1 + kNumSystemNamespaces, namespaces.namespaces_size());
928
1
    CheckNamespaces(
929
1
        {
930
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES
931
1
        }, namespaces);
932
1
  }
933
1
}
934
935
1
TEST_F(MasterTest, TestNamespaceSeparation) {
936
1
  ListNamespacesResponsePB namespaces;
937
938
  // Check default namespace.
939
1
  {
940
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
941
    // Including system namespace.
942
1
    ASSERT_EQ(1 + kNumSystemNamespaces, namespaces.namespaces_size());
943
1
    CheckNamespaces(
944
1
        {
945
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES
946
1
        }, namespaces);
947
1
  }
948
949
  // Create a new namespace for each of YCQL, YSQL and YEDIS database types.
950
1
  CreateNamespaceResponsePB resp;
951
1
  ASSERT_OK(CreateNamespace("test_cql", YQLDatabase::YQL_DATABASE_CQL, &resp));
952
1
  const NamespaceId cql_ns_id = resp.id();
953
1
  ASSERT_OK(CreateNamespace("test_pgsql", YQLDatabase::YQL_DATABASE_PGSQL, &resp));
954
1
  const NamespaceId pgsql_ns_id = resp.id();
955
1
  ASSERT_OK(CreateNamespace("test_redis", YQLDatabase::YQL_DATABASE_REDIS, &resp));
956
1
  const NamespaceId redis_ns_id = resp.id();
957
958
  // List all namespaces and by each database type.
959
1
  ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
960
1
  ASSERT_EQ(4 + kNumSystemNamespaces, namespaces.namespaces_size());
961
1
  CheckNamespaces(
962
1
      {
963
1
        EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES,
964
1
        std::make_tuple("test_cql", cql_ns_id),
965
1
        std::make_tuple("test_pgsql", pgsql_ns_id),
966
1
        std::make_tuple("test_redis", redis_ns_id),
967
1
      }, namespaces);
968
969
1
  ASSERT_NO_FATALS(DoListAllNamespaces(YQLDatabase::YQL_DATABASE_CQL, &namespaces));
970
1
  ASSERT_EQ(2 + kNumSystemNamespaces, namespaces.namespaces_size());
971
1
  CheckNamespaces(
972
1
      {
973
        // Defalt and system namespaces are created in YCQL.
974
1
        EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES,
975
1
        std::make_tuple("test_cql", cql_ns_id),
976
1
      }, namespaces);
977
978
1
  ASSERT_NO_FATALS(DoListAllNamespaces(YQLDatabase::YQL_DATABASE_PGSQL, &namespaces));
979
1
  ASSERT_EQ(1, namespaces.namespaces_size());
980
1
  CheckNamespaces(
981
1
      {
982
1
        std::make_tuple("test_pgsql", pgsql_ns_id),
983
1
      }, namespaces);
984
985
1
  ASSERT_NO_FATALS(DoListAllNamespaces(YQLDatabase::YQL_DATABASE_REDIS, &namespaces));
986
1
  ASSERT_EQ(1, namespaces.namespaces_size());
987
1
  CheckNamespaces(
988
1
      {
989
1
        std::make_tuple("test_redis", redis_ns_id),
990
1
      }, namespaces);
991
1
}
992
993
1
TEST_F(MasterTest, TestDeletingNonEmptyNamespace) {
994
1
  ListNamespacesResponsePB namespaces;
995
996
  // Create a new namespace.
997
1
  const NamespaceName other_ns_name = "testns";
998
1
  NamespaceId other_ns_id;
999
1
  const NamespaceName other_ns_pgsql_name = "testns_pgsql";
1000
1
  NamespaceId other_ns_pgsql_id;
1001
1
  {
1002
1
    CreateNamespaceResponsePB resp;
1003
1
    ASSERT_OK(CreateNamespace(other_ns_name, &resp));
1004
1
    other_ns_id = resp.id();
1005
1
  }
1006
1
  {
1007
1
    CreateNamespaceResponsePB resp;
1008
1
    ASSERT_OK(CreateNamespace(other_ns_pgsql_name, YQLDatabase::YQL_DATABASE_PGSQL, &resp));
1009
1
    other_ns_pgsql_id = resp.id();
1010
1
  }
1011
1
  {
1012
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
1013
1
    ASSERT_EQ(3 + kNumSystemNamespaces, namespaces.namespaces_size());
1014
1
    CheckNamespaces(
1015
1
        {
1016
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES,
1017
1
            std::make_tuple(other_ns_name, other_ns_id),
1018
1
            std::make_tuple(other_ns_pgsql_name, other_ns_pgsql_id)
1019
1
        }, namespaces);
1020
1
  }
1021
1
  {
1022
1
    ASSERT_NO_FATALS(DoListAllNamespaces(YQLDatabase::YQL_DATABASE_PGSQL, &namespaces));
1023
1
    ASSERT_EQ(1, namespaces.namespaces_size());
1024
1
    CheckNamespaces(
1025
1
        {
1026
1
            std::make_tuple(other_ns_pgsql_name, other_ns_pgsql_id)
1027
1
        }, namespaces);
1028
1
  }
1029
1030
  // Create a table.
1031
1
  const TableName kTableName = "testtb";
1032
1
  const TableName kTableNamePgsql = "testtb_pgsql";
1033
1
  const Schema kTableSchema({ ColumnSchema("key", INT32) }, 1);
1034
1035
1
  ASSERT_OK(CreateTable(other_ns_name, kTableName, kTableSchema));
1036
1
  ASSERT_OK(CreatePgsqlTable(other_ns_pgsql_id, kTableNamePgsql + "_1", kTableSchema));
1037
1
  ASSERT_OK(CreatePgsqlTable(other_ns_pgsql_id, kTableNamePgsql + "_2", kTableSchema));
1038
1039
1
  {
1040
1
    ListTablesResponsePB tables;
1041
1
    ASSERT_NO_FATALS(DoListAllTables(&tables));
1042
1
    ASSERT_EQ(3 + kNumSystemTables, tables.tables_size());
1043
1
    CheckTables(
1044
1
        {
1045
1
            std::make_tuple(kTableName, other_ns_name, other_ns_id, USER_TABLE_RELATION),
1046
1
            std::make_tuple(kTableNamePgsql + "_1", other_ns_pgsql_name, other_ns_pgsql_id,
1047
1
                USER_TABLE_RELATION),
1048
1
            std::make_tuple(kTableNamePgsql + "_2", other_ns_pgsql_name, other_ns_pgsql_id,
1049
1
                USER_TABLE_RELATION),
1050
1
            EXPECTED_SYSTEM_TABLES
1051
1
        }, tables);
1052
1
  }
1053
1054
  // You should be able to successfully delete a non-empty PGSQL Database - by ID only
1055
1
  {
1056
1
    DeleteNamespaceRequestPB req;
1057
1
    DeleteNamespaceResponsePB resp;
1058
1
    req.set_database_type(YQLDatabase::YQL_DATABASE_PGSQL);
1059
1
    req.mutable_namespace_()->set_id(other_ns_pgsql_id);
1060
1
    ASSERT_OK(proxy_ddl_->DeleteNamespace(req, &resp, ResetAndGetController()));
1061
1
    SCOPED_TRACE(resp.DebugString());
1062
1
    ASSERT_FALSE(resp.has_error());
1063
1064
    // Must wait for IsDeleteNamespaceDone with PGSQL Namespaces.
1065
1
    IsDeleteNamespaceDoneRequestPB del_req;
1066
1
    del_req.mutable_namespace_()->set_id(other_ns_pgsql_id);
1067
1
    del_req.mutable_namespace_()->set_database_type(YQLDatabase::YQL_DATABASE_PGSQL);
1068
1
    ASSERT_OK(DeleteNamespaceWait(del_req));
1069
1
  }
1070
1
  {
1071
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
1072
1
    ASSERT_EQ(2 + kNumSystemNamespaces, namespaces.namespaces_size());
1073
1
    CheckNamespaces(
1074
1
        {
1075
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES,
1076
1
            std::make_tuple(other_ns_name, other_ns_id)
1077
1
        }, namespaces);
1078
1
  }
1079
1
  {
1080
    // verify that the table for that database also went away
1081
1
    ListTablesResponsePB tables;
1082
1
    ASSERT_NO_FATALS(DoListAllTables(&tables));
1083
1
    ASSERT_EQ(1 + kNumSystemTables, tables.tables_size());
1084
1
    CheckTables(
1085
1
        {
1086
1
            std::make_tuple(kTableName, other_ns_name, other_ns_id, USER_TABLE_RELATION),
1087
1
            EXPECTED_SYSTEM_TABLES
1088
1
        }, tables);
1089
1
  }
1090
1091
  // Try to delete the non-empty namespace - by NAME.
1092
1
  {
1093
1
    DeleteNamespaceRequestPB req;
1094
1
    DeleteNamespaceResponsePB resp;
1095
1096
1
    req.mutable_namespace_()->set_name(other_ns_name);
1097
1
    ASSERT_OK(proxy_ddl_->DeleteNamespace(req, &resp, ResetAndGetController()));
1098
1
    SCOPED_TRACE(resp.DebugString());
1099
1
    ASSERT_TRUE(resp.has_error());
1100
1
    ASSERT_EQ(resp.error().code(), MasterErrorPB::NAMESPACE_IS_NOT_EMPTY);
1101
1
    ASSERT_EQ(resp.error().status().code(), AppStatusPB::INVALID_ARGUMENT);
1102
1
    ASSERT_STR_CONTAINS(resp.error().status().ShortDebugString(),
1103
1
        "Cannot delete keyspace which has table: " + kTableName);
1104
1
  }
1105
1
  {
1106
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
1107
1
    ASSERT_EQ(2 + kNumSystemNamespaces, namespaces.namespaces_size());
1108
1
    CheckNamespaces(
1109
1
        {
1110
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES,
1111
1
            std::make_tuple(other_ns_name, other_ns_id),
1112
1
        }, namespaces);
1113
1
  }
1114
1115
  // Try to delete the non-empty namespace - by ID.
1116
1
  {
1117
1
    DeleteNamespaceRequestPB req;
1118
1
    DeleteNamespaceResponsePB resp;
1119
1120
1
    req.mutable_namespace_()->set_id(other_ns_id);
1121
1
    ASSERT_OK(proxy_ddl_->DeleteNamespace(req, &resp, ResetAndGetController()));
1122
1
    SCOPED_TRACE(resp.DebugString());
1123
1
    ASSERT_TRUE(resp.has_error());
1124
1
    ASSERT_EQ(resp.error().code(), MasterErrorPB::NAMESPACE_IS_NOT_EMPTY);
1125
1
    ASSERT_EQ(resp.error().status().code(), AppStatusPB::INVALID_ARGUMENT);
1126
1
    ASSERT_STR_CONTAINS(resp.error().status().ShortDebugString(),
1127
1
        "Cannot delete keyspace which has table: " + kTableName);
1128
1
  }
1129
1
  {
1130
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
1131
1
    ASSERT_EQ(2 + kNumSystemNamespaces, namespaces.namespaces_size());
1132
1
    CheckNamespaces(
1133
1
        {
1134
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES,
1135
1
            std::make_tuple(other_ns_name, other_ns_id),
1136
1
        }, namespaces);
1137
1
  }
1138
1139
  // Delete the table.
1140
1
  ASSERT_OK(DeleteTable(other_ns_name, kTableName));
1141
1142
  // List tables, should show only system table.
1143
1
  {
1144
1
    ListTablesResponsePB tables;
1145
1
    ASSERT_NO_FATALS(DoListAllTables(&tables));
1146
1
    ASSERT_EQ(kNumSystemTables, tables.tables_size());
1147
1
    CheckTables(
1148
1
        {
1149
1
            EXPECTED_SYSTEM_TABLES
1150
1
        }, tables);
1151
1
  }
1152
1153
  // Delete the namespace (by NAME).
1154
1
  {
1155
1
    DeleteNamespaceRequestPB req;
1156
1
    DeleteNamespaceResponsePB resp;
1157
1
    req.mutable_namespace_()->set_name(other_ns_name);
1158
1
    ASSERT_OK(proxy_ddl_->DeleteNamespace(req, &resp, ResetAndGetController()));
1159
1
    SCOPED_TRACE(resp.DebugString());
1160
1
    ASSERT_FALSE(resp.has_error());
1161
1
  }
1162
1
  {
1163
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
1164
1
    ASSERT_EQ(1 + kNumSystemNamespaces, namespaces.namespaces_size());
1165
1
    CheckNamespaces(
1166
1
        {
1167
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES
1168
1
        }, namespaces);
1169
1
  }
1170
1
}
1171
1172
1
TEST_F(MasterTest, TestTablesWithNamespace) {
1173
1
  const TableName kTableName = "testtb";
1174
1
  const Schema kTableSchema({ ColumnSchema("key", INT32) }, 1);
1175
1
  ListTablesResponsePB tables;
1176
1177
  // Create a table with default namespace.
1178
1
  ASSERT_OK(CreateTable(kTableName, kTableSchema));
1179
1180
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1181
1
  ASSERT_EQ(1 + kNumSystemTables, tables.tables_size());
1182
1
  CheckTables(
1183
1
      {
1184
1
          std::make_tuple(kTableName, default_namespace_name, default_namespace_id,
1185
1
              USER_TABLE_RELATION),
1186
1
          EXPECTED_SYSTEM_TABLES
1187
1
      }, tables);
1188
1189
  // Delete the table.
1190
1
  ASSERT_OK(DeleteTable(kTableName));
1191
1192
  // List tables, should show 1 table.
1193
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1194
1
  ASSERT_EQ(kNumSystemTables, tables.tables_size());
1195
1
  CheckTables(
1196
1
      {
1197
1
          EXPECTED_SYSTEM_TABLES
1198
1
      }, tables);
1199
1200
  // Create a table with the default namespace.
1201
1
  ASSERT_OK(CreateTable(default_namespace_name, kTableName, kTableSchema));
1202
1203
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1204
1
  ASSERT_EQ(1 + kNumSystemTables, tables.tables_size());
1205
1
  CheckTables(
1206
1
      {
1207
1
          std::make_tuple(kTableName, default_namespace_name, default_namespace_id,
1208
1
              USER_TABLE_RELATION),
1209
1
          EXPECTED_SYSTEM_TABLES
1210
1
      }, tables);
1211
1212
  // Delete the table.
1213
1
  ASSERT_OK(DeleteTable(default_namespace_name, kTableName));
1214
1215
  // List tables, should show 1 table.
1216
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1217
1
  ASSERT_EQ(kNumSystemTables, tables.tables_size());
1218
1
  CheckTables(
1219
1
      {
1220
1
          EXPECTED_SYSTEM_TABLES
1221
1
      }, tables);
1222
1223
  // Try to create a table with an unknown namespace.
1224
1
  {
1225
1
    Status s = CreateTable("nonexistingns", kTableName, kTableSchema);
1226
2
    ASSERT_TRUE(s.IsNotFound()) << s.ToString();
1227
1
    ASSERT_STR_CONTAINS(s.ToString(), "Keyspace name not found");
1228
1
  }
1229
1230
  // List tables, should show 1 table.
1231
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1232
1
  ASSERT_EQ(kNumSystemTables, tables.tables_size());
1233
1
  CheckTables(
1234
1
      {
1235
1
          EXPECTED_SYSTEM_TABLES
1236
1
      }, tables);
1237
1238
1
  const NamespaceName other_ns_name = "testns";
1239
1240
  // Create a new namespace.
1241
1
  NamespaceId other_ns_id;
1242
1
  ListNamespacesResponsePB namespaces;
1243
1
  {
1244
1
    CreateNamespaceResponsePB resp;
1245
1
    ASSERT_OK(CreateNamespace(other_ns_name, &resp));
1246
1
    other_ns_id = resp.id();
1247
1
  }
1248
1
  {
1249
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
1250
1
    ASSERT_EQ(2 + kNumSystemNamespaces, namespaces.namespaces_size());
1251
1
    CheckNamespaces(
1252
1
        {
1253
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES,
1254
1
            std::make_tuple(other_ns_name, other_ns_id),
1255
1
        }, namespaces);
1256
1
  }
1257
1258
  // Create a table with the defined new namespace.
1259
1
  ASSERT_OK(CreateTable(other_ns_name, kTableName, kTableSchema));
1260
1261
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1262
1
  ASSERT_EQ(1 + kNumSystemTables, tables.tables_size());
1263
1
  CheckTables(
1264
1
      {
1265
1
          std::make_tuple(kTableName, other_ns_name, other_ns_id, USER_TABLE_RELATION),
1266
1
          EXPECTED_SYSTEM_TABLES
1267
1
      }, tables);
1268
1269
  // Alter table: try to change the table namespace name into an invalid one.
1270
1
  {
1271
1
    AlterTableRequestPB req;
1272
1
    AlterTableResponsePB resp;
1273
1
    req.mutable_table()->set_table_name(kTableName);
1274
1
    req.mutable_table()->mutable_namespace_()->set_name(other_ns_name);
1275
1
    req.mutable_new_namespace()->set_name("nonexistingns");
1276
1
    ASSERT_OK(proxy_ddl_->AlterTable(req, &resp, ResetAndGetController()));
1277
1
    SCOPED_TRACE(resp.DebugString());
1278
1
    ASSERT_TRUE(resp.has_error());
1279
1
    ASSERT_EQ(resp.error().code(), MasterErrorPB::NAMESPACE_NOT_FOUND);
1280
1
    ASSERT_EQ(resp.error().status().code(), AppStatusPB::NOT_FOUND);
1281
1
    ASSERT_STR_CONTAINS(resp.error().status().ShortDebugString(), "Keyspace name not found");
1282
1
  }
1283
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1284
1
  ASSERT_EQ(1 + kNumSystemTables, tables.tables_size());
1285
1
  CheckTables(
1286
1
      {
1287
1
          std::make_tuple(kTableName, other_ns_name, other_ns_id, USER_TABLE_RELATION),
1288
1
          EXPECTED_SYSTEM_TABLES
1289
1
      }, tables);
1290
1291
  // Alter table: try to change the table namespace id into an invalid one.
1292
1
  {
1293
1
    AlterTableRequestPB req;
1294
1
    AlterTableResponsePB resp;
1295
1
    req.mutable_table()->set_table_name(kTableName);
1296
1
    req.mutable_table()->mutable_namespace_()->set_name(other_ns_name);
1297
1
    req.mutable_new_namespace()->set_id("deadbeafdeadbeafdeadbeafdeadbeaf");
1298
1
    ASSERT_OK(proxy_ddl_->AlterTable(req, &resp, ResetAndGetController()));
1299
1
    SCOPED_TRACE(resp.DebugString());
1300
1
    ASSERT_TRUE(resp.has_error());
1301
1
    ASSERT_EQ(resp.error().code(), MasterErrorPB::NAMESPACE_NOT_FOUND);
1302
1
    ASSERT_EQ(resp.error().status().code(), AppStatusPB::NOT_FOUND);
1303
1
    ASSERT_STR_CONTAINS(resp.error().status().ShortDebugString(), "Keyspace identifier not found");
1304
1
  }
1305
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1306
1
  ASSERT_EQ(1 + kNumSystemTables, tables.tables_size());
1307
1
  CheckTables(
1308
1
      {
1309
1
          std::make_tuple(kTableName, other_ns_name, other_ns_id, USER_TABLE_RELATION),
1310
1
          EXPECTED_SYSTEM_TABLES
1311
1
      }, tables);
1312
1313
  // Alter table: change namespace name into the default one.
1314
1
  {
1315
1
    AlterTableRequestPB req;
1316
1
    AlterTableResponsePB resp;
1317
1
    req.mutable_table()->set_table_name(kTableName);
1318
1
    req.mutable_table()->mutable_namespace_()->set_name(other_ns_name);
1319
1
    req.mutable_new_namespace()->set_name(default_namespace_name);
1320
1
    ASSERT_OK(proxy_ddl_->AlterTable(req, &resp, ResetAndGetController()));
1321
1
    SCOPED_TRACE(resp.DebugString());
1322
1
    ASSERT_FALSE(resp.has_error());
1323
1
  }
1324
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1325
1
  ASSERT_EQ(1 + kNumSystemTables, tables.tables_size());
1326
1
  CheckTables(
1327
1
      {
1328
1
          std::make_tuple(kTableName, default_namespace_name, default_namespace_id,
1329
1
              USER_TABLE_RELATION),
1330
1
          EXPECTED_SYSTEM_TABLES
1331
1
      }, tables);
1332
1333
  // Delete the table.
1334
1
  ASSERT_OK(DeleteTable(default_namespace_name, kTableName));
1335
1336
  // List tables, should show 1 table.
1337
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1338
1
  ASSERT_EQ(kNumSystemTables, tables.tables_size());
1339
1
  CheckTables(
1340
1
      {
1341
1
          EXPECTED_SYSTEM_TABLES
1342
1
      }, tables);
1343
1344
  // Delete the namespace (by NAME).
1345
1
  {
1346
1
    DeleteNamespaceRequestPB req;
1347
1
    DeleteNamespaceResponsePB resp;
1348
1
    req.mutable_namespace_()->set_name(other_ns_name);
1349
1
    ASSERT_OK(proxy_ddl_->DeleteNamespace(req, &resp, ResetAndGetController()));
1350
1
    SCOPED_TRACE(resp.DebugString());
1351
1
    ASSERT_FALSE(resp.has_error());
1352
1
  }
1353
1
  {
1354
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
1355
1
    ASSERT_EQ(1 + kNumSystemNamespaces, namespaces.namespaces_size());
1356
1
    CheckNamespaces(
1357
1
        {
1358
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES
1359
1
        }, namespaces);
1360
1
  }
1361
1
}
1362
1363
1
TEST_F(MasterTest, TestNamespaceCreateStates) {
1364
1
  NamespaceName test_name = "test_pgsql";
1365
1366
  // Don't allow the BG thread to process namespaces.
1367
1
  SetAtomicFlag(true, &FLAGS_TEST_hang_on_namespace_transition);
1368
1369
  // Create a new PGSQL namespace.
1370
1
  CreateNamespaceResponsePB resp;
1371
1
  NamespaceId nsid;
1372
1
  ASSERT_OK(CreateNamespaceAsync(test_name, YQLDatabase::YQL_DATABASE_PGSQL, &resp));
1373
1
  nsid = resp.id();
1374
1375
  // ListNamespaces should not yet show the Namespace, because it's in the PREPARING state.
1376
1
  ListNamespacesResponsePB namespaces;
1377
1
  ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
1378
1
  ASSERT_FALSE(FindNamespace(std::make_tuple(test_name, nsid), namespaces));
1379
1380
  // Test that Basic Access is not allowed to a Namespace while INITIALIZING.
1381
  // 1. CANNOT Create a Table on the namespace.
1382
1
  const Schema kTableSchema({ ColumnSchema("key", INT32) }, 1);
1383
1
  ASSERT_NOK(CreatePgsqlTable(nsid, "test_table", kTableSchema));
1384
  // 2. CANNOT Alter the namespace.
1385
1
  {
1386
1
    AlterNamespaceResponsePB alter_resp;
1387
1
    ASSERT_NOK(AlterNamespace(test_name, nsid, YQLDatabase::YQL_DATABASE_PGSQL,
1388
1
                              "new_" + test_name, &alter_resp));
1389
1
    ASSERT_TRUE(alter_resp.has_error());
1390
1
    ASSERT_EQ(alter_resp.error().code(), MasterErrorPB::IN_TRANSITION_CAN_RETRY);
1391
1
  }
1392
  // 3. CANNOT Delete the namespace.
1393
1
  {
1394
1
    DeleteNamespaceRequestPB req;
1395
1
    DeleteNamespaceResponsePB resp;
1396
1
    req.mutable_namespace_()->set_name(test_name);
1397
1
    req.mutable_namespace_()->set_database_type(YQLDatabase::YQL_DATABASE_PGSQL);
1398
1
    ASSERT_OK(proxy_ddl_->DeleteNamespace(req, &resp, ResetAndGetController()));
1399
1
    ASSERT_TRUE(resp.has_error());
1400
1
    ASSERT_EQ(resp.error().code(), MasterErrorPB::IN_TRANSITION_CAN_RETRY);
1401
1
  }
1402
1403
  // Finish Namespace create.
1404
1
  SetAtomicFlag(false, &FLAGS_TEST_hang_on_namespace_transition);
1405
1
  ASSERT_OK(CreateNamespaceWait(nsid, YQLDatabase::YQL_DATABASE_PGSQL));
1406
1407
  // Verify that Basic Access to a Namespace is now available.
1408
  // 1. Create a Table within the Schema.
1409
1
  ASSERT_OK(CreatePgsqlTable(nsid, "test_table", kTableSchema));
1410
  // 2. Alter the namespace.
1411
1
  {
1412
1
    AlterNamespaceResponsePB alter_resp;
1413
1
    ASSERT_OK(AlterNamespace(test_name, nsid, YQLDatabase::YQL_DATABASE_PGSQL,
1414
1
                             "new_" + test_name, &alter_resp) );
1415
1
    ASSERT_FALSE(alter_resp.has_error());
1416
1
  }
1417
  // 3. Delete the namespace.
1418
1
  {
1419
1
    SetAtomicFlag(true, &FLAGS_TEST_hang_on_namespace_transition);
1420
1421
1
    DeleteNamespaceRequestPB del_req;
1422
1
    DeleteNamespaceResponsePB del_resp;
1423
1
    del_req.mutable_namespace_()->set_name("new_" + test_name);
1424
1
    del_req.mutable_namespace_()->set_database_type(YQLDatabase::YQL_DATABASE_PGSQL);
1425
1
    ASSERT_OK(proxy_ddl_->DeleteNamespace(del_req, &del_resp, ResetAndGetController()));
1426
1
    ASSERT_FALSE(del_resp.has_error());
1427
1428
    // ListNamespaces should not show the Namespace, because it's in the DELETING state.
1429
1
    ListNamespacesResponsePB namespaces;
1430
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
1431
1
    ASSERT_FALSE(FindNamespace(std::make_tuple("new_" + test_name, nsid), namespaces));
1432
1433
    // Resume finishing both [1] the delete and [2] the create.
1434
1
    SetAtomicFlag(false, &FLAGS_TEST_hang_on_namespace_transition);
1435
1436
    // Verify the old namespace finishes deletion.
1437
1
    IsDeleteNamespaceDoneRequestPB is_del_req;
1438
1
    is_del_req.mutable_namespace_()->set_id(nsid);
1439
1
    is_del_req.mutable_namespace_()->set_database_type(YQLDatabase::YQL_DATABASE_PGSQL);
1440
1
    ASSERT_OK(DeleteNamespaceWait(is_del_req));
1441
1442
    // We should be able to create a namespace with the same NAME at this time.
1443
1
    ASSERT_OK(CreateNamespaceAsync("new_" + test_name, YQLDatabase::YQL_DATABASE_PGSQL, &resp));
1444
1
    ASSERT_OK(CreateNamespaceWait(resp.id(), YQLDatabase::YQL_DATABASE_PGSQL));
1445
1
  }
1446
1
}
1447
1448
1
TEST_F(MasterTest, TestNamespaceCreateFailure) {
1449
1
  NamespaceName test_name = "test_pgsql";
1450
1451
  // Don't allow the BG thread to process namespaces.
1452
1
  SetAtomicFlag(true, &FLAGS_TEST_hang_on_namespace_transition);
1453
1454
  // Create a new PGSQL namespace.
1455
1
  CreateNamespaceResponsePB resp;
1456
1
  NamespaceId nsid;
1457
1
  ASSERT_OK(CreateNamespaceAsync(test_name, YQLDatabase::YQL_DATABASE_PGSQL, &resp));
1458
1
  nsid = resp.id();
1459
1460
1
  {
1461
    // Public ListNamespaces should not show the Namespace, because it's in the PREPARING state.
1462
1
    ListNamespacesResponsePB namespace_pb;
1463
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespace_pb));
1464
1
    ASSERT_FALSE(FindNamespace(std::make_tuple(test_name, nsid), namespace_pb));
1465
1466
    // Internal search of CatalogManager should reveal it's state (debug UI uses this function).
1467
1
    std::vector<scoped_refptr<NamespaceInfo>> namespace_internal;
1468
1
    mini_master_->catalog_manager().GetAllNamespaces(&namespace_internal, false);
1469
1
    auto pos = std::find_if(namespace_internal.begin(), namespace_internal.end(),
1470
1
                 [&nsid](const scoped_refptr<NamespaceInfo>& ns) {
1471
1
                   return ns && ns->id() == nsid;
1472
1
                 });
1473
1
    ASSERT_NE(pos, namespace_internal.end());
1474
1
    ASSERT_EQ((*pos)->state(), SysNamespaceEntryPB::PREPARING);
1475
1
  }
1476
1477
  // Restart the master (Shutdown kills Namespace BG Thread).
1478
1
  ASSERT_OK(mini_master_->Restart());
1479
1
  ASSERT_OK(mini_master_->master()->WaitUntilCatalogManagerIsLeaderAndReadyForTests());
1480
1481
1
  {
1482
    // ListNamespaces should not show the Namespace on restart because it didn't finish.
1483
1
    ListNamespacesResponsePB namespaces;
1484
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
1485
1
    ASSERT_FALSE(FindNamespace(std::make_tuple(test_name, nsid), namespaces));
1486
1487
    // Internal search of CatalogManager should reveal it's DELETING to cleanup any partial apply.
1488
1
    std::vector<scoped_refptr<NamespaceInfo>> namespace_internal;
1489
1
    mini_master_->catalog_manager().GetAllNamespaces(&namespace_internal, false);
1490
1
    auto pos = std::find_if(namespace_internal.begin(), namespace_internal.end(),
1491
1
        [&nsid](const scoped_refptr<NamespaceInfo>& ns) {
1492
1
          return ns && ns->id() == nsid;
1493
1
        });
1494
1
    ASSERT_NE(pos, namespace_internal.end());
1495
1
    ASSERT_EQ((*pos)->state(), SysNamespaceEntryPB::DELETING);
1496
1
  }
1497
1498
  // Resume BG thread work and verify that the Namespace is eventually DELETED internally.
1499
1
  SetAtomicFlag(false, &FLAGS_TEST_hang_on_namespace_transition);
1500
1501
1
  ASSERT_OK(LoggedWaitFor([&]() -> Result<bool> {
1502
1
    std::vector<scoped_refptr<NamespaceInfo>> namespace_internal;
1503
1
    mini_master_->catalog_manager().GetAllNamespaces(&namespace_internal, false);
1504
1
    auto pos = std::find_if(namespace_internal.begin(), namespace_internal.end(),
1505
1
        [&nsid](const scoped_refptr<NamespaceInfo>& ns) {
1506
1
          return ns && ns->id() == nsid;
1507
1
        });
1508
1
    return pos != namespace_internal.end() && (*pos)->state() == SysNamespaceEntryPB::DELETED;
1509
1
  }, MonoDelta::FromSeconds(10), "Verify Namespace was DELETED"));
1510
1511
  // Restart the master #2, this round should completely remove the Namespace from memory.
1512
1
  ASSERT_OK(mini_master_->Restart());
1513
1
  ASSERT_OK(mini_master_->master()->WaitUntilCatalogManagerIsLeaderAndReadyForTests());
1514
1515
1
  ASSERT_OK(LoggedWaitFor([&]() -> Result<bool> {
1516
1
    std::vector<scoped_refptr<NamespaceInfo>> namespace_internal;
1517
1
    mini_master_->catalog_manager().GetAllNamespaces(&namespace_internal, false);
1518
1
    auto pos = std::find_if(namespace_internal.begin(), namespace_internal.end(),
1519
1
        [&nsid](const scoped_refptr<NamespaceInfo>& ns) {
1520
1
          return ns && ns->id() == nsid;
1521
1
        });
1522
1
    return pos == namespace_internal.end();
1523
1
  }, MonoDelta::FromSeconds(10), "Verify Namespace was completely removed"));
1524
1
}
1525
1526
class LoopedMasterTest : public MasterTest, public testing::WithParamInterface<int> {};
1527
INSTANTIATE_TEST_CASE_P(Loops, LoopedMasterTest, ::testing::Values(10));
1528
1529
1
TEST_P(LoopedMasterTest, TestNamespaceCreateSysCatalogFailure) {
1530
1
  NamespaceName test_name = "test_pgsql"; // Reuse name to find errors with delete cleanup.
1531
1
  CreateNamespaceResponsePB resp;
1532
1
  DeleteNamespaceRequestPB del_req;
1533
1
  del_req.mutable_namespace_()->set_name(test_name);
1534
1
  del_req.mutable_namespace_()->set_database_type(YQLDatabase::YQL_DATABASE_PGSQL);
1535
1
  IsDeleteNamespaceDoneRequestPB is_del_req;
1536
1
  is_del_req.mutable_namespace_()->set_name(test_name);
1537
1
  is_del_req.mutable_namespace_()->set_database_type(YQLDatabase::YQL_DATABASE_PGSQL);
1538
1539
1
  int failures = 0, created = 0, iter = 0;
1540
1
  int loops = GetParam();
1541
1
  LOG(INFO) << "Loops = " << loops;
1542
1543
  // Loop this to cover a spread of random failure situations.
1544
18
  while (failures < loops) {
1545
    // Inject Frequent failures into sys catalog commit.
1546
    // The below code should eventually succeed but require a lot of restarts.
1547
17
    FLAGS_TEST_sys_catalog_write_rejection_percentage = 50;
1548
1549
    // CreateNamespace : Inject IO Errors.
1550
17
    LOG(INFO) << "Iteration " << ++iter;
1551
17
    Status s = CreateNamespace(test_name, YQLDatabase::YQL_DATABASE_PGSQL, &resp);
1552
17
    if (!s.ok()) {
1553
10
      WARN_NOT_OK(s, "CreateNamespace with injected failures");
1554
10
      ++failures;
1555
10
    }
1556
1557
    // Turn off random failures.
1558
17
    FLAGS_TEST_sys_catalog_write_rejection_percentage = 0;
1559
1560
    // Internal search of CatalogManager should reveal whether it was partially created.
1561
17
    std::vector<scoped_refptr<NamespaceInfo>> namespace_internal;
1562
17
    mini_master_->catalog_manager().GetAllNamespaces(&namespace_internal, false);
1563
17
    auto was_internally_created = std::any_of(namespace_internal.begin(), namespace_internal.end(),
1564
96
        [&test_name](const scoped_refptr<NamespaceInfo>& ns) {
1565
96
          if (ns && ns->name() == test_name && ns->state() != SysNamespaceEntryPB::DELETED) {
1566
9
            LOG(INFO) << "Namespace " << ns->name() << " = " << ns->state();
1567
9
            return true;
1568
9
          }
1569
87
          return false;
1570
87
        });
1571
1572
17
    if (was_internally_created) {
1573
9
      ++created;
1574
      // Ensure we can delete the failed namespace.
1575
9
      DeleteNamespaceResponsePB del_resp;
1576
9
      ASSERT_OK(proxy_ddl_->DeleteNamespace(del_req, &del_resp, ResetAndGetController()));
1577
9
      if (del_resp.has_error()) {
1578
0
        LOG(INFO) << del_resp.error().DebugString();
1579
0
      }
1580
9
      ASSERT_FALSE(del_resp.has_error());
1581
9
      ASSERT_OK(DeleteNamespaceWait(is_del_req));
1582
9
    }
1583
17
  }
1584
1
  ASSERT_EQ(failures, loops);
1585
1
  LOG(INFO) << "created = " << created;
1586
1
}
1587
1588
1
TEST_P(LoopedMasterTest, TestNamespaceDeleteSysCatalogFailure) {
1589
1
  NamespaceName test_name = "test_pgsql";
1590
1
  CreateNamespaceResponsePB resp;
1591
1
  DeleteNamespaceRequestPB del_req;
1592
1
  DeleteNamespaceResponsePB del_resp;
1593
1
  del_req.mutable_namespace_()->set_name(test_name);
1594
1
  del_req.mutable_namespace_()->set_database_type(YQLDatabase::YQL_DATABASE_PGSQL);
1595
1
  IsDeleteNamespaceDoneRequestPB is_del_req;
1596
1
  is_del_req.mutable_namespace_()->set_name(test_name);
1597
1
  is_del_req.mutable_namespace_()->set_database_type(YQLDatabase::YQL_DATABASE_PGSQL);
1598
1
  int failures = 0, iter = 0;
1599
1
  int loops = GetParam();
1600
1
  LOG(INFO) << "Loops = " << loops;
1601
1602
// Loop this to cover a spread of random failure situations.
1603
11
  while (failures < loops) {
1604
    // CreateNamespace to setup test
1605
10
    CreateNamespaceResponsePB resp;
1606
10
    NamespaceId nsid;
1607
10
    ASSERT_OK(CreateNamespaceAsync(test_name, YQLDatabase::YQL_DATABASE_PGSQL, &resp));
1608
10
    nsid = resp.id();
1609
1610
    // The below code should eventually succeed but require a lot of restarts.
1611
10
    FLAGS_TEST_sys_catalog_write_rejection_percentage = 50;
1612
1613
    // DeleteNamespace : Inject IO Errors.
1614
10
    LOG(INFO) << "Iteration " << ++iter;
1615
10
    bool delete_failed = false;
1616
1617
10
    ASSERT_OK(proxy_ddl_->DeleteNamespace(del_req, &del_resp, ResetAndGetController()));
1618
1619
10
    delete_failed = del_resp.has_error();
1620
10
    if (del_resp.has_error()) {
1621
5
      LOG(INFO) << "Expected failure: " << del_resp.error().DebugString();
1622
5
    }
1623
1624
10
    if (!del_resp.has_error()) {
1625
5
      Status s = DeleteNamespaceWait(is_del_req);
1626
10
      ASSERT_FALSE(s.IsTimedOut()) << "Unexpected timeout: " << s;
1627
5
      WARN_NOT_OK(s, "Expected failure");
1628
5
      delete_failed = !s.ok();
1629
5
    }
1630
1631
    // Turn off random failures.
1632
10
    FLAGS_TEST_sys_catalog_write_rejection_percentage = 0;
1633
1634
10
    if (delete_failed) {
1635
10
      ++failures;
1636
10
      LOG(INFO) << "Next Delete should succeed";
1637
1638
      // If the namespace delete fails, Ensure that we can restart the delete and it succeeds.
1639
10
      ASSERT_OK(proxy_ddl_->DeleteNamespace(del_req, &del_resp, ResetAndGetController()));
1640
10
      ASSERT_FALSE(del_resp.has_error());
1641
10
      ASSERT_OK(DeleteNamespaceWait(is_del_req));
1642
10
    }
1643
10
  }
1644
1
  ASSERT_EQ(failures, loops);
1645
1
}
1646
1647
1
TEST_F(MasterTest, TestFullTableName) {
1648
1
  const TableName kTableName = "testtb";
1649
1
  const Schema kTableSchema({ ColumnSchema("key", INT32) }, 1);
1650
1
  ListTablesResponsePB tables;
1651
1652
  // Create a table with the default namespace.
1653
1
  ASSERT_OK(CreateTable(default_namespace_name, kTableName, kTableSchema));
1654
1655
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1656
1
  ASSERT_EQ(1 + kNumSystemTables, tables.tables_size());
1657
1
  CheckTables(
1658
1
      {
1659
1
          std::make_tuple(kTableName, default_namespace_name, default_namespace_id,
1660
1
              USER_TABLE_RELATION),
1661
1
          EXPECTED_SYSTEM_TABLES
1662
1
      }, tables);
1663
1664
1
  const NamespaceName other_ns_name = "testns";
1665
1666
  // Create a new namespace.
1667
1
  NamespaceId other_ns_id;
1668
1
  ListNamespacesResponsePB namespaces;
1669
1
  {
1670
1
    CreateNamespaceResponsePB resp;
1671
1
    ASSERT_OK(CreateNamespace(other_ns_name, &resp));
1672
1
    other_ns_id = resp.id();
1673
1
  }
1674
1
  {
1675
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
1676
1
    ASSERT_EQ(2 + kNumSystemNamespaces, namespaces.namespaces_size());
1677
1
    CheckNamespaces(
1678
1
        {
1679
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES,
1680
1
            std::make_tuple(other_ns_name, other_ns_id)
1681
1
        }, namespaces);
1682
1
  }
1683
1684
  // Create a table with the defined new namespace.
1685
1
  ASSERT_OK(CreateTable(other_ns_name, kTableName, kTableSchema));
1686
1687
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1688
1
  ASSERT_EQ(2 + kNumSystemTables, tables.tables_size());
1689
1
  CheckTables(
1690
1
      {
1691
1
          std::make_tuple(kTableName, default_namespace_name, default_namespace_id,
1692
1
              USER_TABLE_RELATION),
1693
1
          std::make_tuple(kTableName, other_ns_name, other_ns_id, USER_TABLE_RELATION),
1694
1
          EXPECTED_SYSTEM_TABLES
1695
1
      }, tables);
1696
1697
  // Test ListTables() for one particular namespace.
1698
  // There are 2 tables now: 'default_namespace::testtb' and 'testns::testtb'.
1699
1
  ASSERT_NO_FATALS(DoListAllTables(&tables, default_namespace_name));
1700
1
  ASSERT_EQ(1, tables.tables_size());
1701
1
  CheckTables(
1702
1
      {
1703
1
          std::make_tuple(kTableName, default_namespace_name, default_namespace_id,
1704
1
              USER_TABLE_RELATION),
1705
1
      }, tables);
1706
1707
1
  ASSERT_NO_FATALS(DoListAllTables(&tables, other_ns_name));
1708
1
  ASSERT_EQ(1, tables.tables_size());
1709
1
  CheckTables(
1710
1
      {
1711
1
          std::make_tuple(kTableName, other_ns_name, other_ns_id, USER_TABLE_RELATION)
1712
1
      }, tables);
1713
1714
  // Try to alter table: change namespace name into the default one.
1715
  // Try to change 'testns::testtb' into 'default_namespace::testtb', but the target table exists,
1716
  // so it must fail.
1717
1
  {
1718
1
    AlterTableRequestPB req;
1719
1
    AlterTableResponsePB resp;
1720
1
    req.mutable_table()->set_table_name(kTableName);
1721
1
    req.mutable_table()->mutable_namespace_()->set_name(other_ns_name);
1722
1
    req.mutable_new_namespace()->set_name(default_namespace_name);
1723
1
    ASSERT_OK(proxy_ddl_->AlterTable(req, &resp, ResetAndGetController()));
1724
1
    SCOPED_TRACE(resp.DebugString());
1725
1
    ASSERT_TRUE(resp.has_error());
1726
1
    ASSERT_EQ(resp.error().code(), MasterErrorPB::OBJECT_ALREADY_PRESENT);
1727
1
    ASSERT_EQ(resp.error().status().code(), AppStatusPB::ALREADY_PRESENT);
1728
1
    ASSERT_STR_CONTAINS(resp.error().status().ShortDebugString(),
1729
1
        " already exists");
1730
1
  }
1731
  // Check that nothing's changed (still have 3 tables).
1732
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1733
1
  ASSERT_EQ(2 + kNumSystemTables, tables.tables_size());
1734
1
  CheckTables(
1735
1
      {
1736
1
          std::make_tuple(kTableName, other_ns_name, other_ns_id, USER_TABLE_RELATION),
1737
1
          std::make_tuple(kTableName, default_namespace_name, default_namespace_id,
1738
1
              USER_TABLE_RELATION),
1739
1
          EXPECTED_SYSTEM_TABLES
1740
1
      }, tables);
1741
1742
  // Delete the table in the namespace 'testns'.
1743
1
  ASSERT_OK(DeleteTable(other_ns_name, kTableName));
1744
1745
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1746
1
  ASSERT_EQ(1 + kNumSystemTables, tables.tables_size());
1747
1
  CheckTables(
1748
1
      {
1749
1
          std::make_tuple(kTableName, default_namespace_name, default_namespace_id,
1750
1
              USER_TABLE_RELATION),
1751
1
          EXPECTED_SYSTEM_TABLES
1752
1
      }, tables);
1753
1754
  // Try to delete the table from wrong namespace (table 'default_namespace::testtbl').
1755
1
  {
1756
1
    DeleteTableRequestPB req;
1757
1
    DeleteTableResponsePB resp;
1758
1
    req.mutable_table()->set_table_name(kTableName);
1759
1
    req.mutable_table()->mutable_namespace_()->set_name(other_ns_name);
1760
1
    ASSERT_OK(proxy_ddl_->DeleteTable(req, &resp, ResetAndGetController()));
1761
1
    SCOPED_TRACE(resp.DebugString());
1762
1
    ASSERT_TRUE(resp.has_error());
1763
1
    ASSERT_EQ(resp.error().code(), MasterErrorPB::OBJECT_NOT_FOUND);
1764
1
    ASSERT_EQ(resp.error().status().code(), AppStatusPB::NOT_FOUND);
1765
1
    auto status = StatusFromPB(resp.error().status());
1766
1
    ASSERT_EQ(MasterError(status), MasterErrorPB::OBJECT_NOT_FOUND);
1767
1
  }
1768
1769
  // Delete the table.
1770
1
  ASSERT_OK(DeleteTable(default_namespace_name, kTableName));
1771
1772
  // List tables, should show only system tables.
1773
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1774
1
  ASSERT_EQ(kNumSystemTables, tables.tables_size());
1775
1
  CheckTables(
1776
1
      {
1777
1
          EXPECTED_SYSTEM_TABLES
1778
1
      }, tables);
1779
1780
  // Delete the namespace (by NAME).
1781
1
  {
1782
1
    DeleteNamespaceRequestPB req;
1783
1
    DeleteNamespaceResponsePB resp;
1784
1
    req.mutable_namespace_()->set_name(other_ns_name);
1785
1
    ASSERT_OK(proxy_ddl_->DeleteNamespace(req, &resp, ResetAndGetController()));
1786
1
    SCOPED_TRACE(resp.DebugString());
1787
1
    ASSERT_FALSE(resp.has_error());
1788
1
  }
1789
1
  {
1790
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
1791
1
    ASSERT_EQ(1 + kNumSystemNamespaces, namespaces.namespaces_size());
1792
1
    CheckNamespaces(
1793
1
        {
1794
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES
1795
1
        }, namespaces);
1796
1
  }
1797
1
}
1798
1799
1
TEST_F(MasterTest, TestGetTableSchema) {
1800
  // Create a new namespace.
1801
1
  const NamespaceName other_ns_name = "testns";
1802
1
  NamespaceId other_ns_id;
1803
1
  ListNamespacesResponsePB namespaces;
1804
1
  {
1805
1
    CreateNamespaceResponsePB resp;
1806
1
    ASSERT_OK(CreateNamespace(other_ns_name, &resp));
1807
1
    other_ns_id = resp.id();
1808
1
  }
1809
1
  {
1810
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
1811
1
    ASSERT_EQ(2 + kNumSystemNamespaces, namespaces.namespaces_size());
1812
1
    CheckNamespaces(
1813
1
        {
1814
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES,
1815
1
            std::make_tuple(other_ns_name, other_ns_id),
1816
1
        }, namespaces);
1817
1
  }
1818
1819
  // Create a table with the defined new namespace.
1820
1
  const TableName kTableName = "testtb";
1821
1
  const Schema kTableSchema({ ColumnSchema("key", INT32) }, 1);
1822
1
  ASSERT_OK(CreateTable(other_ns_name, kTableName, kTableSchema));
1823
1824
1
  ListTablesResponsePB tables;
1825
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1826
1
  ASSERT_EQ(1 + kNumSystemTables, tables.tables_size());
1827
1
  CheckTables(
1828
1
      {
1829
1
          std::make_tuple(kTableName, other_ns_name, other_ns_id, USER_TABLE_RELATION),
1830
1
          EXPECTED_SYSTEM_TABLES
1831
1
      }, tables);
1832
1833
1
  TableId table_id;
1834
16
  for (int i = 0; i < tables.tables_size(); ++i) {
1835
16
    if (tables.tables(i).name() == kTableName) {
1836
1
        table_id = tables.tables(i).id();
1837
1
        break;
1838
1
    }
1839
16
  }
1840
1841
2
  ASSERT_FALSE(table_id.empty()) << "Couldn't get table id for table " << kTableName;
1842
1843
  // Check GetTableSchema().
1844
1
  {
1845
1
    GetTableSchemaRequestPB req;
1846
1
    GetTableSchemaResponsePB resp;
1847
1
    req.mutable_table()->set_table_name(kTableName);
1848
1
    req.mutable_table()->mutable_namespace_()->set_name(other_ns_name);
1849
1850
    // Check the request.
1851
1
    ASSERT_OK(proxy_ddl_->GetTableSchema(req, &resp, ResetAndGetController()));
1852
1853
    // Check the responsed data.
1854
1
    SCOPED_TRACE(resp.DebugString());
1855
1
    ASSERT_FALSE(resp.has_error());
1856
1
    ASSERT_TRUE(resp.has_table_type());
1857
1
    ASSERT_TRUE(resp.has_create_table_done());
1858
    // SchemaPB schema.
1859
1
    ASSERT_TRUE(resp.has_schema());
1860
1
    ASSERT_EQ(1, resp.schema().columns_size());
1861
1
    ASSERT_EQ(Schema::first_column_id(), resp.schema().columns(0).id());
1862
1
    ASSERT_EQ("key", resp.schema().columns(0).name());
1863
1
    ASSERT_EQ(INT32, resp.schema().columns(0).type().main());
1864
1
    ASSERT_TRUE(resp.schema().columns(0).is_key());
1865
1
    ASSERT_FALSE(resp.schema().columns(0).is_nullable());
1866
1
    ASSERT_EQ(1, resp.schema().columns(0).sorting_type());
1867
    // PartitionSchemaPB partition_schema.
1868
1
    ASSERT_TRUE(resp.has_partition_schema());
1869
1
    ASSERT_EQ(resp.partition_schema().hash_schema(), PartitionSchemaPB::MULTI_COLUMN_HASH_SCHEMA);
1870
    // TableIdentifierPB identifier.
1871
1
    ASSERT_TRUE(resp.has_identifier());
1872
1
    ASSERT_TRUE(resp.identifier().has_table_name());
1873
1
    ASSERT_EQ(kTableName, resp.identifier().table_name());
1874
1
    ASSERT_TRUE(resp.identifier().has_table_id());
1875
1
    ASSERT_EQ(table_id, resp.identifier().table_id());
1876
1
    ASSERT_TRUE(resp.identifier().has_namespace_());
1877
1
    ASSERT_TRUE(resp.identifier().namespace_().has_name());
1878
1
    ASSERT_EQ(other_ns_name, resp.identifier().namespace_().name());
1879
1
    ASSERT_TRUE(resp.identifier().namespace_().has_id());
1880
1
    ASSERT_EQ(other_ns_id, resp.identifier().namespace_().id());
1881
1
  }
1882
1883
  // Delete the table in the namespace 'testns'.
1884
1
  ASSERT_OK(DeleteTable(other_ns_name, kTableName));
1885
1886
  // List tables, should show only system tables.
1887
1
  ASSERT_NO_FATALS(DoListAllTables(&tables));
1888
1
  ASSERT_EQ(kNumSystemTables, tables.tables_size());
1889
1
  CheckTables(
1890
1
      {
1891
1
          EXPECTED_SYSTEM_TABLES
1892
1
      }, tables);
1893
1894
  // Delete the namespace (by NAME).
1895
1
  {
1896
1
    DeleteNamespaceRequestPB req;
1897
1
    DeleteNamespaceResponsePB resp;
1898
1
    req.mutable_namespace_()->set_name(other_ns_name);
1899
1
    ASSERT_OK(proxy_ddl_->DeleteNamespace(req, &resp, ResetAndGetController()));
1900
1
    SCOPED_TRACE(resp.DebugString());
1901
1
    ASSERT_FALSE(resp.has_error());
1902
1
  }
1903
1
  {
1904
1
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
1905
1
    ASSERT_EQ(1 + kNumSystemNamespaces, namespaces.namespaces_size());
1906
1
    CheckNamespaces(
1907
1
        {
1908
1
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES
1909
1
        }, namespaces);
1910
1
  }
1911
1
}
1912
1913
1
TEST_F(MasterTest, TestFailedMasterRestart) {
1914
1
  TearDown();
1915
1916
1
  mini_master_.reset(new MiniMaster(Env::Default(), GetTestPath("Master-test"),
1917
1
                                    AllocateFreePort(), AllocateFreePort(), 0));
1918
1
  ASSERT_NOK(mini_master_->Start(true));
1919
  // Restart master should succeed.
1920
1
  ASSERT_OK(mini_master_->Start());
1921
1
}
1922
1923
1
TEST_F(MasterTest, TestNetworkErrorOnFirstRun) {
1924
1
  TearDown();
1925
1
  mini_master_.reset(new MiniMaster(Env::Default(), GetTestPath("Master-test"),
1926
1
                                    AllocateFreePort(), AllocateFreePort(), 0));
1927
1
  FLAGS_TEST_simulate_port_conflict_error = true;
1928
1
  ASSERT_NOK(mini_master_->Start());
1929
  // Instance file should be properly initialized, but consensus metadata is not initialized.
1930
1
  FLAGS_TEST_simulate_port_conflict_error = false;
1931
  // Restarting master should succeed.
1932
1
  ASSERT_OK(mini_master_->Start());
1933
1
}
1934
1935
namespace {
1936
1937
void GetTableSchema(const char* table_name,
1938
                    const char* namespace_name,
1939
                    const Schema* kSchema,
1940
                    const MasterDdlProxy& proxy,
1941
                    CountDownLatch* started,
1942
1
                    AtomicBool* done) {
1943
1
  GetTableSchemaRequestPB req;
1944
1
  GetTableSchemaResponsePB resp;
1945
1
  req.mutable_table()->set_table_name(table_name);
1946
1
  req.mutable_table()->mutable_namespace_()->set_name(namespace_name);
1947
1948
1
  started->CountDown();
1949
4
  while (!done->Load()) {
1950
3
    RpcController controller;
1951
1952
3
    CHECK_OK(proxy.GetTableSchema(req, &resp, &controller));
1953
3
    SCOPED_TRACE(resp.DebugString());
1954
1955
    // There are two possible outcomes:
1956
    //
1957
    // 1. GetTableSchema() happened before CreateTable(): we expect to see a
1958
    //    TABLE_NOT_FOUND error.
1959
    // 2. GetTableSchema() happened after CreateTable(): we expect to see the
1960
    //    full table schema.
1961
    //
1962
    // Any other outcome is an error.
1963
3
    if (resp.has_error()) {
1964
2
      CHECK_EQ(MasterErrorPB::OBJECT_NOT_FOUND, resp.error().code());
1965
1
    } else {
1966
1
      Schema receivedSchema;
1967
1
      CHECK_OK(SchemaFromPB(resp.schema(), &receivedSchema));
1968
0
      CHECK(kSchema->Equals(receivedSchema)) <<
1969
0
          strings::Substitute("$0 not equal to $1",
1970
0
                              kSchema->ToString(), receivedSchema.ToString());
1971
1
    }
1972
3
  }
1973
1
}
1974
1975
} // namespace
1976
1977
// The catalog manager had a bug wherein GetTableSchema() interleaved with
1978
// CreateTable() could expose intermediate uncommitted state to clients. This
1979
// test ensures that bug does not regress.
1980
1
TEST_F(MasterTest, TestGetTableSchemaIsAtomicWithCreateTable) {
1981
1
  const char *kTableName = "testtb";
1982
1
  const Schema kTableSchema({ ColumnSchema("key", INT32),
1983
1
                              ColumnSchema("v1", UINT64),
1984
1
                              ColumnSchema("v2", STRING) },
1985
1
                            1);
1986
1987
1
  CountDownLatch started(1);
1988
1
  AtomicBool done(false);
1989
1990
  // Kick off a thread that calls GetTableSchema() in a loop.
1991
1
  scoped_refptr<Thread> t;
1992
1
  ASSERT_OK(Thread::Create("test", "test",
1993
1
                           &GetTableSchema, kTableName, default_namespace_name.c_str(),
1994
1
                           &kTableSchema, std::cref(*proxy_ddl_), &started, &done, &t));
1995
1996
  // Only create the table after the thread has started.
1997
1
  started.Wait();
1998
1
  ASSERT_OK(CreateTable(kTableName, kTableSchema));
1999
2000
1
  done.Store(true);
2001
1
  t->Join();
2002
1
}
2003
2004
class NamespaceTest : public MasterTest, public testing::WithParamInterface<YQLDatabase> {};
2005
2006
2
TEST_P(NamespaceTest, RenameNamespace) {
2007
2
  ListNamespacesResponsePB namespaces;
2008
2009
  // Check default namespace.
2010
2
  {
2011
2
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
2012
    // Including system namespace.
2013
2
    ASSERT_EQ(1 + kNumSystemNamespaces, namespaces.namespaces_size());
2014
2
    CheckNamespaces(
2015
2
        {
2016
2
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES
2017
2
        }, namespaces);
2018
2
  }
2019
2020
  // Create a new namespace.
2021
2
  const NamespaceName other_ns_name = "testns";
2022
2
  NamespaceId other_ns_id;
2023
2
  {
2024
2
    CreateNamespaceResponsePB resp;
2025
2
    ASSERT_OK(CreateNamespace(other_ns_name, GetParam() /* database_type */, &resp));
2026
2
    other_ns_id = resp.id();
2027
2
  }
2028
2
  {
2029
2
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
2030
    // Including system namespace.
2031
2
    ASSERT_EQ(2 + kNumSystemNamespaces, namespaces.namespaces_size());
2032
2
    CheckNamespaces(
2033
2
        {
2034
2
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES,
2035
2
            std::make_tuple(other_ns_name, other_ns_id),
2036
2
        }, namespaces);
2037
2
  }
2038
2039
  // Rename the namespace
2040
2
  const NamespaceName other_ns_new_name = "testns_newname";
2041
2
  {
2042
2
    AlterNamespaceResponsePB resp;
2043
2
    ASSERT_OK(AlterNamespace(other_ns_name,
2044
2
                             other_ns_id,
2045
2
                             boost::none /* database_type */,
2046
2
                             other_ns_new_name,
2047
2
                             &resp));
2048
2
  }
2049
2
  {
2050
2
    ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
2051
    // Including system namespace.
2052
2
    ASSERT_EQ(2 + kNumSystemNamespaces, namespaces.namespaces_size());
2053
2
    CheckNamespaces(
2054
2
        {
2055
2
            EXPECTED_DEFAULT_AND_SYSTEM_NAMESPACES,
2056
2
            std::make_tuple(other_ns_new_name, other_ns_id),
2057
2
        }, namespaces);
2058
2
  }
2059
2
}
2060
2061
INSTANTIATE_TEST_CASE_P(
2062
    DatabaseType, NamespaceTest,
2063
    ::testing::Values(YQLDatabase::YQL_DATABASE_CQL, YQLDatabase::YQL_DATABASE_PGSQL));
2064
2065
} // namespace master
2066
} // namespace yb