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

Make yaml test runner stricter by enforcing required for paths and parameters #27035

Merged
merged 4 commits into from
Oct 25, 2017

Conversation

olcbean
Copy link
Contributor

@olcbean olcbean commented Oct 17, 2017

Till now the yaml test runner was verifying that the provided path parts and parameters are supported.
With this PR, yaml test runner also checks that all required path parts and parameters are provided.

Related to #25737

@elasticmachine
Copy link
Collaborator

Since this is a community submitted pull request, a Jenkins build has not been kicked off automatically. Can an Elastic organization member please verify the contents of this patch and then kick off a build manually?

@s1monw
Copy link
Contributor

s1monw commented Oct 17, 2017

@elasticmachine ok to test

Copy link
Member

@nik9000 nik9000 left a comment

Choose a reason for hiding this comment

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

Thanks for making this change!

I left a few minor nick picky things. The biggest one is error handling in the parsing. I know we haven't been great about error handling in the yaml parsing of this stuff before but I'd like us to be better.

@@ -80,19 +83,33 @@ public ClientYamlTestResponse callApi(String apiName, Map<String, String> params
//divide params between ones that go within query string and ones that go within path
Map<String, String> pathParts = new HashMap<>();
Map<String, String> queryStringParams = new HashMap<>();

List<String> apiPathParts = restApi.getPathParts().entrySet().stream().filter(e -> e.getValue() == true).map(Entry::getKey)
Copy link
Member

Choose a reason for hiding this comment

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

Maybe Set<String> instead? The list should be short so it likely doesn't matter but it feels better to me if it is a set.

return pathParts;
}

void addPathPart(String pathPart) {
this.pathParts.add(pathPart);
void addPathPart(String pathPart, Boolean required) {
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 it should be bool rather than Boolean.

@@ -98,20 +99,20 @@ void addPath(String path) {
this.paths.add(path);
}

public List<String> getPathParts() {
public Map<String, Boolean> getPathParts() {
Copy link
Member

Choose a reason for hiding this comment

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

Probably should have javadoc because it isn't obvious what the boolean reads unless you read it as part of this PR.

if ("required".equals(parser.currentName())) {
parser.nextToken();
required = parser.booleanValue();
}
Copy link
Member

Choose a reason for hiding this comment

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

Can you either replace this with CosntructingObjectParser<Boolean> or manually throw IOExceptions for things other than required and for tokens other than FIELD_NAME?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@nik9000 thanks for the hint! (I did not know of this parser)
I think that CosntructingObjectParser<Boolean> cannot be used here as the required field is an optional one.

I couldn't find an example how to use ConstructingObjectParser for the primitive wrapper classes. Do you have one?

assertThat(restApi.getPathParts().get(1), equalTo("index"));
assertThat(restApi.getPathParts().get(2), equalTo("type"));
assertThat(restApi.getPathParts().keySet(), containsInAnyOrder("id","index", "type"));
assertThat(restApi.getPathParts().get("index"), equalTo(true));
Copy link
Member

Choose a reason for hiding this comment

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

In cases like this I find that

assertThat(restApi.getPathParts(), hasEntry("index", true));

produces more readable error messages.

@olcbean
Copy link
Contributor Author

olcbean commented Oct 19, 2017

@nik9000 thanks for the review! Can you have another look?

Copy link
Member

@nik9000 nik9000 left a comment

Choose a reason for hiding this comment

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

I agree about the object parser being a bit painful here. But it does get you all that error checking for free which is pretty great. I think you've got it going the right direction though.

I left a minor thing. Otherwise I think this is good to go!

}

private boolean getRequired(XContentParser parser) throws IOException {
ObjectParser<YamlElement, Void> objParser = new ObjectParser<>("", true, YamlElement::new);
Copy link
Member

Choose a reason for hiding this comment

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

We tend to make these static.

@@ -146,4 +147,20 @@ public ClientYamlSuiteRestApi parse(String location, XContentParser parser) thro

return restApi;
}

class YamlElement {
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 it'd be more reasonable to name this Parameter or something.

@olcbean
Copy link
Contributor Author

olcbean commented Oct 19, 2017

@nik9000 ready for another round ;)

Copy link
Member

@nik9000 nik9000 left a comment

Choose a reason for hiding this comment

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

Thanks for being patient with me @olcbean! I left one last thing. I just hadn't communicated clearly enough what I wanted.

}

private static boolean getRequired(XContentParser parser) throws IOException {
ObjectParser<Parameter, Void> objParser = new ObjectParser<>("", true, Parameter::new);
Copy link
Member

Choose a reason for hiding this comment

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

Ah! More like:

private static final ObjectParser<Parameter, Void> PARAMETER_PARSER = new ObjectParser<>("parameter", true, Parameter:true);
static {
  PARAMETER_PARSER.declareBoolean(Parameter::setRequired, new ParseField("required");
}

And they you can call it like PARAMETER_PARSER.parse(parser, null).isRequired() like you have. That way we reuse the parser. It probably isn't a big deal, but it is what we do everywhere else so we may as well do it here.

}
}

if (!apiRequiredPathParts.isEmpty()) {
Copy link
Member

Choose a reason for hiding this comment

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

Funny story: we had a contributor for a long time that always wanted false == blah rather than !blah because, he claimed, it is harder to miss the false == part then the ! part. I kind of agree with him but I think we were in the minority. But that is why you have both patterns all over our code base. Either way is fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hope you don't mind that I change all occurrences of ! to false == (consistency on file level)

@olcbean
Copy link
Contributor Author

olcbean commented Oct 20, 2017

@nik9000 thanks for your patience!
I just made the changes you suggested above.

Copy link
Member

@nik9000 nik9000 left a comment

Choose a reason for hiding this comment

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

Looks good to me. I'm going to run it through the tests locally and merge it when it passes.

@javanna
Copy link
Member

javanna commented Oct 23, 2017

cool stuff, thanks @olcbean LGTM as well.

@javanna javanna added >test Issues or PRs that are addressing/adding tests v7.0.0 v6.1.0 labels Oct 25, 2017
@nik9000 nik9000 merged commit 981b7f4 into elastic:master Oct 25, 2017
nik9000 pushed a commit that referenced this pull request Oct 25, 2017
…parameters (#27035)

Till now the yaml test runner was verifying that the provided path parts and parameters are supported.
With this PR, yaml test runner also checks that all required path parts and parameters are provided.
@nik9000
Copy link
Member

nik9000 commented Oct 25, 2017

I've (finally) merge this to master and 6.x.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>test Issues or PRs that are addressing/adding tests v6.1.0 v7.0.0-beta1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants