@@ -3,10 +3,11 @@ package types
33import (
44 "encoding/json"
55 "fmt"
6+ "testing"
7+
68 "github.com/oapi-codegen/nullable"
79 "github.com/stretchr/testify/assert"
810 "github.com/stretchr/testify/require"
9- "testing"
1011)
1112
1213type SimpleStringNullableRequired struct {
@@ -279,55 +280,54 @@ func TestNullableOptional_UnmarshalJSON(t *testing.T) {
279280 type testCase struct {
280281 name string
281282 json []byte
282- assert func (obj SimpleIntNullableOptional , t * testing.T )
283+ assert func (t * testing.T , obj SimpleIntNullableOptional )
283284 }
284285 tests := []testCase {
285286 {
286287 name : "when not provided" ,
287288 json : []byte (`{}` ),
288- assert : func (obj SimpleIntNullableOptional , t * testing.T ) {
289+ assert : func (t * testing.T , obj SimpleIntNullableOptional ) {
289290 t .Helper ()
290291
291- assert .Equalf ( t , false , obj .ReplicaCount .IsSpecified (), "replica count should not be set" )
292- assert .Equalf ( t , false , obj .ReplicaCount .IsNull (), "replica count should not be null" )
292+ assert .Falsef ( t , obj .ReplicaCount .IsSpecified (), "replica count should not be set" )
293+ assert .Falsef ( t , obj .ReplicaCount .IsNull (), "replica count should not be null" )
293294 },
294295 },
295296
296297 {
297298 name : "when explicitly set to zero value" ,
298299 json : []byte (`{"replica_count":0}` ),
299- assert : func (obj SimpleIntNullableOptional , t * testing.T ) {
300+ assert : func (t * testing.T , obj SimpleIntNullableOptional ) {
300301 t .Helper ()
301302
302- assert .Equalf ( t , true , obj .ReplicaCount .IsSpecified (), "replica count should be set" )
303- assert .Equalf ( t , false , obj .ReplicaCount .IsNull (), "replica count should not be null" )
303+ assert .Truef ( t , obj .ReplicaCount .IsSpecified (), "replica count should be set" )
304+ assert .Falsef ( t , obj .ReplicaCount .IsNull (), "replica count should not be null" )
304305
305306 val , err := obj .ReplicaCount .Get ()
306307 require .NoError (t , err )
307308 assert .Equalf (t , 0 , val , "replica count value should be 0" )
308-
309309 },
310310 },
311311
312312 {
313313 name : "when explicitly set to null value" ,
314314 json : []byte (`{"replica_count":null}` ),
315- assert : func (obj SimpleIntNullableOptional , t * testing.T ) {
315+ assert : func (t * testing.T , obj SimpleIntNullableOptional ) {
316316 t .Helper ()
317317
318- assert .Equalf ( t , true , obj .ReplicaCount .IsSpecified (), "replica count should be set" )
319- assert .Equalf ( t , true , obj .ReplicaCount .IsNull (), "replica count should be null" )
318+ assert .Truef ( t , obj .ReplicaCount .IsSpecified (), "replica count should be set" )
319+ assert .Truef ( t , obj .ReplicaCount .IsNull (), "replica count should be null" )
320320 },
321321 },
322322
323323 {
324324 name : "when explicitly set to a specific value" ,
325325 json : []byte (`{"replica_count":5}` ),
326- assert : func (obj SimpleIntNullableOptional , t * testing.T ) {
326+ assert : func (t * testing.T , obj SimpleIntNullableOptional ) {
327327 t .Helper ()
328328
329- assert .Equalf (t , true , obj .ReplicaCount .IsSpecified (), "replica count should not be null " )
330- assert .Equalf ( t , false , obj .ReplicaCount .IsNull (), "replica count should not be null" )
329+ assert .Truef (t , obj .ReplicaCount .IsSpecified (), "replica count should be set " )
330+ assert .Falsef ( t , obj .ReplicaCount .IsNull (), "replica count should not be null" )
331331
332332 val , err := obj .ReplicaCount .Get ()
333333 require .NoError (t , err )
@@ -340,7 +340,8 @@ func TestNullableOptional_UnmarshalJSON(t *testing.T) {
340340 var obj SimpleIntNullableOptional
341341 err := json .Unmarshal (tt .json , & obj )
342342 require .NoError (t , err )
343- tt .assert (obj , t )
343+
344+ tt .assert (t , obj )
344345 })
345346 }
346347}
@@ -403,7 +404,7 @@ func TestNullableRequired_UnmarshalJSON(t *testing.T) {
403404 type testCase struct {
404405 name string
405406 json []byte
406- assert func (obj SimpleIntNullableRequired , t * testing.T )
407+ assert func (t * testing.T , obj SimpleIntNullableRequired )
407408 }
408409 tests := []testCase {
409410 {
@@ -412,22 +413,22 @@ func TestNullableRequired_UnmarshalJSON(t *testing.T) {
412413 // the behaviour
413414 name : "when not provided" ,
414415 json : []byte (`{}` ),
415- assert : func (obj SimpleIntNullableRequired , t * testing.T ) {
416+ assert : func (t * testing.T , obj SimpleIntNullableRequired ) {
416417 t .Helper ()
417418
418- assert .Equalf ( t , false , obj .ReplicaCount .IsNull (), "replica count should not be null" )
419- assert .Equalf ( t , false , obj .ReplicaCount .IsSpecified (), "replica count should not be set" )
419+ assert .Falsef ( t , obj .ReplicaCount .IsNull (), "replica count should not be null" )
420+ assert .Falsef ( t , obj .ReplicaCount .IsSpecified (), "replica count should not be set" )
420421 },
421422 },
422423
423424 {
424425 name : "when explicitly set to zero value" ,
425426 json : []byte (`{"replica_count":0}` ),
426- assert : func (obj SimpleIntNullableRequired , t * testing.T ) {
427+ assert : func (t * testing.T , obj SimpleIntNullableRequired ) {
427428 t .Helper ()
428429
429- assert .Equalf ( t , false , obj .ReplicaCount .IsNull (), "replica count should not be null" )
430- assert .Equalf ( t , true , obj .ReplicaCount .IsSpecified (), "replica count should be set" )
430+ assert .Falsef ( t , obj .ReplicaCount .IsNull (), "replica count should not be null" )
431+ assert .Truef ( t , obj .ReplicaCount .IsSpecified (), "replica count should be set" )
431432
432433 val , err := obj .ReplicaCount .Get ()
433434 require .NoError (t , err )
@@ -438,22 +439,22 @@ func TestNullableRequired_UnmarshalJSON(t *testing.T) {
438439 {
439440 name : "when explicitly set to null value" ,
440441 json : []byte (`{"replica_count":null}` ),
441- assert : func (obj SimpleIntNullableRequired , t * testing.T ) {
442+ assert : func (t * testing.T , obj SimpleIntNullableRequired ) {
442443 t .Helper ()
443444
444- assert .Equalf ( t , true , obj .ReplicaCount .IsSpecified (), "replica count should be set" )
445- assert .Equalf ( t , true , obj .ReplicaCount .IsNull (), "replica count should be null" )
445+ assert .Truef ( t , obj .ReplicaCount .IsSpecified (), "replica count should be set" )
446+ assert .Truef ( t , obj .ReplicaCount .IsNull (), "replica count should be null" )
446447 },
447448 },
448449
449450 {
450451 name : "when explicitly set to a specific value" ,
451452 json : []byte (`{"replica_count":5}` ),
452- assert : func (obj SimpleIntNullableRequired , t * testing.T ) {
453+ assert : func (t * testing.T , obj SimpleIntNullableRequired ) {
453454 t .Helper ()
454455
455- assert .Equalf ( t , false , obj .ReplicaCount .IsNull (), "replica count should not be null" )
456- assert .Equalf ( t , true , obj .ReplicaCount .IsSpecified (), "replica count should be set" )
456+ assert .Falsef ( t , obj .ReplicaCount .IsNull (), "replica count should not be null" )
457+ assert .Truef ( t , obj .ReplicaCount .IsSpecified (), "replica count should be set" )
457458
458459 val , err := obj .ReplicaCount .Get ()
459460 require .NoError (t , err )
@@ -466,35 +467,179 @@ func TestNullableRequired_UnmarshalJSON(t *testing.T) {
466467 var obj SimpleIntNullableRequired
467468 err := json .Unmarshal (tt .json , & obj )
468469 require .NoError (t , err )
469- tt .assert (obj , t )
470+
471+ tt .assert (t , obj )
472+ })
473+ }
474+ }
475+
476+ type ComplexNullable struct {
477+ Config nullable.Nullable [Config ] `json:"config,omitempty"`
478+ Location nullable.Nullable [string ] `json:"location"`
479+ NodeCount nullable.Nullable [int ] `json:"node_count,omitempty"`
480+ }
481+
482+ type Config struct {
483+ CPU nullable.Nullable [string ] `json:"cpu,omitempty"`
484+ RAM nullable.Nullable [string ] `json:"ram,omitempty"`
485+ }
486+
487+ func TestComplexNullable (t * testing.T ) {
488+ type testCase struct {
489+ name string
490+ jsonInput []byte
491+ assert func (t * testing.T , obj ComplexNullable )
492+ }
493+ tests := []testCase {
494+ {
495+ name : "complex object: empty value" ,
496+ jsonInput : []byte (`{}` ),
497+ assert : func (t * testing.T , obj ComplexNullable ) {
498+ t .Helper ()
499+
500+ assert .Falsef (t , obj .Config .IsSpecified (), "config should not be set" )
501+ assert .Falsef (t , obj .Config .IsNull (), "config should not be null" )
502+
503+ assert .Falsef (t , obj .NodeCount .IsSpecified (), "node count should not be set" )
504+ assert .Falsef (t , obj .NodeCount .IsNull (), "node count should not be null" )
505+
506+ assert .Falsef (t , obj .Location .IsSpecified (), "location should not be set" )
507+ assert .Falsef (t , obj .Location .IsNull (), "location should not be null" )
508+ },
509+ },
510+ {
511+ name : "complex object: empty config value" ,
512+ jsonInput : []byte (`{"config":{}}` ),
513+ assert : func (t * testing.T , obj ComplexNullable ) {
514+ t .Helper ()
515+
516+ assert .Truef (t , obj .Config .IsSpecified (), "config should be set" )
517+ assert .Falsef (t , obj .Config .IsNull (), "config should not be null" )
518+
519+ gotConfig , err := obj .Config .Get ()
520+ require .NoError (t , err )
521+
522+ assert .Falsef (t , gotConfig .CPU .IsSpecified (), "cpu should not be set" )
523+ assert .Falsef (t , gotConfig .CPU .IsNull (), "cpu should not be null" )
524+
525+ assert .Falsef (t , gotConfig .RAM .IsSpecified (), "ram should not be set" )
526+ assert .Falsef (t , gotConfig .RAM .IsNull (), "ram should not be null" )
527+ },
528+ },
529+
530+ {
531+ name : "complex object: setting only cpu config value" ,
532+ jsonInput : []byte (`{"config":{"cpu":"500"}}` ),
533+ assert : func (t * testing.T , obj ComplexNullable ) {
534+ t .Helper ()
535+
536+ assert .Truef (t , obj .Config .IsSpecified (), "config should be set" )
537+ assert .Falsef (t , obj .Config .IsNull (), "config should not be null" )
538+
539+ gotConfig , err := obj .Config .Get ()
540+ require .NoError (t , err )
541+
542+ assert .Truef (t , gotConfig .CPU .IsSpecified (), "cpu should be set" )
543+ assert .Falsef (t , gotConfig .CPU .IsNull (), "cpu should not be null" )
544+
545+ assert .Falsef (t , gotConfig .RAM .IsSpecified (), "ram should not be set" )
546+ assert .Falsef (t , gotConfig .RAM .IsNull (), "ram should not be null" )
547+ },
548+ },
549+
550+ {
551+ name : "complex object: setting only ram config value" ,
552+ jsonInput : []byte (`{"config":{"ram":"1024"}}` ),
553+ assert : func (t * testing.T , obj ComplexNullable ) {
554+ t .Helper ()
555+
556+ assert .Truef (t , obj .Config .IsSpecified (), "config should be set" )
557+ assert .Falsef (t , obj .Config .IsNull (), "config should not be null" )
558+
559+ gotConfig , err := obj .Config .Get ()
560+ require .NoError (t , err )
561+
562+ assert .Falsef (t , gotConfig .CPU .IsSpecified (), "cpu should not be set" )
563+ assert .Falsef (t , gotConfig .CPU .IsNull (), "cpu should not be null" )
564+
565+ assert .Truef (t , gotConfig .RAM .IsSpecified (), "ram should be set" )
566+ assert .Falsef (t , gotConfig .RAM .IsNull (), "ram should not be null" )
567+ },
568+ },
569+
570+ {
571+ name : "complex object: setting config to null" ,
572+ jsonInput : []byte (`{"config":null}` ),
573+ assert : func (t * testing.T , obj ComplexNullable ) {
574+ t .Helper ()
575+
576+ assert .Truef (t , obj .Config .IsSpecified (), "config should be set" )
577+ assert .Truef (t , obj .Config .IsNull (), "config should not be null" )
578+ },
579+ },
580+
581+ {
582+ name : "complex object: setting only cpu config to null" ,
583+ jsonInput : []byte (`{"config":{"cpu":null}}` ),
584+ assert : func (t * testing.T , obj ComplexNullable ) {
585+ t .Helper ()
586+
587+ assert .Truef (t , obj .Config .IsSpecified (), "config should be set" )
588+ assert .Falsef (t , obj .Config .IsNull (), "config should not be null" )
589+
590+ gotConfig , err := obj .Config .Get ()
591+ require .NoError (t , err )
592+
593+ assert .Truef (t , gotConfig .CPU .IsSpecified (), "cpu should be set" )
594+ assert .Truef (t , gotConfig .CPU .IsNull (), "cpu should be null" )
595+
596+ assert .Falsef (t , gotConfig .RAM .IsSpecified (), "ram should not be set" )
597+ assert .Falsef (t , gotConfig .RAM .IsNull (), "ram should not be null" )
598+ },
599+ },
600+ }
601+ for _ , tt := range tests {
602+ t .Run (tt .name , func (t * testing.T ) {
603+ var obj ComplexNullable
604+ err := json .Unmarshal (tt .jsonInput , & obj )
605+ require .NoError (t , err )
606+
607+ tt .assert (t , obj )
470608 })
471609 }
472610}
473611
474- // Idempotency tests for nullable and optional
612+ // Tests to validate that repeated unmarshal and marshal should not change
613+ // the JSON for optional and nullable.
475614type StringNullableOptional struct {
476615 ID nullable.Nullable [string ] `json:"id,omitempty"`
477616 Name nullable.Nullable [string ] `json:"name,omitempty"`
478617 Address nullable.Nullable [string ] `json:"address,omitempty"`
479618}
480619
481- func TestNullableOptionalUnmarshalIdempotency (t * testing.T ) {
620+ func TestNullableOptionalUnmarshal (t * testing.T ) {
482621 var obj1 StringNullableOptional
483622 originalJSON1 := []byte (`{}` )
623+
484624 err := json .Unmarshal (originalJSON1 , & obj1 )
485625 require .NoError (t , err )
486626 newJSON1 , err := json .Marshal (obj1 )
627+ require .NoError (t , err )
628+
487629 require .Equal (t , originalJSON1 , newJSON1 )
488630
489631 var obj2 StringNullableOptional
490632 originalJSON2 := []byte (`{"id":"12esd412"}` )
491- err2 := json .Unmarshal (originalJSON2 , & obj2 )
492- require .NoError (t , err2 )
493- newJSON2 , err2 := json .Marshal (obj2 )
633+
634+ err = json .Unmarshal (originalJSON2 , & obj2 )
635+ require .NoError (t , err )
636+ newJSON2 , err := json .Marshal (obj2 )
637+ require .NoError (t , err )
638+
494639 require .Equal (t , originalJSON2 , newJSON2 )
495640}
496641
497- func TestNullableOptionalMarshalIdempotency (t * testing.T ) {
642+ func TestNullableOptionalMarshal (t * testing.T ) {
498643 obj1 := StringNullableOptional {
499644 ID : nullable.Nullable [string ]{
500645 true : "id-1" ,
@@ -507,8 +652,8 @@ func TestNullableOptionalMarshalIdempotency(t *testing.T) {
507652 },
508653 }
509654 expectedJSON1 := []byte (`{"id":"id-1","name":"","address":null}` )
510- gotJSON1 , err1 := json .Marshal (obj1 )
511- require .NoError (t , err1 )
655+ gotJSON1 , err := json .Marshal (obj1 )
656+ require .NoError (t , err )
512657 require .Equal (t , expectedJSON1 , gotJSON1 )
513658
514659 obj2 := StringNullableOptional {
@@ -520,7 +665,7 @@ func TestNullableOptionalMarshalIdempotency(t *testing.T) {
520665 },
521666 }
522667 expectedJSON2 := []byte (`{"id":"id-1","address":null}` )
523- gotJSON2 , err2 := json .Marshal (obj2 )
524- require .NoError (t , err2 )
668+ gotJSON2 , err := json .Marshal (obj2 )
669+ require .NoError (t , err )
525670 require .Equal (t , expectedJSON2 , gotJSON2 )
526671}
0 commit comments