Skip to content

Commit 417ebae

Browse files
committed
Validate unknown member reference
Add validation for the case where an endpoint test references a non-existent operation input shape member. As part of this change, `CodeGenerator` has ben updated to catch `ModelInvalidException` and write the validation entries in the validation-report.json.
1 parent f4edf0b commit 417ebae

File tree

6 files changed

+98
-3
lines changed

6 files changed

+98
-3
lines changed

codegen/src/main/java/software/amazon/awssdk/codegen/CodeGenerator.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import software.amazon.awssdk.codegen.internal.Jackson;
3030
import software.amazon.awssdk.codegen.internal.Utils;
3131
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
32+
import software.amazon.awssdk.codegen.validation.ModelInvalidException;
3233
import software.amazon.awssdk.codegen.validation.ModelValidationContext;
3334
import software.amazon.awssdk.codegen.validation.ModelValidationReport;
3435
import software.amazon.awssdk.codegen.validation.ModelValidator;
@@ -131,6 +132,13 @@ public void execute() {
131132

132133
} catch (Exception e) {
133134
log.error(() -> "Failed to generate code. ", e);
135+
136+
if (e instanceof ModelInvalidException && emitValidationReport) {
137+
ModelInvalidException invalidException = (ModelInvalidException) e;
138+
report.setValidationEntries(invalidException.validationEntries());
139+
writeValidationReport(report);
140+
}
141+
134142
throw new RuntimeException(
135143
"Failed to generate code. Exception message : " + e.getMessage(), e);
136144
}

codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/BaseGeneratorTasks.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ protected void compute() {
7171
ForkJoinTask.invokeAll(createTasks());
7272
log.info(" Completed " + taskName + ".");
7373
}
74+
} catch (RuntimeException e) {
75+
throw e;
7476
} catch (Exception e) {
7577
throw new RuntimeException(e);
7678
}

codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesClientTestSpec.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@
6161
import software.amazon.awssdk.codegen.poet.PoetExtension;
6262
import software.amazon.awssdk.codegen.poet.PoetUtils;
6363
import software.amazon.awssdk.codegen.utils.AuthUtils;
64+
import software.amazon.awssdk.codegen.validation.ModelInvalidException;
65+
import software.amazon.awssdk.codegen.validation.ValidationEntry;
66+
import software.amazon.awssdk.codegen.validation.ValidationErrorId;
67+
import software.amazon.awssdk.codegen.validation.ValidationErrorSeverity;
6468
import software.amazon.awssdk.core.SdkSystemSetting;
6569
import software.amazon.awssdk.core.async.AsyncRequestBody;
6670
import software.amazon.awssdk.core.rules.testing.AsyncTestCase;
@@ -445,6 +449,20 @@ private CodeBlock requestCreation(OperationModel opModel, Map<String, TreeNode>
445449
if (opParams != null) {
446450
opParams.forEach((n, v) -> {
447451
MemberModel memberModel = opModel.getInputShape().getMemberByC2jName(n);
452+
453+
if (memberModel == null) {
454+
String detailMsg = String.format("Endpoint test definition references member '%s' on the input shape '%s' "
455+
+ "but no such member is defined.", n, opModel.getInputShape().getC2jName());
456+
ValidationEntry entry =
457+
new ValidationEntry()
458+
.withSeverity(ValidationErrorSeverity.DANGER)
459+
.withErrorId(ValidationErrorId.UNKNOWN_SHAPE_MEMBER)
460+
.withDetailMessage(detailMsg);
461+
462+
throw ModelInvalidException.builder()
463+
.validationEntries(Collections.singletonList(entry))
464+
.build();
465+
}
448466
CodeBlock memberValue = createMemberValue(memberModel, v);
449467
b.add(".$N($L)", memberModel.getFluentSetterMethodName(), memberValue);
450468
});
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.codegen.validation;
17+
18+
import java.util.ArrayList;
19+
import java.util.Collections;
20+
import java.util.List;
21+
22+
/**
23+
* Exception thrown during code generation to signal that the model is invalid.
24+
*/
25+
public class ModelInvalidException extends RuntimeException {
26+
private final List<ValidationEntry> validationEntries;
27+
28+
private ModelInvalidException(Builder b) {
29+
super("Validation failed with the following errors: " + b.validationEntries);
30+
this.validationEntries = Collections.unmodifiableList(new ArrayList<>(b.validationEntries));
31+
}
32+
33+
public List<ValidationEntry> validationEntries() {
34+
return validationEntries;
35+
}
36+
37+
public static Builder builder() {
38+
return new Builder();
39+
}
40+
41+
public static class Builder {
42+
private List<ValidationEntry> validationEntries;
43+
44+
public Builder validationEntries(List<ValidationEntry> validationEntries) {
45+
if (validationEntries == null) {
46+
this.validationEntries = Collections.emptyList();
47+
} else {
48+
this.validationEntries = validationEntries;
49+
}
50+
51+
return this;
52+
}
53+
54+
public ModelInvalidException build() {
55+
return new ModelInvalidException(this);
56+
}
57+
}
58+
}

codegen/src/main/java/software/amazon/awssdk/codegen/validation/ValidationEntry.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
package software.amazon.awssdk.codegen.validation;
1717

18+
import software.amazon.awssdk.utils.ToString;
19+
1820
public final class ValidationEntry {
1921
private ValidationErrorId errorId;
2022
private ValidationErrorSeverity severity;
@@ -58,4 +60,13 @@ public ValidationEntry withDetailMessage(String detailMessage) {
5860
setDetailMessage(detailMessage);
5961
return this;
6062
}
63+
64+
@Override
65+
public String toString() {
66+
return ToString.builder("ValidationEntry")
67+
.add("errorId", errorId)
68+
.add("severity", severity)
69+
.add("detailMessage", detailMessage)
70+
.build();
71+
}
6172
}

codegen/src/main/java/software/amazon/awssdk/codegen/validation/ValidationErrorId.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ public enum ValidationErrorId {
2020
"The shared models between two services differ in their definition, which causes differences in the source"
2121
+ " files generated by the code generator."
2222
),
23-
MEMBER_WITH_UNKNOWN_SHAPE(
24-
"The shape declares a member targeting an unknown shape."
25-
),
23+
UNKNOWN_SHAPE_MEMBER("The model references an unknown shape member."),
2624
;
2725

2826
private final String description;

0 commit comments

Comments
 (0)