/Users/deen/code/yugabyte-db/src/yb/integration-tests/kv_table_ts_failover-test.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) YugaByte, Inc. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
4 | | // in compliance with the License. You may obtain a copy of the License at |
5 | | // |
6 | | // http://www.apache.org/licenses/LICENSE-2.0 |
7 | | // |
8 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
9 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
10 | | // or implied. See the License for the specific language governing permissions and limitations |
11 | | // under the License. |
12 | | // |
13 | | |
14 | | #include <atomic> |
15 | | #include <memory> |
16 | | #include <vector> |
17 | | |
18 | | #include "yb/client/client.h" |
19 | | #include "yb/client/table.h" |
20 | | |
21 | | #include "yb/integration-tests/cluster_verifier.h" |
22 | | #include "yb/integration-tests/external_mini_cluster.h" |
23 | | #include "yb/integration-tests/load_generator.h" |
24 | | #include "yb/integration-tests/yb_table_test_base.h" |
25 | | |
26 | | #include "yb/util/test_util.h" |
27 | | |
28 | | DEFINE_int32(test_num_iter, |
29 | | 1, |
30 | | "Number of iterations for key-value table tablet server failover test"); |
31 | | |
32 | | namespace yb { |
33 | | |
34 | | using std::unique_ptr; |
35 | | |
36 | | using client::YBClient; |
37 | | using client::YBClientBuilder; |
38 | | using client::YBTable; |
39 | | using std::shared_ptr; |
40 | | |
41 | | using integration_tests::YBTableTestBase; |
42 | | |
43 | | class KVTableTsFailoverTest : public YBTableTestBase { |
44 | | public: |
45 | 3 | bool use_external_mini_cluster() override { return true; } |
46 | | |
47 | 1 | bool enable_ysql() override { return NonTsanVsTsan(true, false); } |
48 | | }; |
49 | | |
50 | 1 | TEST_F(KVTableTsFailoverTest, KillTabletServerUnderLoad) { |
51 | 1 | for (int i = 1; i <= FLAGS_test_num_iter; ++i) { |
52 | 1 | std::atomic_bool stop_requested_flag(false); |
53 | 1 | int rows = 1000000; |
54 | 1 | int start_key = 0; |
55 | 1 | int writer_threads = 4; |
56 | 1 | int reader_threads = 4; |
57 | 1 | int value_size_bytes = 16; |
58 | 1 | int max_write_errors = 0; |
59 | 1 | int max_read_errors = 0; |
60 | | |
61 | | // Create two separate clients for read and writes. |
62 | 1 | auto write_client = CreateYBClient(); |
63 | 1 | auto read_client = CreateYBClient(); |
64 | 1 | yb::load_generator::YBSessionFactory write_session_factory(write_client.get(), &table_); |
65 | 1 | yb::load_generator::YBSessionFactory read_session_factory(read_client.get(), &table_); |
66 | | |
67 | 1 | yb::load_generator::MultiThreadedWriter writer(rows, start_key, writer_threads, |
68 | 1 | &write_session_factory, &stop_requested_flag, |
69 | 1 | value_size_bytes, max_write_errors); |
70 | 1 | yb::load_generator::MultiThreadedReader reader(rows, reader_threads, &read_session_factory, |
71 | 1 | writer.InsertionPoint(), writer.InsertedKeys(), |
72 | 1 | writer.FailedKeys(), &stop_requested_flag, |
73 | 1 | value_size_bytes, max_read_errors); |
74 | | |
75 | 1 | writer.Start(); |
76 | | // Having separate write requires adding in write client id to the reader. |
77 | 1 | reader.set_client_id(write_session_factory.ClientId()); |
78 | 1 | reader.Start(); |
79 | | |
80 | 1 | for (int i = 0; i < 3; ++i) { |
81 | 0 | SleepFor(MonoDelta::FromSeconds(5)); |
82 | 0 | LOG(INFO) << "Killing tablet server #" << i; |
83 | 0 | external_mini_cluster()->tablet_server(i)->Shutdown(); |
84 | 0 | LOG(INFO) << "Re-starting tablet server #" << i; |
85 | 0 | ASSERT_OK(external_mini_cluster()->tablet_server(i)->Restart()); |
86 | 0 | ASSERT_OK(external_mini_cluster()->WaitForTabletServerCount(3, MonoDelta::FromSeconds(20))); |
87 | 0 | } |
88 | | |
89 | 1 | stop_requested_flag.store(true); // stop both reader and writer |
90 | 1 | writer.WaitForCompletion(); |
91 | 1 | LOG(INFO) << "Writing complete"; |
92 | | |
93 | 1 | reader.WaitForCompletion(); |
94 | 1 | LOG(INFO) << "Reading complete"; |
95 | | |
96 | 1 | if (FLAGS_test_num_iter > 1) { |
97 | 0 | LOG(INFO) << "Completed iteration " << i << " of the test"; |
98 | 0 | } |
99 | | |
100 | 1 | ASSERT_NO_FATALS(writer.AssertSucceeded()); |
101 | 0 | ASSERT_NO_FATALS(reader.AssertSucceeded()); |
102 | | |
103 | | // Assuming every thread has time to do at least 50 writes. Had to lower this from 100 after |
104 | | // enabling TSAN. |
105 | 0 | LOG(INFO) << "Reads: " << reader.num_reads() << ", writes: " << writer.num_writes(); |
106 | 0 | ASSERT_GE(writer.num_writes(), writer_threads * 50); |
107 | | // Assuming at least 100 reads and 100 writes. |
108 | 0 | ASSERT_GE(reader.num_reads(), 100); |
109 | 0 | ASSERT_GE(writer.num_writes(), 100); |
110 | |
|
111 | 0 | ClusterVerifier cluster_verifier(external_mini_cluster()); |
112 | 0 | ASSERT_NO_FATALS(cluster_verifier.CheckCluster()); |
113 | 0 | ASSERT_NO_FATALS(cluster_verifier.CheckRowCount(table_->name(), ClusterVerifier::EXACTLY, |
114 | 0 | writer.num_writes())); |
115 | 0 | } |
116 | 1 | } |
117 | | |
118 | | } // namespace yb |