-
Notifications
You must be signed in to change notification settings - Fork 6
Fix not to render optional fields when unset #55
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
Conversation
String cdEventJson = CDEvents.cdEventAsJson(cdEvent); | ||
|
||
CloudEvent ceEvent = CDEvents.cdEventAsCloudEvent(cdEvent); | ||
|
||
String ceDataJson = new String(ceEvent.getData().toBytes(), StandardCharsets.UTF_8); | ||
|
||
assertThat(ceEvent.getType()).isEqualTo(cdEvent.getContext().getType()); | ||
assertThat(ceEvent.getSource()).isEqualTo(cdEvent.getContext().getSource()); | ||
assertThat(ceDataJson).isEqualTo(cdEventJson); |
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.
If I understand the test correctly, what it does it:
- create a CDEvent object, renders it to json
- create a CloudEvent out of the CDEvent
- extract the payload from the CloudEvent and matches is against the CDEvent as json
- compare type and source
This looks good to test check CloudEvent binding, but how does it help to test the unset fields?
Don't we need JSON documents as test data for that?
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.
Yes, added test data to compare optional fields with the actual CDEvent.
To keep this PR smaller, added the optional field validation only for Core events for now, will create separate PRs to handle tests for other type of events.
@Test | ||
void createTaskRunFinishedEventWithOptionalFieldsUnset() throws IOException { | ||
InputStream inputStream = getClass().getResourceAsStream("/taskrun_finished_optional.json"); | ||
TaskRunFinishedCDEvent expectedCDEvent = objectMapper.readValue(inputStream, TaskRunFinishedCDEvent.class); |
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.
I think this can be ok, it guarantees consistent behaviour, however, I'm not 100% it guarantees that optional fields are not included in the rendered JSON.
At this level, I know that:
- if I create an object without optional fields, those optional fields are not set in the object.
- if I render that object without optional fields and parse it back, those optional fields are not set in the object.
- If a load an object from JSON that does not specify optional fields, those optional fields are not set in the object
I'm still not 100% sure that the rendered JSON will not contain the optional fields set as well, but perhaps that's covered already by other tests - wdyt?
I see two possible ways we could test that further - possibly not for every event, just once might be enough.
- either read bytes from
inputStream
and compare it withcdEventJson
converted to bytes. This can be tricky since you may need to compact the json first (to avoid issues with spaces, indentations etc) and also ordering in dicts may be an issue unless the json rendered implementation always renders in the same order - or add one resource file with the optional fields set to empty value. Load it and check that the optional fields are in the object, with empty or null value.
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.
Yes it compares the Subject's content object as whole but not field to filed comparison.
Or I can compare from both the objects that all optional fields are set to null and they are equal, something like;
assertThat(cdEvent.getSubject().getContent().getTaskName()).isEqualTo(null);
assertThat(expectedCDEvent.getSubject().getContent().getTaskName()).isEqualTo(null);
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.
Now updated the test validation by comparing the JsonNodes created from inputStream
and cdEventJson
This way I can compare actual and expected optional and mandatory fields from the test data.
cdEvent.setSubjectPipelineRunId("/dev/pipeline/run/subject"); | ||
|
||
String cdEventJson = CDEvents.cdEventAsJson(cdEvent); | ||
CloudEvent ceEvent = CDEvents.cdEventAsCloudEvent(cdEvent); |
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.
Do we really need to go through the cloudevent binding in this test?
It does not harm but I thought that would be covered already by previous tests.
It's fine to keep it if you deem it relevant here.
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.
Yes to validate the CDEvent against schema, I need to invoke CDEvents.cdEventAsCloudEvent(cdEvent);
But I think I can move validation part to the CDEvents.cdEventAsJson(cdEvent);
method itself as cdEventAsJson()
is invoked from cdEventAsCloudEvent()
to set the data in the CloudEvent. So that I can remove cloudevent binding from this test also.
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.
Thanks for the clarification!
|
||
PipelineRunFinishedSubjectContent that = (PipelineRunFinishedSubjectContent) o; | ||
|
||
if (getPipelineName() != null ? !getPipelineName().equals(that.getPipelineName()) : that.getPipelineName() != null) { |
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.
NIT: Since pipeline name is a string
, this could be if (getPipelineName() == that.getPipelineName())
which would return true
also in case they're both null
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.
Now updated the test validation by comparing the JsonNodes, equals
method is no longer needed.
@@ -36,6 +36,10 @@ private CDEvents() { | |||
*/ | |||
public static String cdEventAsJson(CDEvent cdEvent) { | |||
try { | |||
if (!validateCDEvent(cdEvent)) { |
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.
Thanks - I think this is fine, perhaps in future, we might add a flag to make validation optional.
In the golang SDK I did not include validation in the JSON rendering, I made a validate
method available instead, so that it is possible to render and invalid CDEvent to JSON, and the producer can decide whether to validate or not.
I did include a call to validate
in the cloudevents binding to enforce sending of valid events thought (similar to what you had before).
I wonder whether instead of moving the validation from cdEventAsCloudEvent
to cdEventAsJson
, it would be better to add a call to validate
in the test?
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.
I'm also ok with keeping it as it is today.
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.
Agree, even this keeps the behavior consistent.
Reverting to keep the validation only for CloudEvents binding, removed for JSON render and added test assertion to validate CDEvent against schema.
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.
Thanks for the updates!
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.
Thanks for the updates!
@rjalander is it ok if squash and merge now, or would you like more reviews from other Java SDK maintainers? |
I think we are good to merge, If you have no other comments. |
🎉 This issue has been resolved in |
This PR has the changes to fix the issue #51, not to render the optional fields when null during serialization using an ObjectMapper.