Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EQL: Add case-sensitive and insensitive integration tests #57323

Closed
wants to merge 11 commits into from
Closed

EQL: Add case-sensitive and insensitive integration tests #57323

wants to merge 11 commits into from

Conversation

rw-access
Copy link
Contributor

@rw-access rw-access commented May 28, 2020

Part of #57313
Closes #56754

Pulled over the latest TOML integration tests from Python, which have case (in)sensitive toggles.

There's a handful more tests added, and I noticed that some of the sequence tests are failing, so I left those in the exclusions list. Also updated the HLRC to include case sensitive toggles, which was needed for the tests.

Basically to mark a test as case-sensitive only, add this to the TOML

case_sensitive = true

or this to make a test case-insensitive only.

case_insensitive = true

If the flags aren't set, then the test is assumed to work with both. case_insensitive=true and case_sensitive=true are mutually exclusive.

@rw-access rw-access added the :Analytics/EQL EQL querying label May 28, 2020
@rw-access rw-access requested review from costin, aleksmaus and astefan May 28, 2020 23:46
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-ql (:Query Languages/EQL)

@elasticmachine elasticmachine added the Team:QL (Deprecated) Meta label for query languages team label May 28, 2020
@rw-access rw-access requested a review from matriv May 28, 2020 23:48


##########################
# FAILING SEQUENCE TESTS #
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@costin do you have any guesses why some of these sequence tests were failing?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it's because of the tie breaker - the logic only looks at the timestamp but since it's the same for all events, it fails to order it by the seq_number.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed now that the tiebreaker is in. It is disabled by default however our tests make use of it.


public class EqlSpec {
private String description;
private String note;
private String[] tags;
private String query;
private Boolean caseSensitiveOnly;
private Boolean caseInsensitiveOnly;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can use boolean? or need 'null' for any reason?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class is similar to that in #57568, I wonder if the TOML code could be reused. It's not a lot but not too little either. Between the spec, boilerplate code in the test for reading the spec there is something that potentially (not right now) can be placed in a separate, small utility project.
It's a bit overheard but medium term could simplify dependency management.

Either way a comment pointing out the relationship between the two would be useful so that any updates happening on one end would be useful in the other.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switched to boolean, thanks @aleksmaus. I handle null => false within the SpecLoader.

I'm not sure the ideal solution to avoid reuse while keeping it fairly simple. at the least, I can add a comment like you suggest for both classes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will leave this PR as is, and update in #57568

Copy link
Contributor

@astefan astefan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM in general. Left some comments, though.

@@ -195,8 +202,8 @@ else if (hits.sequences() != null) {
}
}

protected EqlSearchResponse runQuery(String index, String query) throws Exception {
EqlSearchRequest request = new EqlSearchRequest(testIndexName, query);
protected EqlSearchResponse runQuery(String index, String query, boolean isCaseSensitive) throws Exception {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add two more methods - runQueryCaseSensitive and runQueryCaseInsensitive - that should "hide" the boolean parameter choice and call these instead of runQuery(...., true/false)?

@@ -55,6 +55,14 @@ private static String getTrimmedString(TomlTable table, String key) {
spec.note(getTrimmedString(table, "note"));
spec.description(getTrimmedString(table, "description"));

// default these values to false
spec.caseSensitiveOnly(Boolean.TRUE.equals(table.getBoolean("case_sensitive")));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find the "parameter" from the TOML tests a bit confusing. At Java level it's caseSensitiveOnly and in tests is case_sensitive. Imo, it's an important difference between something being "case sensitive ONLY" and "case sensitive".

A test that is "case sensitive" can, also, be "case insensitive", meaning a test that doesn't care about case sensitivity at all. For example, a test where no string functions are involved: this one could run in whatever configuration. My suggestion is to have in .toml files the only bit added to parameters to make a bit more clear.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in 254b5c3, I removed the implicit behavior for and the concept of "case (in)sensitive only".
now every test requires case_sensitive=true and case_insensitive=true if it should be tested with both

@rw-access rw-access requested a review from aleksmaus June 16, 2020 17:08
Copy link
Contributor

@matriv matriv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, left a comment

Copy link
Contributor

@aleksmaus aleksmaus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple of nits, otherwise LGTM


return Objects.equals(this.query(), that.query())
&& Objects.equals(this.caseSensitive, that.caseSensitive)
&& Objects.equals(this.caseInsensitive, that.caseInsensitive);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: missing description, expectedEventIds?


@Override
public int hashCode() {
return Objects.hash(this.query, this.caseSensitive, this.caseInsensitive);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same nit as above

Copy link
Member

@costin costin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the flags aren't set, then the test is assumed to work with both. case_insensitive=true and case_sensitive=true are mutually exclusive.

Looking at the case, this doesn't seem to be the case. A lot of tests have both parameters specified, that shouldn't be the case though.

}
if (Strings.isNullOrEmpty(name)) {
name = "" + (counter.get() + 1);
else if (Strings.isNullOrEmpty(spec.note()) == false) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless all tests have a note, please keep the name counter since otherwise the name becomes the query which makes it impossible to rerun the test (since it's not a correct method name).

Comment on lines +23 to +24
private boolean caseSensitive = false;
private boolean caseInsensitive = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As on the previous issue, having a Boolean object should cover all the cases.
TRUE - sensitive, FALSE - insensitive, null - unspecified (apply both).

Comment on lines +62 to +64
if (spec.caseInsensitive() == false && spec.caseSensitive() == false) {
throw new IllegalArgumentException("Test must support case-sensitivity or case-insensitivity for test: " + spec.toString());
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of forcing each query to specify a case sensitivity, the default should be missing an argument means that parameter is true.
That is instead of specifying:

case_sensitive = true
case_insensitive = true

don't specify anything. If something is just case sensitive, it means it's insensitive and vice-versa and when none is specified, apply both (case irrelevant).
This makes the test declaration easier.

Copy link
Contributor Author

@rw-access rw-access Jun 18, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds like what I used to have, and simplified writing the tests but the behavior didn't seem to be well liked within EqlSpec.

Instead of forcing each query to specify a case sensitivity, the default should be missing an argument means that parameter is true.

This was the original behavior

[[queries]]
# this was an error
case_sensitive = true
case_insensitive = true

[[queries]]
# test will be checked with case sensitive mode only
case_sensitive = true

[[queries]]
# test will be checked with case insensitive mode only
case_insensitive = true

[[queries]]
# test will be checked with both case sensitive and case-insensitive mode
# case_sensitive = null
# case_insensitive = null

But if missing an argument "means that parameter is true", then you basically are inverting the flags. Then you have to negate the logic to denote which tests are not allowed

[[queries]] 
# the only way to run a test as case-insensitive only
case_sensitive = false

Copy link
Contributor Author

@rw-access rw-access Jun 18, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the most desired behavior is this?
If both case_sensitive and case_insensitive are null, then set them to both to true

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the most desired behavior is this?
If both case_sensitive and case_insensitive are null, then set them to both to true

Correct. Looking at the individual properties in isolation and setting them to true won't work since they both have to be missing.

@astefan
Copy link
Contributor

astefan commented Jun 30, 2020

Superseded by #58624

@astefan astefan closed this Jun 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Analytics/EQL EQL querying Team:QL (Deprecated) Meta label for query languages team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

EQL: case sensitivity aware integration testing
6 participants