@Test void skipsRedundantIndexingInATrace(TestInfo testInfo) throws Exception {
    String testSuffix = testSuffix(testInfo);
    Span[] trace = new Span[101];
    trace[0] = newClientSpan(testSuffix).toBuilder().kind(SERVER).build();

    IntStream.range(0, 100).forEach(i -> trace[i + 1] = Span.newBuilder()
      .traceId(trace[0].traceId())
      .parentId(trace[0].id())
      .id(i + 1)
      .name("get")
      .kind(Span.Kind.CLIENT)
      .localEndpoint(trace[0].localEndpoint())
      .timestamp(
        trace[0].timestampAsLong() + i * 1000L) // all peer span timestamps happen 1ms later
      .duration(10L)
      .build());

    accept(trace);
    assertThat(rowCountForTraceByServiceSpan(storage))
      .isGreaterThanOrEqualTo(4L);
    assertThat(rowCountForTraceByServiceSpan(storage))
      .isGreaterThanOrEqualTo(4L);

    CassandraSpanConsumer withoutStrictTraceId = new CassandraSpanConsumer(
      storage.session(), storage.metadata(),
      false /* strictTraceId */, storage.searchEnabled,
      storage.autocompleteKeys, storage.autocompleteTtl, storage.autocompleteCardinality
    );

    // sanity check base case
    withoutStrictTraceId.accept(List.of(trace)).execute();
    blockWhileInFlight();

    assertThat(rowCountForTraceByServiceSpan(storage))
      .isGreaterThanOrEqualTo(120L); // TODO: magic number
    assertThat(rowCountForTraceByServiceSpan(storage))
      .isGreaterThanOrEqualTo(120L);
  }
Simulates a trace with a step pattern, where each span starts a millisecond after the prior
one. The consumer code optimizes index inserts to only represent the interval represented by
the trace as opposed to each individual timestamp.
zipkin-storage/cassandra/src/test/java/zipkin2/storage/cassandra/ITSpanConsumer.java