1 /*
2   Copyright (c) DataStax, Inc.
3 
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7 
8   http://www.apache.org/licenses/LICENSE-2.0
9 
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15 */
16 
17 #include "unit.hpp"
18 
19 #include "query_request.hpp"
20 #include "session.hpp"
21 #include "tracing_data_handler.hpp"
22 
23 using namespace datastax::internal::core;
24 
25 class TracingUnitTest : public Unit {
26 public:
TearDown()27   void TearDown() {
28     ASSERT_TRUE(session.close()->wait_for(WAIT_FOR_TIME));
29     Unit::TearDown();
30   }
31 
connect(const Config & config=Config ())32   void connect(const Config& config = Config()) {
33     Config temp(config);
34     temp.contact_points().push_back(Address("127.0.0.1", 9042));
35     Future::Ptr connect_future(session.connect(temp));
36     ASSERT_TRUE(connect_future->wait_for(WAIT_FOR_TIME))
37         << "Timed out waiting for session to connect";
38     ASSERT_FALSE(connect_future->error()) << cass_error_desc(connect_future->error()->code) << ": "
39                                           << connect_future->error()->message;
40   }
41 
42   Session session;
43 };
44 
TEST_F(TracingUnitTest,Simple)45 TEST_F(TracingUnitTest, Simple) {
46   mockssandra::SimpleRequestHandlerBuilder builder;
47   builder.on(mockssandra::OPCODE_QUERY)
48       .system_local()
49       .system_peers()
50       .system_traces()
51       .empty_rows_result(1);
52   mockssandra::SimpleCluster cluster(builder.build());
53   ASSERT_EQ(cluster.start_all(), 0);
54 
55   connect();
56 
57   Statement::Ptr request(new QueryRequest("blah", 0));
58   request->set_tracing(true);
59 
60   ResponseFuture::Ptr future(session.execute(Request::ConstPtr(request)));
61   future->wait();
62 
63   ASSERT_TRUE(future->response());
64   EXPECT_TRUE(future->response()->has_tracing_id());
65 
66   CassUuid tracing_id(future->response()->tracing_id());
67   EXPECT_NE(tracing_id.time_and_version, 0u);
68 }
69 
TEST_F(TracingUnitTest,DataNotAvailble)70 TEST_F(TracingUnitTest, DataNotAvailble) {
71   mockssandra::SimpleRequestHandlerBuilder builder;
72   builder.on(mockssandra::OPCODE_QUERY)
73       .system_local()
74       .system_peers()
75       .is_query(SELECT_TRACES_SESSION)
76       .then(mockssandra::Action::Builder().empty_rows_result(0)) // Send back an empty row result
77       .empty_rows_result(1);
78   mockssandra::SimpleCluster cluster(builder.build());
79   ASSERT_EQ(cluster.start_all(), 0);
80 
81   connect();
82 
83   Statement::Ptr request(new QueryRequest("blah", 0));
84   request->set_tracing(true);
85 
86   add_logging_critera("Tracing data not available after 15 ms");
87 
88   ResponseFuture::Ptr future(session.execute(Request::ConstPtr(request)));
89   future->wait();
90 
91   ASSERT_TRUE(future->response());
92   EXPECT_TRUE(future->response()->has_tracing_id());
93 
94   CassUuid tracing_id(future->response()->tracing_id());
95   EXPECT_NE(tracing_id.time_and_version, 0u);
96 
97   EXPECT_GT(logging_criteria_count(), 0);
98 }
99 
TEST_F(TracingUnitTest,RequestTimeout)100 TEST_F(TracingUnitTest, RequestTimeout) {
101   mockssandra::SimpleRequestHandlerBuilder builder;
102   builder.on(mockssandra::OPCODE_QUERY)
103       .system_local()
104       .system_peers()
105       .is_query(SELECT_TRACES_SESSION)
106       .then(mockssandra::Action::Builder().no_result()) // Don't send back a response
107       .empty_rows_result(1);
108   mockssandra::SimpleCluster cluster(builder.build());
109   ASSERT_EQ(cluster.start_all(), 0);
110 
111   Config config;
112   config.set_max_tracing_wait_time_ms(500);
113   connect(config);
114 
115   Statement::Ptr request(new QueryRequest("blah", 0));
116   request->set_request_timeout_ms(100);
117   request->set_tracing(true);
118 
119   add_logging_critera("A query timeout occurred waiting for tracing data to become available");
120 
121   ResponseFuture::Ptr future(session.execute(Request::ConstPtr(request)));
122   future->wait();
123 
124   ASSERT_TRUE(future->response());
125   EXPECT_TRUE(future->response()->has_tracing_id());
126 
127   CassUuid tracing_id(future->response()->tracing_id());
128   EXPECT_NE(tracing_id.time_and_version, 0u);
129 
130   EXPECT_GT(logging_criteria_count(), 0);
131 }
132 
TEST_F(TracingUnitTest,QueryError)133 TEST_F(TracingUnitTest, QueryError) {
134   mockssandra::SimpleRequestHandlerBuilder builder;
135   builder.on(mockssandra::OPCODE_QUERY)
136       .system_local()
137       .system_peers()
138       .is_query(SELECT_TRACES_SESSION)
139       .then(mockssandra::Action::Builder().error(mockssandra::ERROR_INVALID_QUERY, "Invalid query"))
140       .empty_rows_result(1);
141   mockssandra::SimpleCluster cluster(builder.build());
142   ASSERT_EQ(cluster.start_all(), 0);
143 
144   connect();
145 
146   Statement::Ptr request(new QueryRequest("blah", 0));
147   request->set_tracing(true);
148 
149   add_logging_critera("Chained error response 'Invalid query' (0x02002200) for query "
150                       "\"SELECT session_id FROM system_traces.sessions WHERE session_id = ?\"");
151 
152   ResponseFuture::Ptr future(session.execute(Request::ConstPtr(request)));
153   future->wait();
154 
155   ASSERT_TRUE(future->response());
156   EXPECT_TRUE(future->response()->has_tracing_id());
157 
158   CassUuid tracing_id(future->response()->tracing_id());
159   EXPECT_NE(tracing_id.time_and_version, 0u);
160 
161   EXPECT_GT(logging_criteria_count(), 0);
162 }
163