mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-17 10:25:15 +00:00
* EQL: case sensitivity aware integration testing (#58624) * Add DataLoader * Rewrite case sensitivity settings: NULL -> run both case sensitive and insensitive tests TRUE -> run case sensitive test only FALSE -> run case insensitive test only * Rename test_queries_supported * Add more toml tests from the Python client Co-authored-by: Ross Wolf <31489089+rw-access@users.noreply.github.com> (cherry picked from commit 34d383421599f060a5c083b40df35f135de49e39)
This commit is contained in:
parent
be20aacec3
commit
3cb8f54f28
@ -41,6 +41,8 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
|
||||
private String timestampField = "@timestamp";
|
||||
private String eventCategoryField = "event.category";
|
||||
private String implicitJoinKeyField = "agent.id";
|
||||
private boolean isCaseSensitive = true;
|
||||
|
||||
private int fetchSize = 50;
|
||||
private SearchAfterBuilder searchAfterBuilder;
|
||||
private String query;
|
||||
@ -56,6 +58,7 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
|
||||
static final String KEY_TIEBREAKER_FIELD = "tiebreaker_field";
|
||||
static final String KEY_EVENT_CATEGORY_FIELD = "event_category_field";
|
||||
static final String KEY_IMPLICIT_JOIN_KEY_FIELD = "implicit_join_key_field";
|
||||
static final String KEY_CASE_SENSITIVE = "case_sensitive";
|
||||
static final String KEY_SIZE = "size";
|
||||
static final String KEY_SEARCH_AFTER = "search_after";
|
||||
static final String KEY_QUERY = "query";
|
||||
@ -88,6 +91,8 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
|
||||
builder.array(KEY_SEARCH_AFTER, searchAfterBuilder.getSortValues());
|
||||
}
|
||||
|
||||
builder.field(KEY_CASE_SENSITIVE, isCaseSensitive());
|
||||
|
||||
builder.field(KEY_QUERY, query);
|
||||
if (waitForCompletionTimeout != null) {
|
||||
builder.field(KEY_WAIT_FOR_COMPLETION_TIMEOUT, waitForCompletionTimeout);
|
||||
@ -152,6 +157,15 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
|
||||
return this.implicitJoinKeyField;
|
||||
}
|
||||
|
||||
public boolean isCaseSensitive() {
|
||||
return this.isCaseSensitive;
|
||||
}
|
||||
|
||||
public EqlSearchRequest isCaseSensitive(boolean isCaseSensitive) {
|
||||
this.isCaseSensitive = isCaseSensitive;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EqlSearchRequest implicitJoinKeyField(String implicitJoinKeyField) {
|
||||
Objects.requireNonNull(implicitJoinKeyField, "implicit join key must not be null");
|
||||
this.implicitJoinKeyField = implicitJoinKeyField;
|
||||
@ -242,6 +256,7 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
|
||||
Objects.equals(implicitJoinKeyField, that.implicitJoinKeyField) &&
|
||||
Objects.equals(searchAfterBuilder, that.searchAfterBuilder) &&
|
||||
Objects.equals(query, that.query) &&
|
||||
Objects.equals(isCaseSensitive, that.isCaseSensitive) &&
|
||||
Objects.equals(waitForCompletionTimeout, that.waitForCompletionTimeout) &&
|
||||
Objects.equals(keepAlive, that.keepAlive) &&
|
||||
Objects.equals(keepOnCompletion, that.keepOnCompletion);
|
||||
@ -255,11 +270,12 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
|
||||
filter,
|
||||
fetchSize,
|
||||
timestampField,
|
||||
tiebreakerField,
|
||||
tiebreakerField,
|
||||
eventCategoryField,
|
||||
implicitJoinKeyField,
|
||||
searchAfterBuilder,
|
||||
query,
|
||||
isCaseSensitive,
|
||||
waitForCompletionTimeout,
|
||||
keepAlive,
|
||||
keepOnCompletion);
|
||||
|
@ -9,111 +9,56 @@ package org.elasticsearch.test.eql;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.elasticsearch.Build;
|
||||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.action.bulk.BulkResponse;
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.support.WriteRequest;
|
||||
import org.elasticsearch.client.EqlClient;
|
||||
import org.elasticsearch.client.Request;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.ResponseException;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.elasticsearch.client.eql.EqlSearchRequest;
|
||||
import org.elasticsearch.client.eql.EqlSearchResponse;
|
||||
import org.elasticsearch.client.eql.EqlSearchResponse.Hits;
|
||||
import org.elasticsearch.client.eql.EqlSearchResponse.Sequence;
|
||||
import org.elasticsearch.client.indices.CreateIndexRequest;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.io.Streams;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.elasticsearch.test.eql.DataLoader.testIndexName;
|
||||
|
||||
public abstract class CommonEqlActionTestCase extends ESRestTestCase {
|
||||
|
||||
private RestHighLevelClient highLevelClient;
|
||||
|
||||
static final String indexPrefix = "endgame";
|
||||
static final String testIndexName = indexPrefix + "-1.4.0";
|
||||
protected static final String PARAM_FORMATTING = "%1$s.test -> %2$s";
|
||||
private RestHighLevelClient highLevelClient;
|
||||
|
||||
@BeforeClass
|
||||
public static void checkForSnapshot() {
|
||||
assumeTrue("Only works on snapshot builds for now", Build.CURRENT.isSnapshot());
|
||||
}
|
||||
|
||||
private static boolean isSetUp = false;
|
||||
private static int counter = 0;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void setupData(CommonEqlActionTestCase tc) throws Exception {
|
||||
if (isSetUp) {
|
||||
return;
|
||||
}
|
||||
|
||||
CreateIndexRequest request = new CreateIndexRequest(testIndexName)
|
||||
.mapping(Streams.readFully(CommonEqlActionTestCase.class.getResourceAsStream("/mapping-default.json")),
|
||||
XContentType.JSON);
|
||||
|
||||
tc.highLevelClient().indices().create(request, RequestOptions.DEFAULT);
|
||||
|
||||
BulkRequest bulk = new BulkRequest();
|
||||
bulk.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
|
||||
|
||||
try (XContentParser parser = tc.createParser(JsonXContent.jsonXContent,
|
||||
CommonEqlActionTestCase.class.getResourceAsStream("/test_data.json"))) {
|
||||
List<Object> list = parser.list();
|
||||
for (Object item : list) {
|
||||
assertThat(item, instanceOf(HashMap.class));
|
||||
Map<String, Object> entry = (Map<String, Object>) item;
|
||||
bulk.add(new IndexRequest(testIndexName).source(entry, XContentType.JSON));
|
||||
}
|
||||
}
|
||||
|
||||
if (bulk.numberOfActions() > 0) {
|
||||
BulkResponse bulkResponse = tc.highLevelClient().bulk(bulk, RequestOptions.DEFAULT);
|
||||
assertEquals(RestStatus.OK, bulkResponse.status());
|
||||
assertFalse(bulkResponse.hasFailures());
|
||||
isSetUp = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static void cleanupData(CommonEqlActionTestCase tc) throws Exception {
|
||||
// Delete index after all tests ran
|
||||
if (isSetUp && (--counter == 0)) {
|
||||
deleteIndex(testIndexName);
|
||||
isSetUp = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean preserveClusterUponCompletion() {
|
||||
// Need to preserve data between parameterized tests runs
|
||||
return true;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
setupData(this);
|
||||
if (client().performRequest(new Request("HEAD", "/" + testIndexName)).getStatusLine().getStatusCode() == 404) {
|
||||
DataLoader.loadDatasetIntoEs(highLevelClient(), (t, u) -> createParser(t, u));
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() throws Exception {
|
||||
cleanupData(this);
|
||||
@AfterClass
|
||||
public static void cleanup() throws Exception {
|
||||
try {
|
||||
adminClient().performRequest(new Request("DELETE", "/*"));
|
||||
} catch (ResponseException e) {
|
||||
// 404 here just means we had no indexes
|
||||
if (e.getResponse().getStatusLine().getStatusCode() != 404) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ParametersFactory(shuffle = false, argumentFormatting = PARAM_FORMATTING)
|
||||
@ -121,7 +66,7 @@ public abstract class CommonEqlActionTestCase extends ESRestTestCase {
|
||||
|
||||
// Load EQL validation specs
|
||||
List<EqlSpec> specs = EqlSpecLoader.load("/test_queries.toml", true);
|
||||
specs.addAll(EqlSpecLoader.load("/test_queries_supported.toml", true));
|
||||
specs.addAll(EqlSpecLoader.load("/additional_test_queries.toml", true));
|
||||
List<EqlSpec> unsupportedSpecs = EqlSpecLoader.load("/test_queries_unsupported.toml", false);
|
||||
|
||||
// Validate only currently supported specs
|
||||
@ -131,7 +76,7 @@ public abstract class CommonEqlActionTestCase extends ESRestTestCase {
|
||||
boolean supported = true;
|
||||
// Check if spec is supported, simple iteration, cause the list is short.
|
||||
for (EqlSpec unSpec : unsupportedSpecs) {
|
||||
if (spec.query() != null && spec.query().equals(unSpec.query())) {
|
||||
if (spec.equals(unSpec)) {
|
||||
supported = false;
|
||||
break;
|
||||
}
|
||||
@ -141,7 +86,6 @@ public abstract class CommonEqlActionTestCase extends ESRestTestCase {
|
||||
filteredSpecs.add(spec);
|
||||
}
|
||||
}
|
||||
counter = specs.size();
|
||||
return asArray(filteredSpecs);
|
||||
}
|
||||
|
||||
@ -171,7 +115,19 @@ public abstract class CommonEqlActionTestCase extends ESRestTestCase {
|
||||
}
|
||||
|
||||
public void test() throws Exception {
|
||||
assertResponse(runQuery(testIndexName, spec.query()));
|
||||
// run both tests if case sensitivity doesn't matter
|
||||
if (spec.caseSensitive() == null) {
|
||||
assertResponse(runQuery(testIndexName, spec.query(), true));
|
||||
assertResponse(runQuery(testIndexName, spec.query(), false));
|
||||
}
|
||||
// run only the case sensitive test
|
||||
else if (spec.caseSensitive()) {
|
||||
assertResponse(runQuery(testIndexName, spec.query(), true));
|
||||
}
|
||||
// run only the case insensitive test
|
||||
else {
|
||||
assertResponse(runQuery(testIndexName, spec.query(), false));
|
||||
}
|
||||
}
|
||||
|
||||
protected void assertResponse(EqlSearchResponse response) {
|
||||
@ -187,14 +143,16 @@ public abstract class CommonEqlActionTestCase extends ESRestTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
protected EqlSearchResponse runQuery(String index, String query) throws Exception {
|
||||
protected EqlSearchResponse runQuery(String index, String query, boolean isCaseSensitive) throws Exception {
|
||||
EqlSearchRequest request = new EqlSearchRequest(testIndexName, query);
|
||||
request.isCaseSensitive(isCaseSensitive);
|
||||
request.tiebreakerField("event.sequence");
|
||||
return eqlClient().search(request, RequestOptions.DEFAULT);
|
||||
return highLevelClient().eql().search(request, RequestOptions.DEFAULT);
|
||||
}
|
||||
|
||||
protected EqlClient eqlClient() {
|
||||
return highLevelClient().eql();
|
||||
protected void assertSearchHits(List<SearchHit> events) {
|
||||
assertNotNull(events);
|
||||
assertArrayEquals("unexpected result for spec: [" + spec.toString() + "]", spec.expectedEventIds(), extractIds(events));
|
||||
}
|
||||
|
||||
private static long[] extractIds(List<SearchHit> events) {
|
||||
@ -206,11 +164,6 @@ public abstract class CommonEqlActionTestCase extends ESRestTestCase {
|
||||
return ids;
|
||||
}
|
||||
|
||||
protected void assertSearchHits(List<SearchHit> events) {
|
||||
assertNotNull(events);
|
||||
assertArrayEquals("unexpected result for spec: [" + spec.toString() + "]", spec.expectedEventIds(), extractIds(events));
|
||||
}
|
||||
|
||||
protected void assertSequences(List<Sequence> sequences) {
|
||||
List<SearchHit> events = sequences.stream()
|
||||
.flatMap(s -> s.events().stream())
|
||||
@ -229,4 +182,10 @@ public abstract class CommonEqlActionTestCase extends ESRestTestCase {
|
||||
}
|
||||
return highLevelClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean preserveClusterUponCompletion() {
|
||||
// Need to preserve data between parameterized tests runs
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.test.eql;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.action.bulk.BulkResponse;
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.support.WriteRequest;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.RestClient;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.elasticsearch.client.indices.CreateIndexRequest;
|
||||
import org.elasticsearch.cluster.ClusterModule;
|
||||
import org.elasticsearch.common.CheckedBiFunction;
|
||||
import org.elasticsearch.common.io.Streams;
|
||||
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.XContent;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class DataLoader {
|
||||
|
||||
private static final String TEST_DATA = "/test_data.json";
|
||||
private static final String MAPPING = "/mapping-default.json";
|
||||
static final String indexPrefix = "endgame";
|
||||
static final String testIndexName = indexPrefix + "-1.4.0";
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
try (RestClient client = RestClient.builder(new HttpHost("localhost", 9200)).build()) {
|
||||
loadDatasetIntoEs(new RestHighLevelClient(
|
||||
client,
|
||||
ignore -> {
|
||||
},
|
||||
Collections.emptyList()) {
|
||||
}, (t, u) -> createParser(t, u));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static void loadDatasetIntoEs(RestHighLevelClient client,
|
||||
CheckedBiFunction<XContent, InputStream, XContentParser, IOException> p) throws IOException {
|
||||
|
||||
CreateIndexRequest request = new CreateIndexRequest(testIndexName)
|
||||
.mapping(Streams.readFully(DataLoader.class.getResourceAsStream(MAPPING)), XContentType.JSON);
|
||||
|
||||
client.indices().create(request, RequestOptions.DEFAULT);
|
||||
|
||||
BulkRequest bulk = new BulkRequest();
|
||||
bulk.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
|
||||
|
||||
try (XContentParser parser = p.apply(JsonXContent.jsonXContent, DataLoader.class.getResourceAsStream(TEST_DATA))) {
|
||||
List<Object> list = parser.list();
|
||||
for (Object item : list) {
|
||||
bulk.add(new IndexRequest(testIndexName).source((Map<String, Object>) item, XContentType.JSON));
|
||||
}
|
||||
}
|
||||
|
||||
if (bulk.numberOfActions() > 0) {
|
||||
BulkResponse bulkResponse = client.bulk(bulk, RequestOptions.DEFAULT);
|
||||
if (bulkResponse.hasFailures()) {
|
||||
LogManager.getLogger(DataLoader.class).info("Data FAILED loading");
|
||||
} else {
|
||||
LogManager.getLogger(DataLoader.class).info("Data loaded");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static XContentParser createParser(XContent xContent, InputStream data) throws IOException {
|
||||
NamedXContentRegistry contentRegistry = new NamedXContentRegistry(ClusterModule.getNamedXWriteables());
|
||||
return xContent.createParser(contentRegistry, LoggingDeprecationHandler.INSTANCE, data);
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ package org.elasticsearch.test.eql;
|
||||
import org.elasticsearch.common.Strings;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
public class EqlSpec {
|
||||
private String description;
|
||||
@ -17,6 +18,12 @@ public class EqlSpec {
|
||||
private String query;
|
||||
private long[] expectedEventIds;
|
||||
|
||||
// flag to dictate which modes are supported for the test
|
||||
// null -> apply the test to both modes (case sensitive and case insensitive)
|
||||
// TRUE -> case sensitive
|
||||
// FALSE -> case insensitive
|
||||
private Boolean caseSensitive = null;
|
||||
|
||||
public String description() {
|
||||
return description;
|
||||
}
|
||||
@ -57,6 +64,14 @@ public class EqlSpec {
|
||||
this.expectedEventIds = expectedEventIds;
|
||||
}
|
||||
|
||||
public void caseSensitive(Boolean caseSensitive) {
|
||||
this.caseSensitive = caseSensitive;
|
||||
}
|
||||
|
||||
public Boolean caseSensitive() {
|
||||
return this.caseSensitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String str = "";
|
||||
@ -64,6 +79,10 @@ public class EqlSpec {
|
||||
str = appendWithComma(str, "description", description);
|
||||
str = appendWithComma(str, "note", note);
|
||||
|
||||
if (caseSensitive != null) {
|
||||
str = appendWithComma(str, "case_sensitive", Boolean.toString(caseSensitive));
|
||||
}
|
||||
|
||||
if (tags != null) {
|
||||
str = appendWithComma(str, "tags", Arrays.toString(tags));
|
||||
}
|
||||
@ -74,6 +93,27 @@ public class EqlSpec {
|
||||
return str;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (other == null || getClass() != other.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EqlSpec that = (EqlSpec) other;
|
||||
|
||||
return Objects.equals(this.query(), that.query())
|
||||
&& Objects.equals(this.caseSensitive, that.caseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.query, this.caseSensitive);
|
||||
}
|
||||
|
||||
private static String appendWithComma(String str, String name, String append) {
|
||||
if (!Strings.isNullOrEmpty(append)) {
|
||||
if (!Strings.isNullOrEmpty(str)) {
|
||||
|
@ -55,6 +55,20 @@ public class EqlSpecLoader {
|
||||
spec.note(getTrimmedString(table, "note"));
|
||||
spec.description(getTrimmedString(table, "description"));
|
||||
|
||||
Boolean caseSensitive = table.getBoolean("case_sensitive");
|
||||
Boolean caseInsensitive = table.getBoolean("case_insensitive");
|
||||
// if case_sensitive is TRUE and case_insensitive is not TRUE (FALSE or NULL), then the test is case sensitive only
|
||||
if (Boolean.TRUE.equals(caseSensitive)) {
|
||||
if (Boolean.FALSE.equals(caseInsensitive) || caseInsensitive == null) {
|
||||
spec.caseSensitive(true);
|
||||
}
|
||||
}
|
||||
// if case_sensitive is not TRUE (FALSE or NULL) and case_insensitive is TRUE, then the test is case insensitive only
|
||||
else if (Boolean.TRUE.equals(caseInsensitive)) {
|
||||
spec.caseSensitive(false);
|
||||
}
|
||||
// in all other cases, the test should run no matter the case sensitivity (should test both scenarios)
|
||||
|
||||
List<?> arr = table.getList("tags");
|
||||
if (arr != null) {
|
||||
String tags[] = new String[arr.size()];
|
||||
|
@ -1,5 +1,5 @@
|
||||
# This file is populated with additional EQL queries that were not present in the original EQL python implementation
|
||||
# test_queries.toml file in order to keep the original unchanges and easier to sync with the EQL reference implementation tests.
|
||||
# test_queries.toml file in order to keep the original unchanged and easier to sync with the EQL reference implementation tests.
|
||||
|
||||
[[queries]]
|
||||
expected_event_ids = [95]
|
||||
@ -186,6 +186,28 @@ query = "file where 66.0 / serial_event_id == 1"
|
||||
expected_event_ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 46]
|
||||
query = "process where serial_event_id + ((1 + 3) * 2 / (3 - 1)) * 2 == 54 or 70 + serial_event_id < 100"
|
||||
|
||||
[[queries]]
|
||||
query = '''
|
||||
sequence
|
||||
[process where serial_event_id = 1]
|
||||
[process where serial_event_id = 2]
|
||||
'''
|
||||
expected_event_ids = [1, 2]
|
||||
|
||||
[[queries]]
|
||||
query = '''
|
||||
sequence
|
||||
[process where serial_event_id=1] by unique_pid
|
||||
[process where true] by unique_ppid'''
|
||||
expected_event_ids = [1, 2]
|
||||
|
||||
[[queries]]
|
||||
query = '''
|
||||
sequence
|
||||
[process where serial_event_id<3] by unique_pid
|
||||
[process where true] by unique_ppid
|
||||
'''
|
||||
expected_event_ids = [1, 2, 2, 3]
|
||||
|
||||
[[queries]]
|
||||
query = '''
|
||||
@ -193,4 +215,4 @@ sequence
|
||||
[process where false] by unique_pid
|
||||
[process where true] by unique_ppid
|
||||
'''
|
||||
expected_event_ids = []
|
||||
expected_event_ids = []
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user