Skip to content

[all] Adds strict spec option #2783

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

Merged
merged 3 commits into from
May 3, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,12 @@ public class Generate implements Runnable {
description = "Skips the default behavior of validating an input specification.")
private Boolean skipValidateSpec;

@Option(name = {"--strict-spec"},
title = "true/false strict behavior",
description = "'MUST' and 'SHALL' wording in OpenAPI spec is strictly adhered to, e.g. no fixes will be applied to documents which pass validation but don't follow the spec.",
Copy link
Contributor

Choose a reason for hiding this comment

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

s/, e.g. no/. When false, no/

arity = 1)
private Boolean strictSpecBehavior;

@Option(name = {"--log-to-stderr"},
title = "Log to STDERR",
description = "write all log messages (not just errors) to STDOUT."
Expand Down Expand Up @@ -368,10 +374,15 @@ public void run() {
if (generateAliasAsModel != null) {
configurator.setGenerateAliasAsModel(generateAliasAsModel);
}

if (minimalUpdate != null) {
configurator.setEnableMinimalUpdate(minimalUpdate);
}

if (strictSpecBehavior != null) {
configurator.setStrictSpecBehavior(strictSpecBehavior);
}

applySystemPropertiesKvpList(systemProperties, configurator);
applyInstantiationTypesKvpList(instantiationTypes, configurator);
applyImportMappingsKvpList(importMappings, configurator);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,26 @@ public void testSkipOverwrite() throws Exception {
};
}

@Test
public void testStrictSpec() throws Exception {

setupAndRunGenericTest("--strict-spec", "true");
new FullVerifications() {
{
configurator.setStrictSpecBehavior(true);
times = 1;
}
};

setupAndRunGenericTest("--strict-spec", "false");
new FullVerifications() {
{
configurator.setStrictSpecBehavior(false);
times = 1;
}
};
}

@Test
public void testPackageName() throws Exception {
final String value = "io.foo.bar.baz";
Expand Down
1 change: 1 addition & 0 deletions modules/openapi-generator-maven-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ mvn clean compile
- `logToStderr` - write all log messages (not just errors) to STDOUT
- `enablePostProcessFile` - enable file post-processing hook
- `skipValidateSpec` - Whether or not to skip validating the input spec prior to generation. By default, invalid specifications will result in an error.
- `strictSpec` - Whether or not to treat an input document strictly against the spec. 'MUST' and 'SHALL' wording in OpenAPI spec is strictly adhered to, e.g. no fixes will be applied to documents which pass validation but don't follow the spec.
Copy link
Contributor

Choose a reason for hiding this comment

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

s/, e.g. no/. When false, no/

- `generateAliasAsModel` - generate alias (array, map) as model
- `generateApis` - generate the apis (`true` by default)
- `generateApiTests` - generate the api tests (`true` by default. Only available if `generateApis` is `true`)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,12 @@ public class CodeGenMojo extends AbstractMojo {
@Parameter(name = "skipValidateSpec", required = false)
private Boolean skipValidateSpec;

/**
* To treat a document strictly against the spec.
*/
@Parameter(name = "strictSpec", required = false)
private Boolean strictSpecBehavior;

/**
* To generate alias (array, map) as model
*/
Expand Down Expand Up @@ -459,6 +465,10 @@ public void execute() throws MojoExecutionException {
configurator.setValidateSpec(!skipValidateSpec);
}

if (strictSpecBehavior != null) {
configurator.setStrictSpecBehavior(strictSpecBehavior);
}

if (logToStderr != null) {
configurator.setLogToStderr(logToStderr);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,4 +270,8 @@ public interface CodegenConfig {
public boolean isEnableMinimalUpdate();

public void setEnableMinimalUpdate(boolean isEnableMinimalUpdate);

boolean isStrictSpecBehavior();

void setStrictSpecBehavior(boolean strictSpecBehavior);
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ public class DefaultCodegen implements CodegenConfig {
// flag to indicate whether to only update files whose contents have changed
protected boolean enableMinimalUpdate = false;

// acts strictly upon a spec, potentially modifying it to have consistent behavior across generators.
protected boolean strictSpecBehavior = true;

// make openapi available to all methods
protected OpenAPI openAPI;

Expand Down Expand Up @@ -2387,11 +2390,13 @@ public CodegenOperation fromOperation(String path,
}
operationId = removeNonNameElementToCamelCase(operationId);

if (path.startsWith("/")) {
op.path = path;
} else {
if (isStrictSpecBehavior() && !path.startsWith("/")) {
// modifies an operation.path to strictly conform to OpenAPI Spec
op.path = "/" + path;
} else {
op.path = path;
}

op.operationId = toOperationId(operationId);
op.summary = escapeText(operation.getSummary());
op.unescapedNotes = operation.getDescription();
Expand Down Expand Up @@ -4900,4 +4905,24 @@ public void setEnableMinimalUpdate(boolean enableMinimalUpdate) {
this.enableMinimalUpdate = enableMinimalUpdate;
}

/**
* Indicates whether the codegen configuration should treat documents as strictly defined by the OpenAPI specification.
*
* @return true to act strictly upon spec documents, potentially modifying the spec to strictly fit the spec.
*/
@Override
public boolean isStrictSpecBehavior() {
return this.strictSpecBehavior;
}

/**
* Sets the boolean valid indicating whether generation will work strictly against the specification, potentially making
* minor changes to the input document.
*
* @param strictSpecBehavior true if we will behave strictly, false to allow specification documents which pass validation to be loosely interpreted against the spec.
*/
@Override
public void setStrictSpecBehavior(final boolean strictSpecBehavior) {
this.strictSpecBehavior = strictSpecBehavior;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public class CodegenConfigurator implements Serializable {
private boolean validateSpec;
private boolean enablePostProcessFile;
private boolean enableMinimalUpdate;
private boolean strictSpecBehavior;
private String templateDir;
private String templatingEngineName;
private String auth;
Expand Down Expand Up @@ -117,6 +118,7 @@ public class CodegenConfigurator implements Serializable {

public CodegenConfigurator() {
this.validateSpec = true;
this.strictSpecBehavior = true;
this.setOutputDir(".");
}

Expand Down Expand Up @@ -252,6 +254,15 @@ public CodegenConfigurator setModelNameSuffix(String suffix) {
return this;
}

public boolean isStrictSpecBehavior() {
return strictSpecBehavior;
}

public CodegenConfigurator setStrictSpecBehavior(boolean strictSpecBehavior) {
this.strictSpecBehavior = strictSpecBehavior;
return this;
}

public boolean isVerbose() {
return verbose;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,35 @@ public void testProcessPaths() throws Exception {
Assert.assertEquals(defaultList.get(3).path, "/path4");
Assert.assertEquals(defaultList.get(3).allParams.size(), 1);
}



@Test
public void testNonStrictProcessPaths() throws Exception {
OpenAPI openAPI = TestUtils.createOpenAPI();
openAPI.setPaths(new Paths());
openAPI.getPaths().addPathItem("path1/", new PathItem().get(new Operation().operationId("op1").responses(new ApiResponses().addApiResponse("201", new ApiResponse().description("OK")))));
openAPI.getPaths().addPathItem("path2/", new PathItem().get(new Operation().operationId("op2").addParametersItem(new QueryParameter().name("p1").schema(new StringSchema())).responses(new ApiResponses().addApiResponse("201", new ApiResponse().description("OK")))));

ClientOptInput opts = new ClientOptInput();
opts.setOpenAPI(openAPI);
CodegenConfig config = new DefaultCodegen();
config.setStrictSpecBehavior(false);
opts.setConfig(config);
opts.setOpts(new ClientOpts());

DefaultGenerator generator = new DefaultGenerator();
generator.opts(opts);
Map<String, List<CodegenOperation>> result = generator.processPaths(openAPI.getPaths());
Assert.assertEquals(result.size(), 1);
List<CodegenOperation> defaultList = result.get("Default");
Assert.assertEquals(defaultList.size(), 2);
Assert.assertEquals(defaultList.get(0).path, "path1/");
Assert.assertEquals(defaultList.get(0).allParams.size(), 0);
Assert.assertEquals(defaultList.get(1).path, "path2/");
Assert.assertEquals(defaultList.get(1).allParams.size(), 1);
}


@Test
public void minimalUpdateTest() throws IOException {
OpenAPI openAPI = TestUtils.createOpenAPI();
Expand Down