-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
about testJSONMarshal's behavior #2699
Comments
OK, wow. Thanks for the detailed write-up, @exageraldo ! I believe I might be the original author of testJSONMarshal (this could be verified but is probably not a big deal either way)... I actually thought I was being clever at the time and also thought:
but never researched the behavior of json.Marshal that you have pointed out regarding case sensitivity. So I'm now thinking that maybe my original ideas are not that great compared to the possibility of error creeping into the repo due to case sensitivity issues and the problems you have pointed out. Therefore, I'm thinking that we should go ahead and fix this situation, and I'm happy for you to tackle it unless we hear from anyone else who has a different opinion. |
That's great! |
I found one more observation that we should add. As we pass both structs and maps (like From a StackOverflow answer:
|
When I was investigating issue #2679, I faced the following situation:
After changing the tags in the
ListSCIMProvisionedIdentitiesOptions
structure, fromjson
tourl
, I was expecting theTestListSCIMProvisionedIdentitiesOptions_Marshal
test to fail, but it didn't.It made sense that this test was passing before the change, because the structure was in accordance with the defined tags. However, after the change the tests kept passing.
If we add a few more test cases, we can see that regardless of how the letters are (upper or lower case), the tests always pass (both using the
json
andurl
tags).I created a temporary function with the test cases that should fail, the
TestListSCIMProvisionedIdentitiesOptions_Marshal_MustFailed
function, but all are passing so far.To better understand this behavior, we need to see how the
testJSONMarshal
works.As described in the comments in the code, these are the steps performed by this test:
The value of
want
is used (directly) only once to parse the JSON (json.Unmarshal
). After that it goes the other way (json.Marshal
) to generate a new JSON (w []byte
) and it is this new slice of byte that is used for comparison with the value of the passed structure (j []byte
).An important point in the
json.Unmarshal
documentation is:That is, when we do
json.Unmarshal([]byte(want), &u)
, we are building a structure, giving preference to exact match, but also accepting other cases, as the above cases show. This can become a problem, since the GitHub API is case sensitive. If we switch any case letters, the value sent will be ignored and the default value for that field will be kept.To simplify it a bit more and also to have better control of the tests, I suggest that this function has two steps:
My initial suggestion is something like this:
Some comments about the change:
want
" value){"key":"value"}
){"some_key":"value","other_key":"other_value"}
)bytes.Equal(j, []byte(want))
). The idea is to compare the value generated byjson.Marshal(v)
is exactly equal to the expected value (want
).The way of writing the expected result may be a bit longer in some cases, but it will be much more explicit and predictable.
We can update our
TestListSCIMProvisionedIdentitiesOptions_Marshal
andTestListSCIMProvisionedIdentitiesOptions_Marshal_MustFailed
tests. The only thing we need to do is put the expected value (want
) on a single line, without extra spaces:When we run the tests using the
json
tags in the structure, we notice that the cases insideTestListSCIMProvisionedIdentitiesOptions_Marshal
pass successfully and the cases that should fail, actually fail. This is exactly what we expect!By changing the tags to url, we can see that all cases within
TestListSCIMProvisionedIdentitiesOptions_Marshal
fail, and this is a good sign.In
TestListSCIMProvisionedIdentitiesOptions_Marshal_MustFailed
we have one test case passing, which is the case when all fields in the json are equal to the fields in the structure. In this case this result is really expected.Another curious case we can look at is the
TestUpdateAttributeForSCIMUserOptions_Marshal
. If we run our new version oftestJSONMarshal
, the test will break.We already expected the second case to fail, because we still need to put the whole structure on a single line, but the first case also failed.
We are expecting
{}
and the result is{"operations":{"op":""}}
, but if we look at theUpdateAttributeForSCIMUserOptions
andUpdateAttributeForSCIMUserOperations
structures, it makes a lot of sense.The
Op
field, withinUpdateAttributeForSCIMUserOperations
, is a required field and will not be omitted if it is empty. Thus, we can rewrite our test as follows:There are 410 test functions ending with
_Marshal
in 97 different files. Most likely all these tests will be affected by the change.By making this change and running the tests, about 420 test cases failed. This is a large number, but the vast majority of them will be solved just by formatting the expected value.
I would like to open up these ideas for discussion.
What do you think about this?
I'd be very happy to contribute to this issue.
The text was updated successfully, but these errors were encountered: