YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/ent/src/yb/master/catalog_manager-test_ent.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
13
#include "../../src/yb/master/catalog_manager-test_base.h"
14
#include "yb/util/status_log.h"
15
16
namespace yb {
17
namespace master {
18
namespace enterprise {
19
20
using std::shared_ptr;
21
using std::make_shared;
22
23
const string read_only_placement_uuid = "read_only";
24
25
std::shared_ptr<TSDescriptor> SetupTSEnt(const string& uuid,
26
                                         const string& az,
27
19
                                         const string& placement_uuid) {
28
19
  NodeInstancePB node;
29
19
  node.set_permanent_uuid(uuid);
30
31
19
  TSRegistrationPB reg;
32
  // Set the placement uuid field for read_only clusters.
33
19
  reg.mutable_common()->set_placement_uuid(placement_uuid);
34
  // Fake host:port combo, with uuid as host, for ease of testing.
35
19
  auto hp = reg.mutable_common()->add_private_rpc_addresses();
36
19
  hp->set_host(uuid);
37
  // Same cloud info as cluster config, with modifyable AZ.
38
19
  auto ci = reg.mutable_common()->mutable_cloud_info();
39
19
  ci->set_placement_cloud(default_cloud);
40
19
  ci->set_placement_region(default_region);
41
19
  ci->set_placement_zone(az);
42
43
19
  std::shared_ptr<TSDescriptor> ts(new TSDescriptor(node.permanent_uuid()));
44
19
  CHECK_OK(ts->Register(node, reg, CloudInfoPB(), nullptr));
45
46
19
  return ts;
47
19
}
48
49
void SetupClusterConfigEnt(const vector<string>& az_list,
50
                           const vector<string>& read_only_list,
51
                           const vector<string>& affinitized_leader_list,
52
5
                           ReplicationInfoPB* replication_info) {
53
5
  PlacementInfoPB* placement_info = replication_info->mutable_live_replicas();
54
5
  placement_info->set_num_replicas(kDefaultNumReplicas);
55
56
13
  for (const string& az : az_list) {
57
13
    auto pb = placement_info->add_placement_blocks();
58
13
    pb->mutable_cloud_info()->set_placement_cloud(default_cloud);
59
13
    pb->mutable_cloud_info()->set_placement_region(default_region);
60
13
    pb->mutable_cloud_info()->set_placement_zone(az);
61
13
    pb->set_min_num_replicas(1);
62
13
  }
63
64
5
  if (!read_only_list.empty()) {
65
4
    placement_info = replication_info->add_read_replicas();
66
4
    placement_info->set_num_replicas(1);
67
4
  }
68
69
4
  for (const string& read_only_az : read_only_list) {
70
4
    auto pb = placement_info->add_placement_blocks();
71
4
    pb->mutable_cloud_info()->set_placement_cloud(default_cloud);
72
4
    pb->mutable_cloud_info()->set_placement_region(default_region);
73
4
    pb->mutable_cloud_info()->set_placement_zone(read_only_az);
74
4
    placement_info->set_placement_uuid(read_only_placement_uuid);
75
4
    pb->set_min_num_replicas(1);
76
4
  }
77
78
1
  for (const string& affinitized_az : affinitized_leader_list) {
79
1
    CloudInfoPB* ci = replication_info->add_affinitized_leaders();
80
1
    ci->set_placement_cloud(default_cloud);
81
1
    ci->set_placement_region(default_region);
82
1
    ci->set_placement_zone(affinitized_az);
83
1
  }
84
5
}
85
86
class TestLoadBalancerEnterprise : public TestLoadBalancerBase<ClusterLoadBalancerMocked> {
87
 public:
88
  TestLoadBalancerEnterprise(ClusterLoadBalancerMocked* cb, const string& table_id) :
89
1
      TestLoadBalancerBase<ClusterLoadBalancerMocked>(cb, table_id) {}
90
91
1
  void TestAlgorithm() {
92
1
    TestLoadBalancerBase<ClusterLoadBalancerMocked>::TestAlgorithm();
93
94
1
    shared_ptr<TSDescriptor> ts0 =
95
1
        SetupTSEnt("0000", "a", "" /* placement_uuid */);
96
1
    shared_ptr<TSDescriptor> ts1 = SetupTSEnt("1111", "b", "");
97
1
    shared_ptr<TSDescriptor> ts2 = SetupTSEnt("2222", "c", "");
98
99
1
    TSDescriptorVector ts_descs = {ts0, ts1, ts2};
100
101
1
    PrepareTestState(ts_descs);
102
1
    PrepareAffinitizedLeaders({"a"} /* affinitized zones */);
103
1
    TestAlreadyBalancedAffinitizedLeaders();
104
105
1
    PrepareTestState(ts_descs);
106
1
    PrepareAffinitizedLeaders({"a"});
107
1
    TestBalancingOneAffinitizedLeader();
108
109
1
    PrepareTestState(ts_descs);
110
1
    PrepareAffinitizedLeaders({"b", "c"});
111
1
    TestBalancingTwoAffinitizedLeaders();
112
113
1
    PrepareTestState(ts_descs);
114
1
    TestReadOnlyLoadBalancing();
115
116
1
    PrepareTestState(ts_descs);
117
1
    TestLeaderBalancingWithReadOnly();
118
1
  }
119
120
1
  void TestAlreadyBalancedAffinitizedLeaders() {
121
1
    LOG(INFO) << "Starting TestAlreadyBalancedAffinitizedLeaders";
122
    // Move all leaders to ts0.
123
4
    for (const auto& tablet : tablets_) {
124
4
      MoveTabletLeader(tablet.get(), ts_descs_[0]);
125
4
    }
126
1
    LOG(INFO) << "Leader distribution: 4 0 0";
127
128
1
    ASSERT_OK(AnalyzeTablets());
129
1
    string placeholder;
130
    // Only the affinitized zone contains tablet leaders, should be no movement.
131
1
    ASSERT_FALSE(ASSERT_RESULT(HandleLeaderMoves(&placeholder, &placeholder, &placeholder)));
132
1
    LOG(INFO) << "Finishing TestAlreadyBalancedAffinitizedLeaders";
133
1
  }
134
135
1
  void TestBalancingOneAffinitizedLeader() {
136
1
    LOG(INFO) << "Starting TestBalancingOneAffinitizedLeader";
137
1
    int i = 0;
138
4
    for (const auto& tablet : tablets_) {
139
4
      MoveTabletLeader(tablet.get(), ts_descs_[(i % 2) + 1]);
140
4
      i++;
141
4
    }
142
1
    LOG(INFO) << "Leader distribution: 0 2 2";
143
144
1
    ASSERT_OK(AnalyzeTablets());
145
146
1
    std::map<string, int> from_count;
147
1
    std::unordered_set<string> tablets_moved;
148
149
1
    string placeholder, tablet_id, from_ts, to_ts, ts_0, ts_1, ts_2;
150
1
    ts_0 = ts_descs_[0]->permanent_uuid();
151
1
    ts_1 = ts_descs_[1]->permanent_uuid();
152
1
    ts_2 = ts_descs_[2]->permanent_uuid();
153
154
1
    from_count[ts_0] = 0;
155
1
    from_count[ts_1] = 0;
156
1
    from_count[ts_2] = 0;
157
158
1
    ASSERT_TRUE(ASSERT_RESULT(HandleLeaderMoves(&tablet_id, &from_ts, &to_ts)));
159
1
    ASSERT_EQ(to_ts, ts_0);
160
1
    tablets_moved.insert(tablet_id);
161
1
    from_count[from_ts]++;
162
163
1
    ASSERT_TRUE(ASSERT_RESULT(HandleLeaderMoves(&tablet_id, &from_ts, &to_ts)));
164
1
    ASSERT_EQ(to_ts, ts_0);
165
1
    tablets_moved.insert(tablet_id);
166
1
    from_count[from_ts]++;
167
168
1
    LOG(INFO) << "Leader distribution: 2 1 1";
169
    // Make sure one tablet moved from each ts1 and ts2.
170
1
    ASSERT_EQ(1, from_count[ts_1]);
171
1
    ASSERT_EQ(1, from_count[ts_2]);
172
173
1
    ASSERT_TRUE(ASSERT_RESULT(HandleLeaderMoves(&tablet_id, &from_ts, &to_ts)));
174
1
    ASSERT_EQ(to_ts, ts_0);
175
1
    tablets_moved.insert(tablet_id);
176
1
    from_count[from_ts]++;
177
178
1
    ASSERT_TRUE(ASSERT_RESULT(HandleLeaderMoves(&tablet_id, &from_ts, &to_ts)));
179
1
    ASSERT_EQ(to_ts, ts_0);
180
1
    tablets_moved.insert(tablet_id);
181
1
    from_count[from_ts]++;
182
183
1
    LOG(INFO) << "Leader distribution: 4 0 0";
184
    // Make sure two tablets moved from each ts1 and ts2.
185
1
    ASSERT_EQ(2, from_count[ts_1]);
186
1
    ASSERT_EQ(2, from_count[ts_2]);
187
188
    // Make sure all the tablets moved are distinct.
189
1
    ASSERT_EQ(4, tablets_moved.size());
190
191
1
    ASSERT_FALSE(ASSERT_RESULT(HandleLeaderMoves(&placeholder, &placeholder, &placeholder)));
192
1
    LOG(INFO) << "Finishing TestBalancingOneAffinitizedLeader";
193
1
  }
194
195
1
  void TestBalancingTwoAffinitizedLeaders() {
196
1
    LOG(INFO) << "Starting TestBalancingTwoAffinitizedLeaders";
197
198
4
    for (const auto& tablet : tablets_) {
199
4
      MoveTabletLeader(tablet.get(), ts_descs_[0]);
200
4
    }
201
1
    LOG(INFO) << "Leader distribution: 4 0 0";
202
203
1
    ASSERT_OK(AnalyzeTablets());
204
205
1
    std::map<string, int> to_count;
206
1
    std::unordered_set<string> tablets_moved;
207
208
1
    string placeholder, tablet_id, from_ts, to_ts, ts_0, ts_1, ts_2;
209
1
    ts_0 = ts_descs_[0]->permanent_uuid();
210
1
    ts_1 = ts_descs_[1]->permanent_uuid();
211
1
    ts_2 = ts_descs_[2]->permanent_uuid();
212
213
1
    to_count[ts_0] = 0;
214
1
    to_count[ts_1] = 0;
215
1
    to_count[ts_2] = 0;
216
217
218
1
    ASSERT_TRUE(ASSERT_RESULT(HandleLeaderMoves(&tablet_id, &from_ts, &to_ts)));
219
1
    ASSERT_EQ(from_ts, ts_0);
220
1
    tablets_moved.insert(tablet_id);
221
1
    to_count[to_ts]++;
222
223
1
    ASSERT_TRUE(ASSERT_RESULT(HandleLeaderMoves(&tablet_id, &from_ts, &to_ts)));
224
1
    ASSERT_EQ(from_ts, ts_0);
225
1
    tablets_moved.insert(tablet_id);
226
1
    to_count[to_ts]++;
227
228
1
    LOG(INFO) << "Leader distribution: 2 1 1";
229
    // Make sure one tablet moved to each ts1 and ts2.
230
1
    ASSERT_EQ(1, to_count[ts_1]);
231
1
    ASSERT_EQ(1, to_count[ts_2]);
232
233
1
    ASSERT_TRUE(ASSERT_RESULT(HandleLeaderMoves(&tablet_id, &from_ts, &to_ts)));
234
1
    ASSERT_EQ(from_ts, ts_0);
235
1
    tablets_moved.insert(tablet_id);
236
1
    to_count[to_ts]++;
237
238
1
    ASSERT_TRUE(ASSERT_RESULT(HandleLeaderMoves(&tablet_id, &from_ts, &to_ts)));
239
1
    ASSERT_EQ(from_ts, ts_0);
240
1
    tablets_moved.insert(tablet_id);
241
1
    to_count[to_ts]++;
242
243
1
    LOG(INFO) << "Leader distribution: 0 2 2";
244
    // Make sure two tablets moved to each ts1 and ts2.
245
1
    ASSERT_EQ(2, to_count[ts_1]);
246
1
    ASSERT_EQ(2, to_count[ts_2]);
247
248
    // Make sure all the tablets moved are distinct.
249
1
    ASSERT_EQ(4, tablets_moved.size());
250
251
1
    ASSERT_FALSE(ASSERT_RESULT(HandleLeaderMoves(&placeholder, &placeholder, &placeholder)));
252
1
    LOG(INFO) << "Finishing TestBalancingTwoAffinitizedLeaders";
253
1
  }
254
255
1
  void TestReadOnlyLoadBalancing() {
256
1
    LOG(INFO) << "Starting TestBasicBalancingWithReadOnly";
257
    // RF = 3 + 1, 4 TS, 3 AZ, 4 tablets.
258
    // Normal setup.
259
    // then create new node in az1 with all replicas.
260
1
    SetupClusterConfigEnt({"a", "b", "c"} /* az list */, {"a"} /* read only */,
261
1
                          {} /* affinitized leaders */, &replication_info_);
262
1
    ts_descs_.push_back(SetupTSEnt("3333", "a", read_only_placement_uuid /* placement_uuid */));
263
1
    ts_descs_.push_back(SetupTSEnt("4444", "a", read_only_placement_uuid /* placement_uuid */));
264
265
    // Adding all read_only replicas.
266
4
    for (const auto& tablet : tablets_) {
267
4
      AddRunningReplicaEnt(tablet.get(), ts_descs_[3], false /* is live */);
268
4
    }
269
270
1
    LOG(INFO) << "The replica count for each read_only tserver is: ts3: 4, ts4: 0";
271
1
    ASSERT_OK(AnalyzeTablets());
272
273
1
    string placeholder;
274
275
    // First we make sure that no load balancing happens during the live iteration.
276
1
    ASSERT_FALSE(ASSERT_RESULT(HandleAddReplicas(&placeholder, &placeholder, &placeholder)));
277
278
1
    ResetState();
279
1
    cb_->SetOptions(READ_ONLY, read_only_placement_uuid);
280
1
    ASSERT_OK(AnalyzeTablets());
281
    // Now load balance an read_only replica.
282
1
    string expected_from_ts = ts_descs_[3]->permanent_uuid();
283
1
    string expected_to_ts = ts_descs_[4]->permanent_uuid();
284
1
    string expected_tablet_id = tablets_[0]->tablet_id();
285
1
    TestAddLoad(expected_tablet_id, expected_from_ts, expected_to_ts);
286
1
    RemoveReplica(tablet_map_[expected_tablet_id].get(), ts_descs_[3]);
287
1
    AddRunningReplicaEnt(tablet_map_[expected_tablet_id].get(), ts_descs_[4], false);
288
289
1
    ClearTabletsAddedForTest();
290
291
1
    expected_from_ts = ts_descs_[3]->permanent_uuid();
292
1
    expected_to_ts = ts_descs_[4]->permanent_uuid();
293
1
    expected_tablet_id = tablets_[1]->tablet_id();
294
1
    TestAddLoad(expected_tablet_id, expected_from_ts, expected_to_ts);
295
1
    RemoveReplica(tablet_map_[expected_tablet_id].get(), ts_descs_[3]);
296
1
    AddRunningReplicaEnt(tablet_map_[expected_tablet_id].get(), ts_descs_[4], false);
297
298
    // Then make sure there is no more balancing, since both ts3 and ts4 have 2 replicas each.
299
1
    ASSERT_FALSE(ASSERT_RESULT(HandleAddReplicas(&placeholder, &placeholder, &placeholder)));
300
1
    LOG(INFO) << "Finishing TestBasicBalancingWithReadOnly";
301
1
  }
302
303
1
  void TestLeaderBalancingWithReadOnly() {
304
    // RF = 3 + 1, 4 TS, 3 AZ, 4 tablets.
305
1
    LOG(INFO) << "Starting TestLeaderBalancingWithReadOnly";
306
1
    SetupClusterConfigEnt({"a", "b", "c"} /* az list */, {"a"} /* read only */,
307
1
                          {} /* affinitized leaders */, &replication_info_);
308
1
    ts_descs_.push_back(SetupTSEnt("3333", "a", read_only_placement_uuid));
309
310
    // Adding all read_only replicas.
311
4
    for (const auto& tablet : tablets_) {
312
4
      AddRunningReplicaEnt(tablet.get(), ts_descs_[3], false /* is live */);
313
4
    }
314
315
1
    ResetState();
316
1
    ASSERT_OK(AnalyzeTablets());
317
1
    string placeholder;
318
1
    ASSERT_FALSE(ASSERT_RESULT(HandleLeaderMoves(&placeholder, &placeholder, &placeholder)));
319
320
1
    cb_->SetOptions(READ_ONLY, read_only_placement_uuid);
321
1
    ResetState();
322
1
    ASSERT_OK(AnalyzeTablets());
323
1
    ASSERT_FALSE(ASSERT_RESULT(HandleLeaderMoves(&placeholder, &placeholder, &placeholder)));
324
1
    LOG(INFO) << "Finishing TestLeaderBalancingWithReadOnly";
325
1
  }
326
327
3
  void PrepareAffinitizedLeaders(const vector<string>& zones) {
328
4
    for (const string& zone : zones) {
329
4
      CloudInfoPB ci;
330
4
      ci.set_placement_cloud(default_cloud);
331
4
      ci.set_placement_region(default_region);
332
4
      ci.set_placement_zone(zone);
333
4
      affinitized_zones_.insert(ci);
334
4
    }
335
3
  }
336
337
  void AddRunningReplicaEnt(TabletInfo* tablet, std::shared_ptr<yb::master::TSDescriptor> ts_desc,
338
10
                            bool is_live) {
339
10
    std::shared_ptr<TabletReplicaMap> replicas =
340
10
      std::const_pointer_cast<TabletReplicaMap>(tablet->GetReplicaLocations());
341
342
10
    TabletReplica replica;
343
10
    PeerRole role = is_live ? PeerRole::FOLLOWER : PeerRole::LEARNER;
344
10
    NewReplica(ts_desc.get(), tablet::RaftGroupStatePB::RUNNING, role, &replica);
345
10
    InsertOrDie(replicas.get(), ts_desc->permanent_uuid(), replica);
346
10
    tablet->SetReplicaLocations(replicas);
347
10
  }
348
};
349
350
1
TEST(TestLoadBalancerEnterprise, TestLoadBalancerAlgorithm) {
351
1
  const TableId table_id = CURRENT_TEST_NAME();
352
1
  auto options = make_shared<Options>();
353
1
  auto cb = make_shared<ClusterLoadBalancerMocked>(options.get());
354
1
  auto lb = make_shared<TestLoadBalancerEnterprise>(cb.get(), table_id);
355
1
  lb->TestAlgorithm();
356
1
}
357
358
359
1
TEST(TestCatalogManagerEnterprise, TestLeaderLoadBalancedAffinitizedLeaders) {
360
  // Note that this is essentially using transaction_tables_use_preferred_zones = true
361
1
  ReplicationInfoPB replication_info;
362
1
  SetupClusterConfigEnt({"a", "b", "c"} /* az list */, {} /* read only */,
363
1
                        {"a"} /* affinitized leaders */, &replication_info);
364
365
1
  std::shared_ptr<TSDescriptor> ts0 = SetupTSEnt("0000", "a", "");
366
1
  std::shared_ptr<TSDescriptor> ts1 = SetupTSEnt("1111", "a", "");
367
1
  std::shared_ptr<TSDescriptor> ts2 = SetupTSEnt("2222", "b", "");
368
1
  std::shared_ptr<TSDescriptor> ts3 = SetupTSEnt("3333", "b", "");
369
1
  std::shared_ptr<TSDescriptor> ts4 = SetupTSEnt("4444", "c", "");
370
371
1
  ASSERT_TRUE(ts0->IsAcceptingLeaderLoad(replication_info));
372
1
  ASSERT_TRUE(ts1->IsAcceptingLeaderLoad(replication_info));
373
1
  ASSERT_FALSE(ts2->IsAcceptingLeaderLoad(replication_info));
374
1
  ASSERT_FALSE(ts3->IsAcceptingLeaderLoad(replication_info));
375
1
  ASSERT_FALSE(ts4->IsAcceptingLeaderLoad(replication_info));
376
377
1
  TSDescriptorVector ts_descs = {ts0, ts1, ts2, ts3, ts4};
378
379
1
  ts0->set_leader_count(8);
380
1
  ts1->set_leader_count(8);
381
1
  ts2->set_leader_count(0);
382
1
  ts3->set_leader_count(0);
383
1
  ts4->set_leader_count(1);
384
1
  ASSERT_NOK(CatalogManagerUtil::AreLeadersOnPreferredOnly(ts_descs, replication_info));
385
386
1
  ts4->set_leader_count(0);
387
1
  ASSERT_OK(CatalogManagerUtil::AreLeadersOnPreferredOnly(ts_descs, replication_info));
388
389
1
  ts0->set_leader_count(12);
390
1
  ts1->set_leader_count(4);
391
1
  ASSERT_OK(CatalogManagerUtil::AreLeadersOnPreferredOnly(ts_descs, replication_info));
392
1
}
393
394
1
TEST(TestCatalogManagerEnterprise, TestLeaderLoadBalancedReadOnly) {
395
  // Note that this is essentially using transaction_tables_use_preferred_zones = true
396
1
  ReplicationInfoPB replication_info;
397
1
  SetupClusterConfigEnt({"a", "b", "c"} /* az list */, {"d"} /* read only */,
398
1
                        {} /* affinitized leaders */, &replication_info);
399
400
1
  std::shared_ptr<TSDescriptor> ts0 = SetupTSEnt("0000", "a", "");
401
1
  std::shared_ptr<TSDescriptor> ts1 = SetupTSEnt("1111", "b", "");
402
1
  std::shared_ptr<TSDescriptor> ts2 = SetupTSEnt("2222", "c", "");
403
1
  std::shared_ptr<TSDescriptor> ts3 = SetupTSEnt("3333", "d", "read_only");
404
405
1
  ASSERT_TRUE(ts0->IsAcceptingLeaderLoad(replication_info));
406
1
  ASSERT_TRUE(ts1->IsAcceptingLeaderLoad(replication_info));
407
1
  ASSERT_TRUE(ts2->IsAcceptingLeaderLoad(replication_info));
408
1
  ASSERT_FALSE(ts3->IsAcceptingLeaderLoad(replication_info));
409
410
1
  TSDescriptorVector ts_descs = {ts0, ts1, ts2, ts3};
411
412
1
  ts0->set_leader_count(8);
413
1
  ts1->set_leader_count(8);
414
1
  ts2->set_leader_count(8);
415
1
  ts3->set_leader_count(0);
416
1
  ASSERT_OK(CatalogManagerUtil::AreLeadersOnPreferredOnly(ts_descs, replication_info));
417
418
1
  ts3->set_leader_count(1);
419
1
  ASSERT_NOK(CatalogManagerUtil::AreLeadersOnPreferredOnly(ts_descs, replication_info));
420
1
}
421
422
1
TEST(TestCatalogManagerEnterprise, TestLoadBalancedReadOnlySameAz) {
423
1
  ReplicationInfoPB replication_info;
424
1
  SetupClusterConfigEnt({"a"} /* az list */, {"a"} /* read only */,
425
1
                        {} /* affinitized leaders */, &replication_info);
426
1
  std::shared_ptr<TSDescriptor> ts0 = SetupTSEnt("0000", "a", "");
427
1
  std::shared_ptr<TSDescriptor> ts1 = SetupTSEnt("1111", "a", "");
428
1
  std::shared_ptr<TSDescriptor> ts2 = SetupTSEnt("2222", "a", "read_only");
429
1
  std::shared_ptr<TSDescriptor> ts3 = SetupTSEnt("3333", "a", "read_only");
430
431
1
  TSDescriptorVector ts_descs = {ts0, ts1, ts2, ts3};
432
433
1
  ts0->set_num_live_replicas(6);
434
1
  ts1->set_num_live_replicas(6);
435
1
  ts2->set_num_live_replicas(12);
436
1
  ts3->set_num_live_replicas(12);
437
1
  ASSERT_OK(CatalogManagerUtil::IsLoadBalanced(ts_descs));
438
439
1
  ts0->set_num_live_replicas(6);
440
1
  ts1->set_num_live_replicas(6);
441
1
  ts2->set_num_live_replicas(8);
442
1
  ts3->set_num_live_replicas(4);
443
1
  ASSERT_NOK(CatalogManagerUtil::IsLoadBalanced(ts_descs));
444
1
}
445
446
} // namespace enterprise
447
} // namespace master
448
} // namespace yb