-
Notifications
You must be signed in to change notification settings - Fork 25.1k
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
Run core's integration tests with runtime fields #60931
Run core's integration tests with runtime fields #60931
Conversation
Adds the `x-pack/plugin/runtime-fields/qa/rest` project to run core's integration tests against an index with `runtime_scipt` fields. This works by modifying the test configuration on load to replace supported field types with `runtime_script`. Relates to elastic#59332
Pinging @elastic/es-search (:Search/Search) |
This adds a little under 300 integration tests for runtime fields. |
@@ -724,7 +724,7 @@ setup: | |||
body: { "size" : 0, "aggs" : { "no_field_terms" : { "terms" : { "size": 1 } } } } | |||
|
|||
--- | |||
"string profiler": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wrote this one so I figured I could fix it while I was here. Runtime fields don't have global ordinals so rather than skip the entire test for them I split it into two tests, one that runtime fields can run (below) and this one which runtime fields will skip.
This is a nice idea! I can see how this would really increase confidence in 'cross-cutting' functionality for runtime fields. I think it'd be good to loop in someone from core infra for their thoughts on this testing strategy. One potential concern is that we're running many more REST tests than previously. We followed a similar approach (of running most tests twice) when deprecating document types, but this was clearly temporary and we removed the duplication in 8.0. |
I'll do it!
We do it in I think skipping the test when I'm not able to convert it into a |
|
||
integTest { | ||
systemProperty 'tests.rest.blacklist', | ||
[ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is quite the list of exclusions. Seems a bit brittle. One issue I anticipate is future newly added tests also being incompatible with this approach for one reason or another.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My goal is to fix the ones between here and line 36 fairly soon. At least theoretically, tests that fetch the mapping are never going to work but other sorts of tests should work. I could scan the test configuration for the command to fetch the mapping and skip those. It wouldn't be too bad and would shrink these.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another option is to add skip
style property so these tests can opt themselves out of running against runtime field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of a skip
property -- that way the 'skip reason' is discoverable and right next to the test itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'd have to bring this notion of runtime fields testing up into the test framework itself though, which seems a bit awkward given how this is currently structured as a specific qa project.
This is a concern of mine as well. In terms of total build time, it doesn't really add that much but we should still determine whether this coverage is worth the cost, or if there's some subset of this that would be sufficient to give us confidence we haven't introduce some kind of regression. |
@@ -0,0 +1,45 @@ | |||
apply plugin: 'elasticsearch.testclusters' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should replace all of this with the elasticsearch.yaml-rest-test
plugin. Additionally the test suite should move from src/test
to src/yamlRestTest
to comply with new conventions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is worth it. In hacking runtime fields I've found that the way we link fields and the search definition can be a little janky. Sometimes it is nice and as simple as implementing an interface. Other times there are a lot of |
I don't have an opinion here. I'll let folks with better knowledge on the behavioral implications (you) make that call. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... we should still determine whether this coverage is worth the cost, or if there's some subset of this that would be sufficient to give us confidence we haven't introduce some kind of regression.
I also think it's really helpful. I know if we had added this kind of coverage for field aliases we would've caught bugs around interactions with other features like field collapsing.
Would it make sense to limit this to only search-related tests? That would include everything under the search
, msearch
, and field_caps
directories, plus some related ones like explain
and suggest
(which should maybe live under search
anyways...) This is really where I see the most value in terms of test coverage. Plus runtime fields are only interchangeable with 'standard' fields from the perspective of a search request, their behavior is not the same in terms of mappings, CRUD operations, etc.
|
||
integTest { | ||
systemProperty 'tests.rest.blacklist', | ||
[ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of a skip
property -- that way the 'skip reason' is discoverable and right next to the test itself.
Map<String, Boolean> seenSetups = new HashMap<>(); | ||
List<Object[]> result = new ArrayList<>(); | ||
for (Object[] orig : ESClientYamlSuiteTestCase.createParameters()) { | ||
ClientYamlTestCandidate candidate = (ClientYamlTestCandidate) orig[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there ever a time when the rest of the Object
array is relevant (beyond the first element)? Maybe we could replace orig[0]
and still return orig
, or simply assert orig.length == 1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The array only ever has a single entry, but I'll add an assert just to make sure it stays that way. The funny shape of the return here comes from the method being used primarily for junit's parameterized tests.
} | ||
|
||
private static boolean containsUnsupportedSettings(Map<?, ?> settings) { | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find the formatting hard to follow, does it work to just do return settings.containsKey("sort.field");
? Also maybe we could use the phrase 'index sort' to clarify what this setting refers to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I super thought there'd be other things to add here. But it turned out this was it. I'll remove the method and move the check into the caller.
|
||
private static final Map<String, String> PAINLESS_TO_EMIT = Map.ofEntries( | ||
// TODO implement dates against the parser | ||
Map.entry( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like the best approach for now but feels a bit fragile -- we're essentially duplicating the source parsing logic, which can be pretty nuanced. For example, for boolean
fields, the value ""
is interpreted as false
. We also don't cover cases where the value is malformed or missing from _source.
To make this more robust, I guess we could switch to 'source-only fields' when those are available? That way we could reuse the logic from fields
retrieval for parsing values from source. Or we could consider adding a way to access nicely-formatted source fields from painless?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It really is pretty fragile. I was thinking of something similar to what you said - steal the source parsing and expose it to the script. That wouldn't be a "painless feature" so much as a feature of the script context of the runtime field. The advantage of this is that I know exactly which runtime field I'm running against so, for example, dates could use the the field's date parsing logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. I think this is the right way to go for this feature branch, but it'd be good to follow-up on source parsing improvements at a later point.
I think that'd get us a huge way there and skip a lot of unneeded stuff. If we find more things we want to drag in we can do that. I'll give it a shot! |
When I limit the list to just search related APIs I still get a ton of coverage and I can drop a bunch of the "strange" exclusions. I'm happy about it! |
@jtibshirani I pushed an update that:
This leaves me with 2 skip lines that I know I'll never support and 7 that I plan to fix. I think that list is small enough that it'd be ok to keep it in the build file. Hopefully it'll stay that short! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me as an initial version. One question that's still open is whether we'll add a special skip
type for runtime fields.
Object settings = body.get("settings"); | ||
if (settings instanceof Map && ((Map<?, ?>) settings).containsKey("sort.field")) { | ||
/* | ||
* You can't sort on a runtime_keyword and it is hard to figure out |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small comment, we could say 'index sort' for clarity?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++
|
||
private static final Map<String, String> PAINLESS_TO_EMIT = Map.ofEntries( | ||
// TODO implement dates against the parser | ||
Map.entry( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. I think this is the right way to go for this feature branch, but it'd be good to follow-up on source parsing improvements at a later point.
Oops, I missed this while preparing my review. That works for me, we can revisit this if it turns out to be hard to maintain. |
Thanks @jtibshirani and @mark-vieira! This'll really help! |
This is great @nik9000 , I wonder if we can also execute async_search tests, but they may be taken from another place which possibly complicates things.
I wonder how this translates to what we need to do once we merge the feature branch to master, which we plan to do very soon. |
Great idea! I'll take a look at that.
I'm working on something that'll parse dates that might make this cleaner by giving us a path to being more consistent. |
Breaks up an integration test into one that runtime fields can run and one that runtime fields have to skip. This is because runtime fields don't have global ords and we assert things *about* global ords in the test we have to skip.
This "borrows" 150 more tests from core for runtime fields, extending the work done in elastic#60931. More precisely, it adds a template to every test that forces dynamic mapping updates to build runtime fields where possible. In particular, `long` and `double` field are created as runtime fields. `string`-typed fields are mimick the out of the box behavior and create a top level `text` field with a `.keyword` multi-field, but this `keyword` multi-field executes a script and loads from source.
…1103) Breaks up an integration test into one that runtime fields can run and one that runtime fields have to skip. This is because runtime fields don't have global ords and we assert things *about* global ords in the test we have to skip.
…er) (elastic#61103) Breaks up an integration test into one that runtime fields can run and one that runtime fields have to skip. This is because runtime fields don't have global ords and we assert things *about* global ords in the test we have to skip.
This "borrows" 150 more tests from core for runtime fields, extending the work done in #60931. More precisely, it adds a template to every test that forces dynamic mapping updates to build runtime fields where possible. In particular, `long` and `double` field are created as runtime fields. `string`-typed fields are mimick the out of the box behavior and create a top level `text` field with a `.keyword` multi-field, but this `keyword` multi-field executes a script and loads from source.
Adds the
x-pack/plugin/runtime-fields/qa/rest
project to run core'sintegration tests against an index with
runtime_scipt
fields. Thisworks by modifying the test configuration on load to replace supported
field types with
runtime_script
.Relates to #59332