github.com/ipld/go-ipld-prime@v0.21.0/node/tests/schemaStructsContainingMaybe.go (about) 1 package tests 2 3 import ( 4 "testing" 5 6 "github.com/ipld/go-ipld-prime/datamodel" 7 "github.com/ipld/go-ipld-prime/schema" 8 ) 9 10 // TestStructsContainingMaybe checks all the variations of "nullable" and "optional" on struct fields. 11 // It does this twice: once for the child maybes being implemented with pointers, 12 // and once with maybes implemented as embeds. 13 // The child values are scalars. 14 // 15 // Both type-level generic build and access as well as representation build and access are exercised; 16 // the representation used is map (the native representation for structs). 17 func SchemaTestStructsContainingMaybe(t *testing.T, engine Engine) { 18 // Type declarations. 19 // The tests here will all be targetted against this "Stroct" type. 20 ts := schema.TypeSystem{} 21 ts.Init() 22 ts.Accumulate(schema.SpawnString("String")) 23 ts.Accumulate(schema.SpawnStruct("Stroct", 24 []schema.StructField{ 25 // Every field in this struct (including their order) is exercising an interesting case... 26 schema.SpawnStructField("f1", "String", false, false), // plain field. 27 schema.SpawnStructField("f2", "String", true, false), // optional; later we have more than one optional field, nonsequentially. 28 schema.SpawnStructField("f3", "String", false, true), // nullable; but required. 29 schema.SpawnStructField("f4", "String", true, true), // optional and nullable; trailing optional. 30 schema.SpawnStructField("f5", "String", true, false), // optional; and the second one in a row, trailing. 31 }, 32 schema.SpawnStructRepresentationMap(map[string]string{ 33 "f1": "r1", 34 "f2": "r2", 35 "f3": "r3", 36 "f4": "r4", 37 }), 38 )) 39 engine.Init(t, ts) 40 41 // There's a lot of cases to cover so a shorthand code labels each case for clarity: 42 // - 'v' -- value in that entry 43 // - 'n' -- null in that entry 44 // - 'z' -- absent entry 45 // There's also a semantic description of the main detail being probed suffixed to the shortcode. 46 specs := []testcase{ 47 { 48 name: "vvvvv-AllFieldsSet", 49 typeJson: `{"f1":"a","f2":"b","f3":"c","f4":"d","f5":"e"}`, 50 reprJson: `{"f5":"e","r1":"a","r2":"b","r3":"c","r4":"d"}`, 51 typePoints: []testcasePoint{ 52 {"", datamodel.Kind_Map}, 53 {"f1", "a"}, 54 {"f2", "b"}, 55 {"f3", "c"}, 56 {"f4", "d"}, 57 {"f5", "e"}, 58 }, 59 reprPoints: []testcasePoint{ 60 {"", datamodel.Kind_Map}, 61 {"r1", "a"}, 62 {"r2", "b"}, 63 {"r3", "c"}, 64 {"r4", "d"}, 65 {"f5", "e"}, 66 }, 67 }, 68 { 69 name: "vvnnv-Nulls", 70 typeJson: `{"f1":"a","f2":"b","f3":null,"f4":null,"f5":"e"}`, 71 reprJson: `{"f5":"e","r1":"a","r2":"b","r3":null,"r4":null}`, 72 typePoints: []testcasePoint{ 73 {"", datamodel.Kind_Map}, 74 {"f1", "a"}, 75 {"f2", "b"}, 76 {"f3", datamodel.Null}, 77 {"f4", datamodel.Null}, 78 {"f5", "e"}, 79 }, 80 reprPoints: []testcasePoint{ 81 {"", datamodel.Kind_Map}, 82 {"r1", "a"}, 83 {"r2", "b"}, 84 {"r3", datamodel.Null}, 85 {"r4", datamodel.Null}, 86 {"f5", "e"}, 87 }, 88 }, 89 { 90 name: "vzvzv-AbsentOptionals", 91 typeJson: `{"f1":"a","f3":"c","f5":"e"}`, 92 reprJson: `{"f5":"e","r1":"a","r3":"c"}`, 93 typePoints: []testcasePoint{ 94 {"", datamodel.Kind_Map}, 95 {"f1", "a"}, 96 {"f2", datamodel.Absent}, 97 {"f3", "c"}, 98 {"f4", datamodel.Absent}, 99 {"f5", "e"}, 100 }, 101 reprPoints: []testcasePoint{ 102 {"", datamodel.Kind_Map}, 103 {"r1", "a"}, 104 //{"r2", datamodel.ErrNotExists{}}, // TODO: need better error typing from traversal package. 105 {"r3", "c"}, 106 //{"r4", datamodel.ErrNotExists{}}, // TODO: need better error typing from traversal package. 107 {"f5", "e"}, 108 }, 109 typeItr: []entry{ 110 {"f1", "a"}, 111 {"f2", datamodel.Absent}, 112 {"f3", "c"}, 113 {"f4", datamodel.Absent}, 114 {"f5", "e"}, 115 }, 116 }, 117 { 118 name: "vvnzz-AbsentTrailingOptionals", 119 typeJson: `{"f1":"a","f2":"b","f3":null}`, 120 reprJson: `{"r1":"a","r2":"b","r3":null}`, 121 typePoints: []testcasePoint{ 122 {"", datamodel.Kind_Map}, 123 {"f1", "a"}, 124 {"f2", "b"}, 125 {"f3", datamodel.Null}, 126 {"f4", datamodel.Absent}, 127 {"f5", datamodel.Absent}, 128 }, 129 reprPoints: []testcasePoint{ 130 {"", datamodel.Kind_Map}, 131 {"r1", "a"}, 132 {"r2", "b"}, 133 {"r3", datamodel.Null}, 134 //{"r4", datamodel.ErrNotExists{}}, // TODO: need better error typing from traversal package. 135 //{"f5", datamodel.ErrNotExists{}}, // TODO: need better error typing from traversal package. 136 }, 137 typeItr: []entry{ 138 {"f1", "a"}, 139 {"f2", "b"}, 140 {"f3", datamodel.Null}, 141 {"f4", datamodel.Absent}, 142 {"f5", datamodel.Absent}, 143 }, 144 }, 145 } 146 147 for _, tcase := range specs { 148 tcase.Test(t, engine.PrototypeByName("Stroct"), engine.PrototypeByName("Stroct.Repr")) 149 } 150 }