-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ | |
import org.apache.http.client.methods.HttpPut; | ||
|
||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
|
@@ -35,8 +36,8 @@ public class ClientYamlSuiteRestApi { | |
private final String name; | ||
private List<String> methods = new ArrayList<>(); | ||
private List<String> paths = new ArrayList<>(); | ||
private List<String> pathParts = new ArrayList<>(); | ||
private List<String> params = new ArrayList<>(); | ||
private Map<String, Boolean> pathParts = new HashMap<>(); | ||
private Map<String, Boolean> params = new HashMap<>(); | ||
private Body body = Body.NOT_SUPPORTED; | ||
|
||
public enum Body { | ||
|
@@ -98,20 +99,28 @@ void addPath(String path) { | |
this.paths.add(path); | ||
} | ||
|
||
public List<String> getPathParts() { | ||
/** | ||
* Gets all path parts supported by the api. For every path part defines if it | ||
* is required or optional. | ||
*/ | ||
public Map<String, Boolean> getPathParts() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
return pathParts; | ||
} | ||
|
||
void addPathPart(String pathPart) { | ||
this.pathParts.add(pathPart); | ||
void addPathPart(String pathPart, boolean required) { | ||
this.pathParts.put(pathPart, required); | ||
} | ||
|
||
public List<String> getParams() { | ||
/** | ||
* Gets all parameters supported by the api. For every parameter defines if it | ||
* is required or optional. | ||
*/ | ||
public Map<String, Boolean> getParams() { | ||
return params; | ||
} | ||
|
||
void addParam(String param) { | ||
this.params.add(param); | ||
void addParam(String param, boolean required) { | ||
this.params.put(param, required); | ||
} | ||
|
||
void setBodyOptional() { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,8 @@ | |
*/ | ||
package org.elasticsearch.test.rest.yaml.restspec; | ||
|
||
import org.elasticsearch.common.ParseField; | ||
import org.elasticsearch.common.xcontent.ObjectParser; | ||
import org.elasticsearch.common.xcontent.XContentParser; | ||
|
||
import java.io.IOException; | ||
|
@@ -57,7 +59,6 @@ public ClientYamlSuiteRestApi parse(String location, XContentParser parser) thro | |
if (parser.currentToken() == XContentParser.Token.FIELD_NAME) { | ||
currentFieldName = parser.currentName(); | ||
} | ||
|
||
if (parser.currentToken() == XContentParser.Token.START_ARRAY && "paths".equals(currentFieldName)) { | ||
while (parser.nextToken() == XContentParser.Token.VALUE_STRING) { | ||
String path = parser.text(); | ||
|
@@ -71,30 +72,30 @@ public ClientYamlSuiteRestApi parse(String location, XContentParser parser) thro | |
if (parser.currentToken() == XContentParser.Token.START_OBJECT && "parts".equals(currentFieldName)) { | ||
while (parser.nextToken() == XContentParser.Token.FIELD_NAME) { | ||
String part = parser.currentName(); | ||
if (restApi.getPathParts().contains(part)) { | ||
if (restApi.getPathParts().containsKey(part)) { | ||
throw new IllegalArgumentException("Found duplicate part [" + part + "]"); | ||
} | ||
restApi.addPathPart(part); | ||
parser.nextToken(); | ||
if (parser.currentToken() != XContentParser.Token.START_OBJECT) { | ||
throw new IllegalArgumentException("Expected parts field in rest api definition to contain an object"); | ||
} | ||
parser.skipChildren(); | ||
restApi.addPathPart(part, getRequired(parser)); | ||
} | ||
} | ||
|
||
if (parser.currentToken() == XContentParser.Token.START_OBJECT && "params".equals(currentFieldName)) { | ||
while (parser.nextToken() == XContentParser.Token.FIELD_NAME) { | ||
|
||
String param = parser.currentName(); | ||
if (restApi.getParams().contains(param)) { | ||
if (restApi.getParams().containsKey(param)) { | ||
throw new IllegalArgumentException("Found duplicate param [" + param + "]"); | ||
} | ||
restApi.addParam(parser.currentName()); | ||
|
||
parser.nextToken(); | ||
if (parser.currentToken() != XContentParser.Token.START_OBJECT) { | ||
throw new IllegalArgumentException("Expected params field in rest api definition to contain an object"); | ||
} | ||
parser.skipChildren(); | ||
restApi.addParam(param, getRequired(parser)); | ||
} | ||
} | ||
|
||
|
@@ -146,4 +147,20 @@ public ClientYamlSuiteRestApi parse(String location, XContentParser parser) thro | |
|
||
return restApi; | ||
} | ||
|
||
class YamlElement { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it'd be more reasonable to name this |
||
private boolean required; | ||
public boolean isRequired() { | ||
return required; | ||
} | ||
public void setRequired(boolean required) { | ||
this.required = required; | ||
} | ||
} | ||
|
||
private boolean getRequired(XContentParser parser) throws IOException { | ||
ObjectParser<YamlElement, Void> objParser = new ObjectParser<>("", true, YamlElement::new); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We tend to make these static. |
||
objParser.declareBoolean(YamlElement::setRequired, new ParseField("required")); | ||
return objParser.parse(parser, null).isRequired(); | ||
} | ||
} |
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.
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 thefalse ==
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.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.
Hope you don't mind that I change all occurrences of
!
tofalse ==
(consistency on file level)