1#include <Common/typeid_cast.h>
2#include <Common/ZooKeeper/ZooKeeper.h>
3#include <Common/ZooKeeper/KeeperException.h>
4#include <Common/StringUtils/StringUtils.h>
5#include <iostream>
6#include <chrono>
7
8#include <gtest/gtest.h>
9
10#include <Common/ShellCommand.h>
11
12
13using namespace DB;
14
15TEST(zkutil, zookeeper_connected)
16{
17 try
18 {
19 auto zookeeper = std::make_unique<zkutil::ZooKeeper>("localhost:2181");
20 zookeeper->exists("/");
21 }
22 catch (...)
23 {
24 std::cerr << "No zookeeper. skip tests." << std::endl;
25 exit(0);
26 }
27}
28
29TEST(zkutil, multi_nice_exception_msg)
30{
31 auto zookeeper = std::make_unique<zkutil::ZooKeeper>("localhost:2181");
32
33 Coordination::Requests ops;
34
35 ASSERT_NO_THROW(
36 zookeeper->tryRemoveRecursive("/clickhouse_test/zkutil_multi");
37
38 ops.emplace_back(zkutil::makeCreateRequest("/clickhouse_test/zkutil_multi", "_", zkutil::CreateMode::Persistent));
39 ops.emplace_back(zkutil::makeCreateRequest("/clickhouse_test/zkutil_multi/a", "_", zkutil::CreateMode::Persistent));
40 zookeeper->multi(ops);
41 );
42
43 try
44 {
45 ops.clear();
46 ops.emplace_back(zkutil::makeCreateRequest("/clickhouse_test/zkutil_multi/c", "_", zkutil::CreateMode::Persistent));
47 ops.emplace_back(zkutil::makeRemoveRequest("/clickhouse_test/zkutil_multi/c", -1));
48 ops.emplace_back(zkutil::makeCreateRequest("/clickhouse_test/zkutil_multi/a", "BadBoy", zkutil::CreateMode::Persistent));
49 ops.emplace_back(zkutil::makeCreateRequest("/clickhouse_test/zkutil_multi/b", "_", zkutil::CreateMode::Persistent));
50 ops.emplace_back(zkutil::makeCreateRequest("/clickhouse_test/zkutil_multi/a", "_", zkutil::CreateMode::Persistent));
51
52 zookeeper->multi(ops);
53 FAIL();
54 }
55 catch (...)
56 {
57 zookeeper->tryRemoveRecursive("/clickhouse_test/zkutil_multi");
58
59 String msg = getCurrentExceptionMessage(false);
60
61 bool msg_has_reqired_patterns = msg.find("#2") != std::string::npos;
62 EXPECT_TRUE(msg_has_reqired_patterns) << msg;
63 }
64}
65
66
67TEST(zkutil, multi_async)
68{
69 auto zookeeper = std::make_unique<zkutil::ZooKeeper>("localhost:2181");
70 Coordination::Requests ops;
71
72 zookeeper->tryRemoveRecursive("/clickhouse_test/zkutil_multi");
73
74 {
75 ops.clear();
76 auto fut = zookeeper->asyncMulti(ops);
77 }
78
79 {
80 ops.clear();
81 ops.emplace_back(zkutil::makeCreateRequest("/clickhouse_test/zkutil_multi", "", zkutil::CreateMode::Persistent));
82 ops.emplace_back(zkutil::makeCreateRequest("/clickhouse_test/zkutil_multi/a", "", zkutil::CreateMode::Persistent));
83
84 auto fut = zookeeper->tryAsyncMulti(ops);
85 ops.clear();
86
87 auto res = fut.get();
88 ASSERT_TRUE(res.error == Coordination::ZOK);
89 ASSERT_EQ(res.responses.size(), 2);
90 }
91
92 EXPECT_ANY_THROW
93 (
94 std::vector<std::future<Coordination::MultiResponse>> futures;
95
96 for (size_t i = 0; i < 10000; ++i)
97 {
98 ops.clear();
99 ops.emplace_back(zkutil::makeRemoveRequest("/clickhouse_test/zkutil_multi", -1));
100 ops.emplace_back(zkutil::makeCreateRequest("/clickhouse_test/zkutil_multi", "_", zkutil::CreateMode::Persistent));
101 ops.emplace_back(zkutil::makeCheckRequest("/clickhouse_test/zkutil_multi", -1));
102 ops.emplace_back(zkutil::makeSetRequest("/clickhouse_test/zkutil_multi", "xxx", 42));
103 ops.emplace_back(zkutil::makeCreateRequest("/clickhouse_test/zkutil_multi/a", "_", zkutil::CreateMode::Persistent));
104
105 futures.emplace_back(zookeeper->asyncMulti(ops));
106 }
107
108 futures[0].get();
109 );
110
111 /// Check there are no segfaults for remaining 999 futures
112 using namespace std::chrono_literals;
113 std::this_thread::sleep_for(1s);
114
115 {
116 ops.clear();
117 ops.emplace_back(zkutil::makeCreateRequest("/clickhouse_test/zkutil_multi", "_", zkutil::CreateMode::Persistent));
118 ops.emplace_back(zkutil::makeCreateRequest("/clickhouse_test/zkutil_multi/a", "_", zkutil::CreateMode::Persistent));
119
120 auto fut = zookeeper->tryAsyncMulti(ops);
121 ops.clear();
122
123 auto res = fut.get();
124 ASSERT_TRUE(res.error == Coordination::ZNODEEXISTS);
125 ASSERT_EQ(res.responses.size(), 2);
126 }
127}
128
129TEST(zkutil, watch_get_children_with_chroot)
130{
131 try
132 {
133 const String zk_server = "localhost:2181";
134 const String prefix = "/clickhouse_test/zkutil/watch_get_children_with_chroot";
135
136 /// Create chroot node firstly
137 auto zookeeper = std::make_unique<zkutil::ZooKeeper>(zk_server);
138 zookeeper->createAncestors(prefix + "/");
139 zookeeper = std::make_unique<zkutil::ZooKeeper>(zk_server, "",
140 zkutil::DEFAULT_SESSION_TIMEOUT,
141 zkutil::DEFAULT_OPERATION_TIMEOUT,
142 prefix);
143
144 String queue_path = "/queue";
145 zookeeper->tryRemoveRecursive(queue_path);
146 zookeeper->createAncestors(queue_path + "/");
147
148 zkutil::EventPtr event = std::make_shared<Poco::Event>();
149 zookeeper->getChildren(queue_path, nullptr, event);
150 {
151 auto zookeeper2 = std::make_unique<zkutil::ZooKeeper>(zk_server, "",
152 zkutil::DEFAULT_SESSION_TIMEOUT,
153 zkutil::DEFAULT_OPERATION_TIMEOUT,
154 prefix);
155 zookeeper2->create(queue_path + "/children-", "", zkutil::CreateMode::PersistentSequential);
156 }
157 event->wait();
158 }
159 catch (...)
160 {
161 std::cerr << getCurrentExceptionMessage(true);
162 throw;
163 }
164}
165
166TEST(zkutil, multi_create_sequential)
167{
168 try
169 {
170 const String zk_server = "localhost:2181";
171 const String prefix = "/clickhouse_test/zkutil";
172
173 /// Create chroot node firstly
174 auto zookeeper = std::make_unique<zkutil::ZooKeeper>(zk_server);
175 zookeeper->createAncestors(prefix + "/");
176 zookeeper = std::make_unique<zkutil::ZooKeeper>(zk_server, "",
177 zkutil::DEFAULT_SESSION_TIMEOUT,
178 zkutil::DEFAULT_OPERATION_TIMEOUT,
179 "/clickhouse_test");
180
181 String base_path = "/multi_create_sequential";
182 zookeeper->tryRemoveRecursive(base_path);
183 zookeeper->createAncestors(base_path + "/");
184
185 Coordination::Requests ops;
186 String sequential_node_prefix = base_path + "/queue-";
187 ops.emplace_back(zkutil::makeCreateRequest(sequential_node_prefix, "", zkutil::CreateMode::EphemeralSequential));
188 auto results = zookeeper->multi(ops);
189 const auto & sequential_node_result_op = dynamic_cast<const Coordination::CreateResponse &>(*results.at(0));
190
191 EXPECT_FALSE(sequential_node_result_op.path_created.empty());
192 EXPECT_GT(sequential_node_result_op.path_created.length(), sequential_node_prefix.length());
193 EXPECT_EQ(sequential_node_result_op.path_created.substr(0, sequential_node_prefix.length()), sequential_node_prefix);
194 }
195 catch (...)
196 {
197 std::cerr << getCurrentExceptionMessage(false);
198 throw;
199 }
200}
201
202
203
204