GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — Add tests for `nullable` type by sonasingh46 · Pull Request #26 · oapi-codegen/runtime Conversation
|
| // MarshalJSON implements the Marshaler interface. | ||
| func (t Nullable[T]) MarshalJSON() ([]byte, error) { | ||
| if t.IsNull() { | ||
| return nullBytes, nil |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
We need to replace this with:
| return nullBytes, nil | |
| return []byte("null"), nil |
Right now, we've got the risk that someone could do something like:
func TestF(t *testing.T) { var n Nullable[string] n.Null = true b, err := n.MarshalJSON() fmt.Printf("b: %v\n", b) fmt.Printf("b: %s\n", b) fmt.Printf("err: %v\n", err) b[1] = '_' b_, err := n.MarshalJSON() fmt.Printf("b: %v\n", b_) fmt.Printf("b: %s\n", b_) fmt.Printf("err: %v\n", err) }
Which outputs:
b: [110 117 108 108]
b: null
err: <nil>
b: [110 95 108 108]
b: n_ll
err: <nil>
Note that nullBytes from the package is changed.
We could alternatively perform a protective copy, or in this case, just return a literal
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Did not grok this in the first read. Trying to understand it.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Ah! Makes sense now.. So basically some one can alter the nullByte. Good catch.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| assert.NoError(t, err) | ||
| assert.Equalf(t, tt.wantNull, obj.Name.IsNull(), "IsNull()") | ||
| assert.Equalf(t, tt.wantSet, obj.Name.IsSet(), "IsSet()") | ||
| fmt.Println(obj.Name.Get()) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
| fmt.Println(obj.Name.Get()) |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| return t.Set | ||
| } | ||
|
|
||
| func (t *Nullable[T]) Get() (value T, null bool) { |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Think this should be:
| func (t *Nullable[T]) Get() (value T, null bool) { | |
| func (t *Nullable[T]) Get() (value *T, set bool) { |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
On similar line -- now I am thinking we do not need this Get() method too.. Especially when I used in my own implementation -- I did not feel them need to use it especially when it returns 2 values, the code becomes little clumsy.
I think we should add these util functions as and when we need them. wdyt?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| // IsNull returns true if the value is explicitly provided `null` in json | ||
| func (t *Nullable[T]) IsNull() bool { | ||
| return t.Null | ||
| } | ||
|
|
||
| // IsSet returns true if the value is provided in json | ||
| func (t *Nullable[T]) IsSet() bool { | ||
| return t.Set | ||
| } |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Unsure if these are needed if we export the values from the struct?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Hmm.. Agreed.
Set and Null keys is not a good idea as to create a Nullable type it is just easy to have them.I was thinking on that and figured we should have something like the following:
// HasValue returns true if the value is provided in json func (t *Nullable[T]) HasValue() bool { return t.Set && !t.Null }
HasValue() is a good util to have as I felt the need to that while using this type to answer this question:
If this util is not present then one will have to do:
if t.Set && !t.Null {// do something}
vs
if t.HasValue() {// do something}
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| }, | ||
| } | ||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t1 *testing.T) { |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
| t.Run(tt.name, func(t1 *testing.T) { | |
| t.Run(tt.name, func(t *testing.T) { |
Otherwise we're not passing in the correct type.
Shadowing here is fine (in my opinion - happy to chat if there are things to be aware of)
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
typo.. thanks.
Will fix that.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| assert: func(obj TestComplex, t *testing.T) { | ||
| assert.Equalf(t, true, obj.StringList.IsSet(), "string_list should be set") | ||
| assert.Equalf(t, false, obj.StringList.IsNull(), "string_list should not be null") | ||
| gotStringList, isNull := obj.StringList.Get() |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Mind adding newlines for readability?
| gotStringList, isNull := obj.StringList.Get() | |
| gotStringList, isNull := obj.StringList.Get() |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| t.Run(tt.name, func(t1 *testing.T) { | ||
| var obj SimplePointerInt | ||
| err := json.Unmarshal(tt.jsonInput, &obj) | ||
| assert.NoError(t, err) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
May be worth replacing this and similar ones with:
| assert.NoError(t, err) | |
| require.NoError(t, err) |
So we're failing earlier
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
Was the original implementation of the code adapted from https://github.com/guregu/null ? It looks like it but we've not declared so, as the licence would expect? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Not really but definitely adapted the So if we need to declare it or do anything needful, sure! Thanks for bringing this. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
bfc1c43 to
cbea05b
Compare
We have spun out a separate package, `oapi-codegen/nullable` as a step towards oapi-codegen/oapi-codegen#1039. Until we have implemented oapi-codegen#27, we cannot add an explicit type alias in this package, so we can at least add some tests to cover additional functionality and expectations that the package should have when interplaying with `oapi-codegen`. Co-authored-by: Sebastien Guilloux <[email protected]> Co-authored-by: Ashutosh Kumar <[email protected]>
cbea05b to
f26cbc7
Compare
Signed-off-by: Ashutosh Kumar <[email protected]>
| } | ||
| } | ||
|
|
||
| // Idempotency tests for nullable and optional |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Are these actually Idempotency tests? Or can we find a better name?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I think the word idempotency can be simple removed. I will do that.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
|
||
| var obj2 StringNullableOptional | ||
| originalJSON2 := []byte(`{"id":"12esd412"}`) | ||
| err2 := json.Unmarshal(originalJSON2, &obj2) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Why not re-use err?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| name: "when explicitly set to a specific value", | ||
| json: []byte(`{"replica_count":5}`), | ||
| assert: func(t *testing.T, obj SimpleIntNullableRequired) { | ||
| assert: func(obj SimpleIntNullableRequired, t *testing.T) { |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
🛑 please revert this back, the ordering was changed on purpose
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| t.Helper() | ||
|
|
||
| assert.Truef(t, obj.ReplicaCount.IsNull(), "replica count should be null") | ||
| assert.Equalf(t, true, obj.ReplicaCount.IsSpecified(), "replica count should be set") |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Please revert this, we're using Truef on purpose
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| require.NoError(t, err) | ||
|
|
||
| tt.assert(t, obj) | ||
| tt.assert(obj, t) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
newline was added on purpose
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| type testCase struct { | ||
| name string | ||
| jsonInput []byte | ||
| assert func(obj ComplexNullable, t *testing.T) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
| assert func(obj ComplexNullable, t *testing.T) | |
| assert func(t *testing.T, obj ComplexNullable) |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Signed-off-by: Ashutosh Kumar <[email protected]>
ab5218f to
e6e916a
Compare
At least 1 approving review is required to merge this pull request.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.