Skip to content

Commit f9c9f6a

Browse files
committed
Tracing: added abstract-based unit tests
These tests verify that the span tree structure is valid and that spans are filled with tags of proper content, by providing a mock implementation of TracingInfo.
1 parent f40dcfe commit f9c9f6a

File tree

3 files changed

+744
-0
lines changed

3 files changed

+744
-0
lines changed
Lines changed: 360 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,360 @@
1+
/*
2+
* Copyright (C) 2021 ScyllaDB
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+
package com.datastax.driver.core.tracing;
18+
19+
import static org.junit.Assert.assertNotNull;
20+
import static org.testng.Assert.assertEquals;
21+
import static org.testng.Assert.assertNotEquals;
22+
import static org.testng.Assert.assertNull;
23+
import static org.testng.Assert.assertTrue;
24+
25+
import com.datastax.driver.core.BoundStatement;
26+
import com.datastax.driver.core.CCMTestsSupport;
27+
import com.datastax.driver.core.ConsistencyLevel;
28+
import com.datastax.driver.core.PreparedStatement;
29+
import com.datastax.driver.core.ResultSet;
30+
import com.datastax.driver.core.Session;
31+
import com.datastax.driver.core.SimpleStatement;
32+
import com.datastax.driver.core.policies.DefaultRetryPolicy;
33+
import com.datastax.driver.core.policies.FallthroughRetryPolicy;
34+
import com.datastax.driver.core.policies.NoSpeculativeExecutionPolicy;
35+
import com.datastax.driver.core.policies.PagingOptimizingLoadBalancingPolicy;
36+
import java.nio.ByteBuffer;
37+
import java.util.ArrayList;
38+
import java.util.Collection;
39+
import java.util.concurrent.ExecutionException;
40+
import org.testng.annotations.Test;
41+
42+
public class BasicTracingTest extends CCMTestsSupport {
43+
private static TestTracingInfoFactory testTracingInfoFactory;
44+
private Session session;
45+
46+
@Override
47+
public void onTestContextInitialized() {
48+
initializeTestTracing();
49+
session.execute("USE " + keyspace);
50+
session.execute("DROP TABLE IF EXISTS t");
51+
session.execute("CREATE TABLE t (k int PRIMARY KEY, v int)");
52+
session.execute("CREATE TABLE blobs (k int PRIMARY KEY, v blob)");
53+
session.execute("INSERT INTO t(k, v) VALUES (2, 3)");
54+
session.execute("INSERT INTO t(k, v) VALUES (1, 7)");
55+
session.execute("INSERT INTO t(k, v) VALUES (5, 7)");
56+
session.execute("INSERT INTO t(k, v) VALUES (6, 7)");
57+
session.execute("INSERT INTO t(k, v) VALUES (7, 7)");
58+
session.execute("INSERT INTO t(k, v) VALUES (8, 7)");
59+
session.execute("INSERT INTO t(k, v) VALUES (9, 7)");
60+
session.execute("INSERT INTO t(k, v) VALUES (10, 7)");
61+
62+
Collection<TracingInfo> spans = testTracingInfoFactory.getSpans();
63+
spans.clear();
64+
}
65+
66+
@Test(groups = "short")
67+
public void simpleTracingTest() {
68+
session.execute("INSERT INTO t(k, v) VALUES (4, 5)");
69+
70+
Collection<TracingInfo> spans = testTracingInfoFactory.getSpans();
71+
assertNotEquals(spans.size(), 0);
72+
73+
TracingInfo rootSpan = getRoot(spans);
74+
assertTrue(rootSpan instanceof TestTracingInfo);
75+
TestTracingInfo root = (TestTracingInfo) rootSpan;
76+
77+
assertTrue(root.isSpanStarted());
78+
assertTrue(root.isSpanFinished());
79+
assertEquals(root.getStatusCode(), TracingInfo.StatusCode.OK);
80+
81+
spans.clear();
82+
}
83+
84+
@Test(groups = "short")
85+
public void tagsInsertTest() {
86+
PreparedStatement prepared = session.prepare("INSERT INTO blobs(k, v) VALUES (?, ?)");
87+
88+
Collection<TracingInfo> prepareSpans = testTracingInfoFactory.getSpans();
89+
assertNotEquals(prepareSpans.size(), 0);
90+
assertTrue(getRoot(prepareSpans) instanceof TestTracingInfo);
91+
prepareSpans.clear();
92+
93+
BoundStatement bound = prepared.bind(1, ByteBuffer.wrap("\n\0\n".getBytes()));
94+
session.execute(bound);
95+
96+
Collection<TracingInfo> spans = testTracingInfoFactory.getSpans();
97+
assertNotEquals(spans.size(), 0);
98+
99+
TracingInfo rootSpan = getRoot(spans);
100+
assertTrue(rootSpan instanceof TestTracingInfo);
101+
TestTracingInfo root = (TestTracingInfo) rootSpan;
102+
103+
assertTrue(root.isSpanStarted());
104+
assertTrue(root.isSpanFinished());
105+
assertEquals(root.getStatusCode(), TracingInfo.StatusCode.OK);
106+
107+
// these tags should be set for request span
108+
assertEquals(root.getStatementType(), "prepared");
109+
assertNull(root.getBatchSize());
110+
assertEquals(root.getConsistencyLevel(), ConsistencyLevel.ONE);
111+
assertNull(root.getRowsCount()); // no rows are returned in INSERT
112+
assertTrue(root.getLoadBalancingPolicy() instanceof PagingOptimizingLoadBalancingPolicy);
113+
assertTrue(root.getSpeculativeExecutionPolicy() instanceof NoSpeculativeExecutionPolicy);
114+
assertTrue(root.getRetryPolicy() instanceof DefaultRetryPolicy);
115+
assertNull(root.getFetchSize()); // fetch size was not explicitly set for this statement
116+
assertNull(root.getHasMorePages()); // no paging are returned in INSERT
117+
assertNull(root.getStatement()); // because of precision level NORMAL
118+
// these are tags specific to bound statement
119+
assertEquals(root.getKeyspace(), keyspace);
120+
assertEquals(root.getBoundValues(), "k=1, v=0x0A000A"); // "\n\0\n"
121+
assertEquals(root.getPartitionKey(), "k=1");
122+
assertEquals(root.getTable(), "blobs");
123+
124+
// these tags should not be set for request span
125+
assertNull(root.getPeerName());
126+
assertNull(root.getPeerIP());
127+
assertNull(root.getPeerPort());
128+
assertNull(root.getAttemptCount());
129+
130+
ArrayList<TracingInfo> speculativeExecutions = getChildren(spans, root);
131+
assertTrue(speculativeExecutions.size() > 0);
132+
133+
for (TracingInfo speculativeExecutionSpan : speculativeExecutions) {
134+
assertTrue(speculativeExecutionSpan instanceof TestTracingInfo);
135+
TestTracingInfo tracingInfo = (TestTracingInfo) speculativeExecutionSpan;
136+
137+
// these tags should not be set for speculative execution span
138+
assertNull(tracingInfo.getStatementType());
139+
assertNull(tracingInfo.getBatchSize());
140+
assertNull(tracingInfo.getConsistencyLevel());
141+
assertNull(tracingInfo.getRowsCount());
142+
assertNull(tracingInfo.getLoadBalancingPolicy());
143+
assertNull(tracingInfo.getRetryPolicy());
144+
assertNull(tracingInfo.getFetchSize());
145+
assertNull(tracingInfo.getHasMorePages());
146+
assertNull(tracingInfo.getStatement());
147+
assertNull(tracingInfo.getPeerName());
148+
assertNull(tracingInfo.getPeerIP());
149+
assertNull(tracingInfo.getPeerPort());
150+
// these are tags specific to bound statement
151+
assertNull(tracingInfo.getKeyspace());
152+
assertNull(tracingInfo.getPartitionKey());
153+
assertNull(tracingInfo.getTable());
154+
155+
// this tag should be set for speculative execution span
156+
assertTrue(tracingInfo.getAttemptCount() >= 1);
157+
}
158+
159+
ArrayList<TracingInfo> attempts = new ArrayList<TracingInfo>();
160+
for (TracingInfo tracingInfo : speculativeExecutions) {
161+
attempts.addAll(getChildren(spans, tracingInfo));
162+
}
163+
assertTrue(attempts.size() > 0);
164+
165+
for (TracingInfo attemptSpan : attempts) {
166+
assertTrue(attemptSpan instanceof TestTracingInfo);
167+
TestTracingInfo tracingInfo = (TestTracingInfo) attemptSpan;
168+
169+
// these tags should not be set for attempt span
170+
assertNull(tracingInfo.getStatementType());
171+
assertNull(tracingInfo.getBatchSize());
172+
assertNull(tracingInfo.getConsistencyLevel());
173+
assertNull(tracingInfo.getRowsCount());
174+
assertNull(tracingInfo.getLoadBalancingPolicy());
175+
assertNull(tracingInfo.getRetryPolicy());
176+
assertNull(tracingInfo.getFetchSize());
177+
assertNull(tracingInfo.getHasMorePages());
178+
assertNull(tracingInfo.getStatement());
179+
assertNull(tracingInfo.getAttemptCount());
180+
// these are tags specific to bound statement
181+
assertNull(tracingInfo.getKeyspace());
182+
assertNull(tracingInfo.getPartitionKey());
183+
assertNull(tracingInfo.getTable());
184+
185+
// these tags should be set for attempt span
186+
assertNotNull(tracingInfo.getPeerName());
187+
assertNotNull(tracingInfo.getPeerIP());
188+
assertNotNull(tracingInfo.getPeerPort());
189+
assertTrue(tracingInfo.getPeerPort() >= 0 && tracingInfo.getPeerPort() <= 65535);
190+
}
191+
192+
spans.clear();
193+
}
194+
195+
@Test(groups = "short")
196+
public void tagsSelectTest() {
197+
SimpleStatement s = new SimpleStatement("SELECT k FROM t WHERE v = 7 ALLOW FILTERING");
198+
s.setFetchSize(2);
199+
s.setIdempotent(true);
200+
s.setRetryPolicy(FallthroughRetryPolicy.INSTANCE);
201+
s.setConsistencyLevel(ConsistencyLevel.QUORUM);
202+
203+
final Collection<TracingInfo> spans = testTracingInfoFactory.getSpans();
204+
class SpanChecks {
205+
int totalRows = 0;
206+
207+
void checkTotalCount() {
208+
assertEquals(totalRows, 7);
209+
}
210+
211+
void checkAssertions(boolean hasMorePages) {
212+
assertEquals(spans.size(), 3);
213+
214+
TracingInfo rootSpan = getRoot(spans);
215+
assertTrue(rootSpan instanceof TestTracingInfo);
216+
TestTracingInfo root = (TestTracingInfo) rootSpan;
217+
218+
assertTrue(root.isSpanStarted());
219+
assertTrue(root.isSpanFinished());
220+
assertEquals(root.getStatusCode(), TracingInfo.StatusCode.OK);
221+
222+
// these tags should be set for request span
223+
assertEquals(root.getStatementType(), "regular");
224+
assertNull(root.getBatchSize());
225+
assertEquals(root.getConsistencyLevel(), ConsistencyLevel.QUORUM);
226+
assertNotNull(root.getRowsCount());
227+
totalRows += root.getRowsCount();
228+
assertTrue(root.getLoadBalancingPolicy() instanceof PagingOptimizingLoadBalancingPolicy);
229+
assertTrue(root.getSpeculativeExecutionPolicy() instanceof NoSpeculativeExecutionPolicy);
230+
assertTrue(root.getRetryPolicy() == FallthroughRetryPolicy.INSTANCE);
231+
assertEquals(root.getFetchSize(), new Integer(2));
232+
assertEquals(root.getHasMorePages(), new Boolean(hasMorePages));
233+
assertNull(root.getStatement()); // because of precision level NORMAL
234+
235+
// these are tags specific to bound statement
236+
assertNull(root.getKeyspace());
237+
assertNull(root.getPartitionKey());
238+
assertNull(root.getTable());
239+
240+
// these tags should not be set for request span
241+
assertNull(root.getPeerName());
242+
assertNull(root.getPeerIP());
243+
assertNull(root.getPeerPort());
244+
assertNull(root.getAttemptCount());
245+
246+
ArrayList<TracingInfo> speculativeExecutions = getChildren(spans, root);
247+
assertTrue(speculativeExecutions.size() > 0);
248+
249+
for (TracingInfo speculativeExecutionSpan : speculativeExecutions) {
250+
assertTrue(speculativeExecutionSpan instanceof TestTracingInfo);
251+
TestTracingInfo tracingInfo = (TestTracingInfo) speculativeExecutionSpan;
252+
253+
// these tags should not be set for speculative execution span
254+
assertNull(tracingInfo.getStatementType());
255+
assertNull(tracingInfo.getBatchSize());
256+
assertNull(tracingInfo.getConsistencyLevel());
257+
assertNull(tracingInfo.getRowsCount());
258+
assertNull(tracingInfo.getLoadBalancingPolicy());
259+
assertNull(tracingInfo.getRetryPolicy());
260+
assertNull(tracingInfo.getFetchSize());
261+
assertNull(tracingInfo.getHasMorePages());
262+
assertNull(tracingInfo.getStatement());
263+
assertNull(tracingInfo.getPeerName());
264+
assertNull(tracingInfo.getPeerIP());
265+
assertNull(tracingInfo.getPeerPort());
266+
// these are tags specific to bound statement
267+
assertNull(tracingInfo.getKeyspace());
268+
assertNull(tracingInfo.getPartitionKey());
269+
assertNull(tracingInfo.getTable());
270+
271+
// this tag should be set for speculative execution span
272+
assertTrue(tracingInfo.getAttemptCount() >= 1);
273+
}
274+
275+
ArrayList<TracingInfo> attempts = new ArrayList<TracingInfo>();
276+
for (TracingInfo tracingInfo : speculativeExecutions) {
277+
attempts.addAll(getChildren(spans, tracingInfo));
278+
}
279+
assertTrue(attempts.size() > 0);
280+
281+
for (TracingInfo attemptSpan : attempts) {
282+
assertTrue(attemptSpan instanceof TestTracingInfo);
283+
TestTracingInfo tracingInfo = (TestTracingInfo) attemptSpan;
284+
285+
// these tags should not be set for attempt span
286+
assertNull(tracingInfo.getStatementType());
287+
assertNull(tracingInfo.getBatchSize());
288+
assertNull(tracingInfo.getConsistencyLevel());
289+
assertNull(tracingInfo.getRowsCount());
290+
assertNull(tracingInfo.getLoadBalancingPolicy());
291+
assertNull(tracingInfo.getRetryPolicy());
292+
assertNull(tracingInfo.getFetchSize());
293+
assertNull(tracingInfo.getHasMorePages());
294+
assertNull(tracingInfo.getStatement());
295+
assertNull(tracingInfo.getAttemptCount());
296+
// these are tags specific to bound statement
297+
assertNull(tracingInfo.getKeyspace());
298+
assertNull(tracingInfo.getPartitionKey());
299+
assertNull(tracingInfo.getTable());
300+
301+
// these tags should be set for attempt span
302+
assertNotNull(tracingInfo.getPeerName());
303+
assertNotNull(tracingInfo.getPeerIP());
304+
assertNotNull(tracingInfo.getPeerPort());
305+
assertTrue(tracingInfo.getPeerPort() >= 0 && tracingInfo.getPeerPort() <= 65535);
306+
}
307+
308+
spans.clear();
309+
}
310+
}
311+
312+
SpanChecks spanChecks = new SpanChecks();
313+
314+
try {
315+
ResultSet rs = session.execute(s);
316+
317+
while (!rs.isFullyFetched()) {
318+
spanChecks.checkAssertions(true);
319+
rs.fetchMoreResults().get();
320+
}
321+
spanChecks.checkAssertions(false);
322+
323+
} catch (InterruptedException e) {
324+
assert false : "InterruptedException";
325+
} catch (ExecutionException e) {
326+
assert false : "ExecutionException";
327+
}
328+
spanChecks.checkTotalCount();
329+
}
330+
331+
private void initializeTestTracing() {
332+
testTracingInfoFactory = new TestTracingInfoFactory(PrecisionLevel.NORMAL);
333+
cluster().setTracingInfoFactory(testTracingInfoFactory);
334+
session = cluster().connect();
335+
}
336+
337+
private TracingInfo getRoot(Collection<TracingInfo> spans) {
338+
TracingInfo root = null;
339+
for (TracingInfo tracingInfo : spans) {
340+
if (tracingInfo instanceof TestTracingInfo
341+
&& ((TestTracingInfo) tracingInfo).getParent() == null) {
342+
assertNull(root); // There should be only one root.
343+
root = tracingInfo;
344+
}
345+
}
346+
347+
return root;
348+
}
349+
350+
private ArrayList<TracingInfo> getChildren(Collection<TracingInfo> spans, TracingInfo parent) {
351+
ArrayList<TracingInfo> children = new ArrayList<TracingInfo>();
352+
for (TracingInfo tracingInfo : spans) {
353+
if (tracingInfo instanceof TestTracingInfo
354+
&& ((TestTracingInfo) tracingInfo).getParent() == parent) {
355+
children.add(tracingInfo);
356+
}
357+
}
358+
return children;
359+
}
360+
}

0 commit comments

Comments
 (0)