public boolean test(List<Span> spans) {
    // v2 returns raw spans in any order, get the root's timestamp or the first timestamp
    long timestamp = 0L;
    for (Span span : spans) {
      if (span.timestampAsLong() == 0L) continue;
      if (span.parentId() == null) {
        timestamp = span.timestampAsLong();
        break;
      }
      if (timestamp == 0L || timestamp > span.timestampAsLong()) {
        timestamp = span.timestampAsLong();
      }
    }
    if (timestamp == 0L ||
      timestamp < (endTs() - lookback()) * 1000 ||
      timestamp > endTs() * 1000) {
      return false;
    }
    boolean testedDuration = minDuration() == null && maxDuration() == null;

    String serviceNameToMatch = serviceName();
    String remoteServiceNameToMatch = remoteServiceName();
    String spanNameToMatch = spanName();
    Map<String, String> annotationQueryRemaining = new LinkedHashMap<>(annotationQuery());

    for (Span span : spans) {
      String localServiceName = span.localServiceName();

      // service name, when present, constrains other queries.
      if (serviceName() == null || serviceName().equals(localServiceName)) {
        serviceNameToMatch = null;
        for (Annotation a : span.annotations()) {
          if ("".equals(annotationQueryRemaining.get(a.value()))) {
            annotationQueryRemaining.remove(a.value());
          }
        }
        for (Map.Entry<String, String> t : span.tags().entrySet()) {
          String value = annotationQueryRemaining.get(t.getKey());
          if (value == null) continue;
          if (value.isEmpty() || value.equals(t.getValue())) {
            annotationQueryRemaining.remove(t.getKey());
          }
        }
        if (remoteServiceNameToMatch != null && remoteServiceNameToMatch.equals(
          span.remoteServiceName())) {
          remoteServiceNameToMatch = null;
        }
        if (spanNameToMatch != null && spanNameToMatch.equals(span.name())) {
          spanNameToMatch = null;
        }
        if (!testedDuration) {
          if (minDuration() != null && maxDuration() != null) {
            testedDuration =
              span.durationAsLong() >= minDuration() && span.durationAsLong() <= maxDuration();
          } else if (minDuration() != null) {
            testedDuration = span.durationAsLong() >= minDuration();
          }
        }
      }
    }
    return (serviceName() == null || serviceNameToMatch == null)
      && remoteServiceNameToMatch == null
      && spanNameToMatch == null
      && annotationQueryRemaining.isEmpty()
      && testedDuration;
  }
Tests the supplied trace against the current request.

<p>This is used when the backend cannot fully refine a trace query.
zipkin/src/main/java/zipkin2/storage/QueryRequest.java