Skip to content

Commit 1d509ab

Browse files
committed
Fix incorrect bitmask exposed by DeferredMemberSchema
The bitmask applies to the member, not its target schema -- delegating to the target schema exposes the wrong bitmask. Also change MemberSchema.requiredStructureMemberBitfield() to delegate to its target, because the bitfield *is* derived from the target type (not the specific member usage of the target type).
1 parent dec1677 commit 1d509ab

File tree

3 files changed

+39
-8
lines changed

3 files changed

+39
-8
lines changed

core/src/main/java/software/amazon/smithy/java/core/schema/DeferredMemberSchema.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ final class DeferredMemberSchema extends Schema {
1515

1616
private final SchemaBuilder target;
1717
private final TraitMap directTraits;
18+
private final long requiredByValidationBitmask;
1819

1920
DeferredMemberSchema(MemberSchemaBuilder builder) {
2021
super(builder);
2122
this.target = builder.targetBuilder;
2223
this.directTraits = builder.directTraits;
24+
this.requiredByValidationBitmask = builder.requiredByValidationBitmask;
2325
}
2426

2527
@Override
@@ -44,7 +46,9 @@ public int requiredMemberCount() {
4446

4547
@Override
4648
long requiredByValidationBitmask() {
47-
return memberTarget().requiredByValidationBitmask();
49+
// The bitmask applies to the member itself, not its target schema, so this should not be forwarded
50+
// to memberTarget as the previous accessors do.
51+
return requiredByValidationBitmask;
4852
}
4953

5054
@Override

core/src/main/java/software/amazon/smithy/java/core/schema/MemberSchema.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,12 @@ final class MemberSchema extends Schema {
1616

1717
private final Schema target;
1818
private final TraitMap directTraits;
19-
private final long requiredStructureMemberBitfield;
2019
private final long requiredByValidationBitmask;
2120

2221
MemberSchema(MemberSchemaBuilder builder) {
2322
super(builder);
2423
this.target = builder.target;
2524
this.directTraits = builder.directTraits;
26-
this.requiredStructureMemberBitfield = SchemaBuilder.computeRequiredBitField(
27-
type(),
28-
target.requiredMemberCount(),
29-
builder.target.members(),
30-
Schema::requiredByValidationBitmask);
3125
this.requiredByValidationBitmask = builder.requiredByValidationBitmask;
3226
}
3327

@@ -68,7 +62,7 @@ long requiredByValidationBitmask() {
6862

6963
@Override
7064
long requiredStructureMemberBitfield() {
71-
return requiredStructureMemberBitfield;
65+
return target.requiredStructureMemberBitfield();
7266
}
7367

7468
@Override

core/src/test/java/software/amazon/smithy/java/core/schema/ValidatorTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,39 @@ public void detectsTooDeepRecursion() {
131131
assertThat(errors.get(0).path(), equalTo("/"));
132132
}
133133

134+
@Test
135+
public void detectsPresenceForNestedRecursiveFields() {
136+
var innerBuilder = Schema.structureBuilder(ShapeId.from("smithy.example#Inner"))
137+
.putMember("foo", PreludeSchemas.STRING, new RequiredTrait());
138+
var innerSchema = innerBuilder.build();
139+
140+
var innerInstance = TestHelper.create(innerSchema, (schema, serializer) -> {
141+
serializer.writeString(schema.member("foo"), "bar");
142+
});
143+
144+
var rootSchemaWithMember = Schema.structureBuilder(ShapeId.from("smithy.example#Root"))
145+
.putMember("inner", innerSchema, new RequiredTrait())
146+
.build();
147+
var rootInstanceWithMember = TestHelper.create(rootSchemaWithMember, (schema, serializer) -> {
148+
serializer.writeStruct(schema.member("inner"), innerInstance);
149+
});
150+
151+
var rootSchemaWithDeferredMember = Schema.structureBuilder(ShapeId.from("smithy.example#Root"))
152+
.putMember("inner", innerBuilder, new RequiredTrait())
153+
.build();
154+
var rootInstanceWithDeferredMember = TestHelper.create(rootSchemaWithDeferredMember, (schema, serializer) -> {
155+
serializer.writeStruct(schema.member("inner"), innerInstance);
156+
});
157+
158+
var validator = Validator.builder().build();
159+
160+
var memberErrors = validator.validate(rootInstanceWithMember);
161+
assertThat(memberErrors, empty());
162+
163+
var deferredMemberErrors = validator.validate(rootInstanceWithDeferredMember);
164+
assertThat(deferredMemberErrors, empty());
165+
}
166+
134167
private List<Schema> createListSchemas(int depth) {
135168
List<Schema> schemas = new ArrayList<>(depth);
136169
for (int i = depth; i > 0; i--) {

0 commit comments

Comments
 (0)