Skip to content

Commit

Permalink
Add tests for Record deserialization regression and related (#3921)
Browse files Browse the repository at this point in the history
  • Loading branch information
JooHyukKim authored May 22, 2023
1 parent 3140bb7 commit 228bc0e
Showing 1 changed file with 161 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package com.fasterxml.jackson.databind.failing;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BaseMapTest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector;
import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
import com.fasterxml.jackson.databind.module.SimpleModule;

/**
* Test case that covers both failing-by-regression tests and passing tests.
* <p>For more details, refer to
* <a href="https://github.com/FasterXML/jackson-databind/issues/3906">
* [databind#3906]: Regression: 2.15.0 breaks deserialization for records when mapper.setVisibility(ALL, NONE);</a>
*/
public class RecordDeserialization3906Test extends BaseMapTest {

/*
/**********************************************************
/* Set up
/**********************************************************
*/

record Record3906(String string, int integer) {
}

@JsonAutoDetect(creatorVisibility = Visibility.NON_PRIVATE)
record Record3906Annotated(String string, int integer) {
}

record Record3906Creator(String string, int integer) {
@JsonCreator
Record3906Creator {
}
}

private record PrivateRecord3906(String string, int integer) {
}

/*
/**********************************************************
/* Failing tests that pass in 2.14 (regression)
/**********************************************************
*/

// minimal config for reproduction
public void testEmptyJsonToRecordMiminal() throws JsonProcessingException {
ObjectMapper mapper = newJsonMapper();
mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);

Record3906 recordDeser = mapper.readValue("{}", Record3906.class);

assertEquals(new Record3906(null, 0), recordDeser);
}

// actual config used reproduction
public void testEmptyJsonToRecordActualImpl() throws JsonProcessingException {
ObjectMapper mapper = newJsonMapper();
mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

Record3906 recordDeser = mapper.readValue("{}", Record3906.class);

assertEquals(new Record3906(null, 0), recordDeser);
}

/*
/**********************************************************
/* Passing Tests : Suggested work-arounds
/* for future modifications
/**********************************************************
*/

public void testEmptyJsonToRecordWorkAround() throws JsonProcessingException {
ObjectMapper mapper = newJsonMapper();
mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
mapper.setVisibility(PropertyAccessor.CREATOR, Visibility.ANY);

Record3906 recordDeser = mapper.readValue("{}", Record3906.class);

assertEquals(new Record3906(null, 0), recordDeser);
}

public void testEmptyJsonToRecordCreatorsVisibile() throws JsonProcessingException {
ObjectMapper mapper = newJsonMapper();
mapper.setVisibility(PropertyAccessor.CREATOR, Visibility.NON_PRIVATE);

Record3906 recordDeser = mapper.readValue("{}", Record3906.class);
assertEquals(new Record3906(null, 0), recordDeser);
}

public void testEmptyJsonToRecordUsingModule() throws JsonProcessingException {
ObjectMapper mapper = jsonMapperBuilder().addModule(new SimpleModule() {
@Override
public void setupModule(SetupContext context) {
super.setupModule(context);
context.insertAnnotationIntrospector(new NopAnnotationIntrospector() {
@Override
public VisibilityChecker<?> findAutoDetectVisibility(AnnotatedClass ac,
VisibilityChecker<?> checker) {
return ac.getType().isRecordType()
? checker.withCreatorVisibility(JsonAutoDetect.Visibility.NON_PRIVATE)
: checker;
}
});
}
}).build();

Record3906 recordDeser = mapper.readValue("{}", Record3906.class);
assertEquals(new Record3906(null, 0), recordDeser);
}

public void testEmptyJsonToRecordDirectAutoDetectConfig() throws JsonProcessingException {
ObjectMapper mapper = newJsonMapper();

Record3906Annotated recordDeser = mapper.readValue("{}", Record3906Annotated.class);
assertEquals(new Record3906Annotated(null, 0), recordDeser);
}

public void testEmptyJsonToRecordJsonCreator() throws JsonProcessingException {
ObjectMapper mapper = newJsonMapper();

Record3906Creator recordDeser = mapper.readValue("{}", Record3906Creator.class);
assertEquals(new Record3906Creator(null, 0), recordDeser);
}

public void testEmptyJsonToRecordUsingModuleOther() throws JsonProcessingException {
ObjectMapper mapper = jsonMapperBuilder().addModule(
new SimpleModule() {
@Override
public void setupModule(SetupContext context) {
super.setupModule(context);
context.insertAnnotationIntrospector(new NopAnnotationIntrospector() {
@Override
public VisibilityChecker<?> findAutoDetectVisibility(AnnotatedClass ac,
VisibilityChecker<?> checker) {
if (ac.getType() == null) {
return checker;
}
if (!ac.getType().isRecordType()) {
return checker;
}
// If this is a Record, then increase the "creator" visibility again
return checker.withCreatorVisibility(Visibility.ANY);
}
});
}
})
.build();

assertEquals(new Record3906(null, 0),
mapper.readValue("{}", Record3906.class));
assertEquals(new PrivateRecord3906(null, 0),
mapper.readValue("{}", PrivateRecord3906.class));
}
}

0 comments on commit 228bc0e

Please sign in to comment.