22
22
#include " timer.hpp"
23
23
#include " wait_for_handler.hpp"
24
24
25
+ #include < ostream>
26
+
25
27
using namespace datastax ::internal;
26
28
using namespace datastax ::internal::core;
27
29
30
+ typedef Vector<WaitForHandler::WaitForError> Errors;
31
+
32
+ namespace std {
33
+
34
+ std::ostream& operator <<(std::ostream& os, const Errors& errors) {
35
+ for (Errors::const_iterator it = errors.begin (); it != errors.end (); ++it) {
36
+ if (it != errors.begin ()) os << " , " ;
37
+ os << *it;
38
+ }
39
+ return os;
40
+ }
41
+
42
+ } // namespace std
43
+
28
44
class WaitForHandlerUnitTest : public LoopTest {
29
45
public:
30
46
class TestWaitForHandler : public WaitForHandler {
@@ -35,54 +51,70 @@ class WaitForHandlerUnitTest : public LoopTest {
35
51
: WaitForHandler(
36
52
RequestHandler::Ptr (new RequestHandler(QueryRequest::Ptr(new QueryRequest(" " )),
37
53
ResponseFuture::Ptr(new ResponseFuture()))),
38
- Host::Ptr(new Host(Address())), Response::Ptr(), max_wait_time, retry_wait_time) {}
39
-
40
- virtual RequestCallback::Ptr callback () = 0;
54
+ Host::Ptr(new Host(Address())), Response::Ptr(), max_wait_time, retry_wait_time)
55
+ , count_on_set_(0 )
56
+ , count_on_error_(0 )
57
+ , is_idempotent_(false ) {}
58
+
59
+ Ptr with_is_idempotent (bool is_idempotent) {
60
+ is_idempotent_ = is_idempotent;
61
+ return Ptr (this );
62
+ }
41
63
42
- private:
43
- virtual bool on_set ( const ChainedRequestCallback::Ptr& callback) {
44
- return false ; // Never complete
64
+ Ptr with_expected_error (WaitForHandler::WaitForError error) {
65
+ expected_. push_back (error);
66
+ return Ptr ( this );
45
67
}
46
- };
47
68
48
- class RegularQueryHandler : public TestWaitForHandler {
49
- public:
50
69
virtual RequestCallback::Ptr callback () {
51
70
WaitforRequestVec requests;
52
- requests.push_back (make_request (" local" , " SELECT * FROM system.local WHERE key='local'" ));
53
- requests.push_back (make_request (" peers" , " SELECT * FROM system.peers" ));
71
+ QueryRequest::Ptr table1_request (new QueryRequest (" SELECT * FROM test.table1" ));
72
+ QueryRequest::Ptr table2_request (new QueryRequest (" SELECT * FROM test.table2" ));
73
+ table1_request->set_is_idempotent (is_idempotent_);
74
+ table2_request->set_is_idempotent (is_idempotent_);
75
+ requests.push_back (WaitForRequest (" table1" , table1_request));
76
+ requests.push_back (WaitForRequest (" table2" , table2_request));
54
77
return WaitForHandler::callback (requests);
55
78
}
56
79
57
- private:
58
- virtual void on_error (WaitForError code, const String& message) {
59
- EXPECT_TRUE (WAIT_FOR_ERROR_CONNECTION_CLOSED == code || WAIT_FOR_ERROR_REQUEST_ERROR == code);
60
- }
61
- };
80
+ int count_on_set () const { return count_on_set_; }
62
81
63
- class IdempotentQueryHandler : public TestWaitForHandler {
64
- public:
65
- virtual RequestCallback::Ptr callback () {
66
- WaitforRequestVec requests;
67
- QueryRequest::Ptr local_request (
68
- new QueryRequest (" SELECT * FROM system.local WHERE key='local'" ));
69
- QueryRequest::Ptr peers_request (new QueryRequest (" SELECT * FROM system.peers" ));
70
- local_request->set_is_idempotent (true );
71
- peers_request->set_is_idempotent (true );
72
- requests.push_back (WaitForRequest (" local" , local_request));
73
- requests.push_back (WaitForRequest (" peers" , peers_request));
74
- return WaitForHandler::callback (requests);
82
+ protected:
83
+ virtual bool on_set (const ChainedRequestCallback::Ptr& callback) {
84
+ EXPECT_EQ (0 , count_on_error_); // Set shouldn't be called after an error
85
+ count_on_set_++;
86
+ return false ; // Never complete
75
87
}
76
88
77
- private:
78
89
virtual void on_error (WaitForError code, const String& message) {
79
- EXPECT_TRUE (WAIT_FOR_ERROR_CONNECTION_CLOSED == code ||
80
- WAIT_FOR_ERROR_REQUEST_TIMEOUT == code);
90
+ ASSERT_NE (0 , expected_.size ());
91
+ bool found_expected = false ;
92
+ for (Errors::const_iterator it = expected_.begin (), end = expected_.end ();
93
+ !found_expected && it != end; ++it) {
94
+ if (*it == code) {
95
+ found_expected = true ;
96
+ }
97
+ }
98
+ EXPECT_TRUE (found_expected) << " Expected error codes [ " << expected_
99
+ << " ], but received error " << code;
100
+ count_on_error_++;
81
101
}
102
+
103
+ private:
104
+ Errors expected_;
105
+ int count_on_set_;
106
+ int count_on_error_;
107
+ bool is_idempotent_;
82
108
};
83
109
84
110
void run (const TestWaitForHandler::Ptr& handler, uint64_t timeout = 0 ) {
85
- mockssandra::SimpleCluster cluster (simple ());
111
+ mockssandra::SimpleRequestHandlerBuilder builder;
112
+ run (handler, builder, timeout);
113
+ }
114
+
115
+ void run (const TestWaitForHandler::Ptr& handler,
116
+ mockssandra::SimpleRequestHandlerBuilder& builder, uint64_t timeout = 0 ) {
117
+ mockssandra::SimpleCluster cluster (builder.build ());
86
118
ASSERT_EQ (cluster.start_all (), 0 );
87
119
88
120
handler_ = handler;
@@ -140,17 +172,46 @@ class WaitForHandlerUnitTest : public LoopTest {
140
172
};
141
173
142
174
TEST_F (WaitForHandlerUnitTest, CloseImmediatelyWhileWaiting) {
143
- run (TestWaitForHandler::Ptr (new RegularQueryHandler ()));
175
+ run (TestWaitForHandler::Ptr (new TestWaitForHandler ())
176
+ ->with_expected_error (WaitForHandler::WAIT_FOR_ERROR_REQUEST_ERROR)
177
+ ->with_expected_error (WaitForHandler::WAIT_FOR_ERROR_CONNECTION_CLOSED));
144
178
}
145
179
146
180
TEST_F (WaitForHandlerUnitTest, CloseAfterTimeoutWhileWaiting) {
147
- run (TestWaitForHandler::Ptr (new RegularQueryHandler ()), 500 );
181
+ run (TestWaitForHandler::Ptr (new TestWaitForHandler ())
182
+ ->with_expected_error (WaitForHandler::WAIT_FOR_ERROR_REQUEST_ERROR)
183
+ ->with_expected_error (WaitForHandler::WAIT_FOR_ERROR_CONNECTION_CLOSED),
184
+ 500 );
148
185
}
149
186
150
187
TEST_F (WaitForHandlerUnitTest, CloseIdempotentImmediatelyWhileWaiting) {
151
- run (TestWaitForHandler::Ptr (new IdempotentQueryHandler ()));
188
+ run (TestWaitForHandler::Ptr (new TestWaitForHandler ())
189
+ ->with_is_idempotent (true )
190
+ ->with_expected_error (WaitForHandler::WAIT_FOR_ERROR_REQUEST_TIMEOUT)
191
+ ->with_expected_error (WaitForHandler::WAIT_FOR_ERROR_CONNECTION_CLOSED));
152
192
}
153
193
154
194
TEST_F (WaitForHandlerUnitTest, CloseIdempotentAfterTimeoutWhileWaiting) {
155
- run (TestWaitForHandler::Ptr (new IdempotentQueryHandler ()), 500 );
195
+ run (TestWaitForHandler::Ptr (new TestWaitForHandler ())
196
+ ->with_is_idempotent (true )
197
+ ->with_expected_error (WaitForHandler::WAIT_FOR_ERROR_REQUEST_TIMEOUT)
198
+ ->with_expected_error (WaitForHandler::WAIT_FOR_ERROR_CONNECTION_CLOSED),
199
+ 500 );
200
+ }
201
+
202
+ TEST_F (WaitForHandlerUnitTest, EnsureOnSetNotCalledAfterTimeout) {
203
+ TestWaitForHandler::Ptr handler (
204
+ new TestWaitForHandler (1 )); // Timeout handler before query returns
205
+
206
+ // Make sure the query doesn't complete before the handler times out
207
+ mockssandra::SimpleRequestHandlerBuilder builder;
208
+ builder.on (mockssandra::OPCODE_QUERY)
209
+ .system_local ()
210
+ .system_peers ()
211
+ .wait (200 )
212
+ .empty_rows_result (1 );
213
+
214
+ run (handler->with_expected_error (WaitForHandler::WAIT_FOR_ERROR_TIMEOUT), builder, 500 );
215
+
216
+ EXPECT_EQ (0 , handler->count_on_set ()); // Ensure on_set() never called
156
217
}
0 commit comments