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_base.cc
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
33
#include "yb/master/master-test_base.h"
34
35
#include <memory>
36
37
#include <gtest/gtest.h>
38
39
#include "yb/common/wire_protocol.h"
40
41
#include "yb/gutil/strings/substitute.h"
42
43
#include "yb/master/master-test-util.h"
44
#include "yb/master/master.h"
45
#include "yb/master/master_client.proxy.h"
46
#include "yb/master/master_cluster.proxy.h"
47
#include "yb/master/master_ddl.proxy.h"
48
#include "yb/master/master_heartbeat.proxy.h"
49
#include "yb/master/master_replication.proxy.h"
50
#include "yb/master/mini_master.h"
51
#include "yb/master/ts_descriptor.h"
52
53
#include "yb/rpc/messenger.h"
54
#include "yb/rpc/proxy.h"
55
56
#include "yb/util/status.h"
57
#include "yb/util/status_format.h"
58
#include "yb/util/status_log.h"
59
#include "yb/util/test_util.h"
60
61
DECLARE_bool(catalog_manager_check_ts_count_for_create_table);
62
DECLARE_bool(TEST_disable_cdc_state_insert_on_setup);
63
64
namespace yb {
65
namespace master {
66
67
35
MasterTestBase::MasterTestBase() = default;
68
33
MasterTestBase::~MasterTestBase() = default;
69
70
35
void MasterTestBase::SetUp() {
71
35
  YBTest::SetUp();
72
73
  // Set an RPC timeout for the controllers.
74
35
  controller_ = make_shared<RpcController>();
75
35
  controller_->set_timeout(MonoDelta::FromSeconds(10));
76
77
  // In this test, we create tables to test catalog manager behavior,
78
  // but we have no tablet servers. Typically this would be disallowed.
79
35
  FLAGS_catalog_manager_check_ts_count_for_create_table = false;
80
  // Since this is a master-only test, don't do any operations on cdc state for xCluster tests.
81
35
  FLAGS_TEST_disable_cdc_state_insert_on_setup = true;
82
83
  // Start master with the create flag on.
84
35
  mini_master_.reset(new MiniMaster(Env::Default(), GetTestPath("Master"),
85
35
                                    AllocateFreePort(), AllocateFreePort(), 0));
86
35
  ASSERT_OK(mini_master_->Start());
87
35
  ASSERT_OK(mini_master_->master()->WaitUntilCatalogManagerIsLeaderAndReadyForTests());
88
89
  // Create a client proxy to it.
90
35
  client_messenger_ = ASSERT_RESULT(MessengerBuilder("Client").Build());
91
35
  rpc::ProxyCache proxy_cache(client_messenger_.get());
92
35
  proxy_client_ = std::make_unique<MasterClientProxy>(
93
35
      &proxy_cache, mini_master_->bound_rpc_addr());
94
35
  proxy_cluster_ = std::make_unique<MasterClusterProxy>(
95
35
      &proxy_cache, mini_master_->bound_rpc_addr());
96
35
  proxy_ddl_ = std::make_unique<MasterDdlProxy>(
97
35
      &proxy_cache, mini_master_->bound_rpc_addr());
98
35
  proxy_heartbeat_ = std::make_unique<MasterHeartbeatProxy>(
99
35
      &proxy_cache, mini_master_->bound_rpc_addr());
100
35
  proxy_replication_ = std::make_unique<MasterReplicationProxy>(
101
35
      &proxy_cache, mini_master_->bound_rpc_addr());
102
103
  // Create the default test namespace.
104
35
  CreateNamespaceResponsePB resp;
105
35
  ASSERT_OK(CreateNamespace(default_namespace_name, &resp));
106
35
  default_namespace_id = resp.id();
107
35
}
108
109
35
void MasterTestBase::TearDown() {
110
35
  if (client_messenger_) {
111
35
    client_messenger_->Shutdown();
112
35
  }
113
35
  mini_master_->Shutdown();
114
35
  YBTest::TearDown();
115
35
}
116
117
Status MasterTestBase::CreateTable(const NamespaceName& namespace_name,
118
                                   const TableName& table_name,
119
                                   const Schema& schema,
120
18
                                   TableId *table_id /* = nullptr */) {
121
18
  CreateTableRequestPB req;
122
18
  return DoCreateTable(namespace_name, table_name, schema, &req, table_id);
123
18
}
124
125
Status MasterTestBase::CreatePgsqlTable(const NamespaceId& namespace_id,
126
                                        const TableName& table_name,
127
4
                                        const Schema& schema) {
128
4
  CreateTableRequestPB req, *request;
129
4
  request = &req;
130
4
  CreateTableResponsePB resp;
131
132
4
  request->set_table_type(TableType::PGSQL_TABLE_TYPE);
133
4
  request->set_name(table_name);
134
4
  SchemaToPB(schema, request->mutable_schema());
135
136
4
  if (!namespace_id.empty()) {
137
4
    request->mutable_namespace_()->set_id(namespace_id);
138
4
  }
139
4
  request->mutable_partition_schema()->set_hash_schema(PartitionSchemaPB::PGSQL_HASH_SCHEMA);
140
4
  request->mutable_schema()->mutable_table_properties()->set_num_tablets(8);
141
142
  // Dereferencing as the RPCs require const ref for request. Keeping request param as pointer
143
  // though, as that helps with readability and standardization.
144
4
  RETURN_NOT_OK(proxy_ddl_->CreateTable(*request, &resp, ResetAndGetController()));
145
4
  if (resp.has_error()) {
146
1
    RETURN_NOT_OK(StatusFromPB(resp.error().status()));
147
1
  }
148
3
  return Status::OK();
149
4
}
150
151
Status MasterTestBase::CreateTablegroupTable(const NamespaceId& namespace_id,
152
                                             const TableName& table_name,
153
                                             const TablegroupId& tablegroup_id,
154
1
                                             const Schema& schema) {
155
1
  CreateTableRequestPB req, *request;
156
1
  request = &req;
157
1
  CreateTableResponsePB resp;
158
159
1
  request->set_table_type(TableType::PGSQL_TABLE_TYPE);
160
1
  request->set_name(table_name);
161
1
  request->set_colocated(true);
162
1
  request->set_tablegroup_id(tablegroup_id);
163
1
  SchemaToPB(schema, request->mutable_schema());
164
165
1
  if (!namespace_id.empty()) {
166
1
    request->mutable_namespace_()->set_id(namespace_id);
167
1
  }
168
169
  // Dereferencing as the RPCs require const ref for request. Keeping request param as pointer
170
  // though, as that helps with readability and standardization.
171
1
  RETURN_NOT_OK(proxy_ddl_->CreateTable(*request, &resp, ResetAndGetController()));
172
1
  if (resp.has_error()) {
173
0
    RETURN_NOT_OK(StatusFromPB(resp.error().status()));
174
0
  }
175
1
  return Status::OK();
176
1
}
177
178
Status MasterTestBase::DoCreateTable(const NamespaceName& namespace_name,
179
                                     const TableName& table_name,
180
                                     const Schema& schema,
181
                                     CreateTableRequestPB* request,
182
21
                                     TableId *table_id /* = nullptr */) {
183
21
  CreateTableResponsePB resp;
184
185
21
  request->set_name(table_name);
186
21
  SchemaToPB(schema, request->mutable_schema());
187
188
21
  if (!namespace_name.empty()) {
189
21
    request->mutable_namespace_()->set_name(namespace_name);
190
21
  }
191
21
  request->mutable_partition_schema()->set_hash_schema(PartitionSchemaPB::MULTI_COLUMN_HASH_SCHEMA);
192
21
  request->mutable_schema()->mutable_table_properties()->set_num_tablets(8);
193
194
  // Dereferencing as the RPCs require const ref for request. Keeping request param as pointer
195
  // though, as that helps with readability and standardization.
196
21
  RETURN_NOT_OK(proxy_ddl_->CreateTable(*request, &resp, ResetAndGetController()));
197
21
  if (table_id) {
198
4
    *table_id = resp.table_id();
199
4
  }
200
21
  if (resp.has_error()) {
201
4
    RETURN_NOT_OK(StatusFromPB(resp.error().status()));
202
4
  }
203
204
17
  return Status::OK();
205
21
}
206
207
35
void MasterTestBase::DoListTables(const ListTablesRequestPB& req, ListTablesResponsePB* resp) {
208
35
  ASSERT_OK(proxy_ddl_->ListTables(req, resp, ResetAndGetController()));
209
35
  SCOPED_TRACE(resp->DebugString());
210
35
  ASSERT_FALSE(resp->has_error());
211
35
}
212
213
void MasterTestBase::DoListAllTables(ListTablesResponsePB* resp,
214
25
                                     const NamespaceName& namespace_name /*= ""*/) {
215
25
  ListTablesRequestPB req;
216
217
25
  if (!namespace_name.empty()) {
218
2
    req.mutable_namespace_()->set_name(namespace_name);
219
2
  }
220
221
25
  DoListTables(req, resp);
222
25
}
223
224
Status MasterTestBase::DeleteTable(const NamespaceName& namespace_name,
225
                                   const TableName& table_name,
226
10
                                   TableId* table_id /* = nullptr */) {
227
10
  DeleteTableRequestPB req;
228
10
  DeleteTableResponsePB resp;
229
10
  req.mutable_table()->set_table_name(table_name);
230
231
10
  if (!namespace_name.empty()) {
232
10
    req.mutable_table()->mutable_namespace_()->set_name(namespace_name);
233
10
  }
234
235
10
  RETURN_NOT_OK(proxy_ddl_->DeleteTable(req, &resp, ResetAndGetController()));
236
10
  SCOPED_TRACE(resp.DebugString());
237
10
  if (table_id) {
238
3
    *table_id = resp.table_id();
239
3
  }
240
241
10
  if (resp.has_error()) {
242
1
    RETURN_NOT_OK(StatusFromPB(resp.error().status()));
243
1
  }
244
9
  return Status::OK();
245
10
}
246
247
Status MasterTestBase::CreateTablegroup(const TablegroupId& tablegroup_id,
248
                                        const NamespaceId& namespace_id,
249
                                        const NamespaceName& namespace_name,
250
1
                                        const TablespaceId& tablespace_id) {
251
1
  CreateTablegroupRequestPB req, *request;
252
1
  request = &req;
253
1
  CreateTablegroupResponsePB resp;
254
255
1
  request->set_id(tablegroup_id);
256
1
  request->set_namespace_id(namespace_id);
257
1
  request->set_namespace_name(namespace_name);
258
1
  request->set_tablespace_id(tablespace_id);
259
260
  // Dereferencing as the RPCs require const ref for request. Keeping request param as pointer
261
  // though, as that helps with readability and standardization.
262
1
  RETURN_NOT_OK(proxy_ddl_->CreateTablegroup(*request, &resp, ResetAndGetController()));
263
1
  if (resp.has_error()) {
264
0
    RETURN_NOT_OK(StatusFromPB(resp.error().status()));
265
0
  }
266
1
  return Status::OK();
267
1
}
268
269
Status MasterTestBase::DeleteTablegroup(const TablegroupId& tablegroup_id,
270
1
                                        const NamespaceId& namespace_id) {
271
1
  DeleteTablegroupRequestPB req;
272
1
  DeleteTablegroupResponsePB resp;
273
1
  req.set_id(tablegroup_id);
274
1
  req.set_namespace_id(namespace_id);
275
276
1
  RETURN_NOT_OK(proxy_ddl_->DeleteTablegroup(req, &resp, ResetAndGetController()));
277
1
  if (resp.has_error()) {
278
0
    RETURN_NOT_OK(StatusFromPB(resp.error().status()));
279
0
  }
280
1
  return Status::OK();
281
1
}
282
283
void MasterTestBase::DoListTablegroups(const ListTablegroupsRequestPB& req,
284
2
                                       ListTablegroupsResponsePB* resp) {
285
2
  ASSERT_OK(proxy_ddl_->ListTablegroups(req, resp, ResetAndGetController()));
286
2
  SCOPED_TRACE(resp->DebugString());
287
2
  ASSERT_FALSE(resp->has_error());
288
2
}
289
290
32
void MasterTestBase::DoListAllNamespaces(ListNamespacesResponsePB* resp) {
291
32
  DoListAllNamespaces(boost::none, resp);
292
32
}
293
294
void MasterTestBase::DoListAllNamespaces(const boost::optional<YQLDatabase>& database_type,
295
36
                                         ListNamespacesResponsePB* resp) {
296
36
  ListNamespacesRequestPB req;
297
36
  if (database_type) {
298
4
    req.set_database_type(*database_type);
299
4
  }
300
301
36
  ASSERT_OK(proxy_ddl_->ListNamespaces(req, resp, ResetAndGetController()));
302
36
  SCOPED_TRACE(resp->DebugString());
303
36
  ASSERT_FALSE(resp->has_error());
304
36
}
305
306
Status MasterTestBase::CreateNamespace(const NamespaceName& ns_name,
307
43
                                       CreateNamespaceResponsePB* resp) {
308
43
  return CreateNamespace(ns_name, boost::none, resp);
309
43
}
310
311
Status MasterTestBase::CreateNamespace(const NamespaceName& ns_name,
312
                                       const boost::optional<YQLDatabase>& database_type,
313
68
                                       CreateNamespaceResponsePB* resp) {
314
68
  RETURN_NOT_OK(CreateNamespaceAsync(ns_name, database_type, resp));
315
56
  return CreateNamespaceWait(resp->id(), database_type);
316
68
}
317
318
Status MasterTestBase::CreateNamespaceAsync(const NamespaceName& ns_name,
319
                                            const boost::optional<YQLDatabase>& database_type,
320
81
                                            CreateNamespaceResponsePB* resp) {
321
81
  CreateNamespaceRequestPB req;
322
81
  req.set_name(ns_name);
323
81
  if (database_type) {
324
38
    req.set_database_type(*database_type);
325
38
  }
326
327
81
  RETURN_NOT_OK(proxy_ddl_->CreateNamespace(req, resp, ResetAndGetController()));
328
81
  if (resp->has_error()) {
329
12
    RETURN_NOT_OK(StatusFromPB(resp->error().status()));
330
12
  }
331
69
  return Status::OK();
332
81
}
333
334
Status MasterTestBase::CreateNamespaceWait(const NamespaceId& ns_id,
335
58
                                           const boost::optional<YQLDatabase>& database_type) {
336
58
  Status status = Status::OK();
337
338
58
  IsCreateNamespaceDoneRequestPB is_req;
339
58
  is_req.mutable_namespace_()->set_id(ns_id);
340
58
  if (database_type) {
341
17
    is_req.mutable_namespace_()->set_database_type(*database_type);
342
17
  }
343
344
104
  return LoggedWaitFor([&]() -> Result<bool> {
345
104
    IsCreateNamespaceDoneResponsePB is_resp;
346
104
    status = proxy_ddl_->IsCreateNamespaceDone(is_req, &is_resp, ResetAndGetController());
347
104
    WARN_NOT_OK(status, "IsCreateNamespaceDone returned unexpected error");
348
104
    if (!status.ok()) {
349
0
      return status;
350
0
    }
351
104
    if (is_resp.has_done() && is_resp.done()) {
352
58
      if (is_resp.has_error()) {
353
0
        return StatusFromPB(is_resp.error().status());
354
0
      }
355
58
      return true;
356
58
    }
357
46
    return false;
358
46
  }, MonoDelta::FromSeconds(60), "Wait for create namespace to finish async setup tasks.");
359
58
}
360
361
Status MasterTestBase::AlterNamespace(const NamespaceName& ns_name,
362
                                      const NamespaceId& ns_id,
363
                                      const boost::optional<YQLDatabase>& database_type,
364
                                      const std::string& new_name,
365
4
                                      AlterNamespaceResponsePB* resp) {
366
4
  AlterNamespaceRequestPB req;
367
4
  req.mutable_namespace_()->set_id(ns_id);
368
4
  req.mutable_namespace_()->set_name(ns_name);
369
4
  if (database_type) {
370
2
    req.mutable_namespace_()->set_database_type(*database_type);
371
2
  }
372
4
  req.set_new_name(new_name);
373
374
4
  RETURN_NOT_OK(proxy_ddl_->AlterNamespace(req, resp, ResetAndGetController()));
375
4
  if (resp->has_error()) {
376
1
    RETURN_NOT_OK(StatusFromPB(resp->error().status()));
377
1
  }
378
3
  return Status::OK();
379
4
}
380
381
// PGSQL Namespaces are deleted asynchronously since they may delete a large number of tables.
382
// CQL Namespaces don't need to call this function and return success if present.
383
26
Status MasterTestBase::DeleteNamespaceWait(IsDeleteNamespaceDoneRequestPB const& del_req) {
384
62
  return LoggedWaitFor([&]() -> Result<bool> {
385
62
    IsDeleteNamespaceDoneResponsePB del_resp;
386
62
    auto status = proxy_ddl_->IsDeleteNamespaceDone(del_req, &del_resp, ResetAndGetController());
387
62
    if (!status.ok()) {
388
0
      WARN_NOT_OK(status, "IsDeleteNamespaceDone returned unexpected error");
389
0
      return status;
390
0
    }
391
62
    if (del_resp.has_done() && del_resp.done()) {
392
26
      if (del_resp.has_error()) {
393
5
        return StatusFromPB(del_resp.error().status());
394
5
      }
395
21
      return true;
396
21
    }
397
36
    return false;
398
36
  }, MonoDelta::FromSeconds(10), "Wait for delete namespace to finish async cleanup tasks.");
399
26
}
400
401
Status MasterTestBase::DeleteTableSync(const NamespaceName& ns_name, const TableName& table_name,
402
2
                                       TableId* table_id) {
403
2
  RETURN_NOT_OK(DeleteTable(ns_name, table_name, table_id));
404
405
1
  IsDeleteTableDoneRequestPB done_req;
406
1
  done_req.set_table_id(*table_id);
407
1
  IsDeleteTableDoneResponsePB done_resp;
408
1
  bool delete_done = false;
409
410
1
  for (int num_retries = 0; num_retries < 30; ++num_retries) {
411
1
    RETURN_NOT_OK(proxy_ddl_->IsDeleteTableDone(done_req, &done_resp, ResetAndGetController()));
412
1
    if (!done_resp.has_done()) {
413
0
      return STATUS_FORMAT(
414
0
          IllegalState, "Expected IsDeleteTableDone response to set value for done ($0.$1)",
415
0
          ns_name, table_name);
416
0
    }
417
1
    if (done_resp.done()) {
418
1
      LOG(INFO) << "Done on retry " << num_retries;
419
1
      delete_done = true;
420
1
      break;
421
1
    }
422
423
0
    SleepFor(MonoDelta::FromMilliseconds(10 * num_retries)); // sleep a bit more with each attempt.
424
0
  }
425
426
1
  if (!delete_done) {
427
0
    return STATUS_FORMAT(IllegalState, "Delete Table did not complete ($0.$1)",
428
0
                         ns_name, table_name);
429
0
  }
430
1
  return Status::OK();
431
1
}
432
433
void MasterTestBase::CheckNamespaces(
434
    const std::set<std::tuple<NamespaceName, NamespaceId>>& namespace_info,
435
32
    const ListNamespacesResponsePB& namespaces) {
436
171
  for (int i = 0; i < namespaces.namespaces_size(); i++) {
437
139
    auto search_key = std::make_tuple(namespaces.namespaces(i).name(),
438
139
                                      namespaces.namespaces(i).id());
439
278
    ASSERT_TRUE(namespace_info.find(search_key) != namespace_info.end())
440
278
                  << strings::Substitute("Couldn't find namespace $0", namespaces.namespaces(i)
441
278
                      .name());
442
139
  }
443
444
32
  ASSERT_EQ(namespaces.namespaces_size(), namespace_info.size());
445
32
}
446
447
bool MasterTestBase::FindNamespace(
448
    const std::tuple<NamespaceName, NamespaceId>& namespace_info,
449
4
    const ListNamespacesResponsePB& namespaces) {
450
20
  for (int i = 0; i < namespaces.namespaces_size(); i++) {
451
16
    auto cur_ns = std::make_tuple(namespaces.namespaces(i).name(),
452
16
                                  namespaces.namespaces(i).id());
453
16
    if (cur_ns == namespace_info) {
454
0
      return true; // found!
455
0
    }
456
16
  }
457
4
  return false; // namespace not found.
458
4
}
459
460
void MasterTestBase::CheckTables(
461
    const std::set<std::tuple<TableName, NamespaceName, NamespaceId, bool>>& table_info,
462
25
    const ListTablesResponsePB& tables) {
463
437
  for (int i = 0; i < tables.tables_size(); i++) {
464
412
    auto search_key = std::make_tuple(tables.tables(i).name(),
465
412
                                      tables.tables(i).namespace_().name(),
466
412
                                      tables.tables(i).namespace_().id(),
467
412
                                      tables.tables(i).relation_type());
468
824
    ASSERT_TRUE(table_info.find(search_key) != table_info.end())
469
824
        << strings::Substitute("Couldn't find table $0.$1",
470
824
            tables.tables(i).namespace_().name(), tables.tables(i).name());
471
412
  }
472
473
25
  ASSERT_EQ(tables.tables_size(), table_info.size());
474
25
}
475
476
3
void MasterTestBase::UpdateMasterClusterConfig(SysClusterConfigEntryPB* cluster_config) {
477
3
  ChangeMasterClusterConfigRequestPB change_req;
478
3
  change_req.mutable_cluster_config()->CopyFrom(*cluster_config);
479
3
  ChangeMasterClusterConfigResponsePB change_resp;
480
3
  rpc::ProxyCache proxy_cache(client_messenger_.get());
481
3
  master::MasterClusterProxy proxy(&proxy_cache, mini_master_->bound_rpc_addr());
482
3
  ASSERT_OK(proxy.ChangeMasterClusterConfig(change_req, &change_resp, ResetAndGetController()));
483
  // Bump version number by 1, so we do not have to re-query.
484
3
  cluster_config->set_version(cluster_config->version() + 1);
485
3
  LOG(INFO) << "Update cluster config to: " << cluster_config->ShortDebugString();
486
3
}
487
488
} // namespace master
489
} // namespace yb