github.com/ipld/go-ipld-prime@v0.21.0/node/tests/mapSpecs.go (about) 1 package tests 2 3 import ( 4 "testing" 5 6 qt "github.com/frankban/quicktest" 7 8 "github.com/ipld/go-ipld-prime/datamodel" 9 "github.com/ipld/go-ipld-prime/must" 10 ) 11 12 func SpecTestMapStrInt(t *testing.T, np datamodel.NodePrototype) { 13 t.Run("map<str,int>, 3 entries", func(t *testing.T) { 14 n := buildMapStrIntN3(np) 15 t.Run("reads back out", func(t *testing.T) { 16 qt.Check(t, n.Length(), qt.Equals, int64(3)) 17 18 v, err := n.LookupByString("whee") 19 qt.Check(t, err, qt.IsNil) 20 v2, err := v.AsInt() 21 qt.Check(t, err, qt.IsNil) 22 qt.Check(t, v2, qt.Equals, int64(1)) 23 24 v, err = n.LookupByString("waga") 25 qt.Check(t, err, qt.IsNil) 26 v2, err = v.AsInt() 27 qt.Check(t, err, qt.IsNil) 28 qt.Check(t, v2, qt.Equals, int64(3)) 29 30 v, err = n.LookupByString("woot") 31 qt.Check(t, err, qt.IsNil) 32 v2, err = v.AsInt() 33 qt.Check(t, err, qt.IsNil) 34 qt.Check(t, v2, qt.Equals, int64(2)) 35 }) 36 t.Run("reads via iteration", func(t *testing.T) { 37 itr := n.MapIterator() 38 39 qt.Check(t, itr.Done(), qt.IsFalse) 40 k, v, err := itr.Next() 41 qt.Check(t, err, qt.IsNil) 42 k2, err := k.AsString() 43 qt.Check(t, err, qt.IsNil) 44 qt.Check(t, k2, qt.Equals, "whee") 45 v2, err := v.AsInt() 46 qt.Check(t, err, qt.IsNil) 47 qt.Check(t, v2, qt.Equals, int64(1)) 48 49 qt.Check(t, itr.Done(), qt.IsFalse) 50 k, v, err = itr.Next() 51 qt.Check(t, err, qt.IsNil) 52 k2, err = k.AsString() 53 qt.Check(t, err, qt.IsNil) 54 qt.Check(t, k2, qt.Equals, "woot") 55 v2, err = v.AsInt() 56 qt.Check(t, err, qt.IsNil) 57 qt.Check(t, v2, qt.Equals, int64(2)) 58 59 qt.Check(t, itr.Done(), qt.IsFalse) 60 k, v, err = itr.Next() 61 qt.Check(t, err, qt.IsNil) 62 k2, err = k.AsString() 63 qt.Check(t, err, qt.IsNil) 64 qt.Check(t, k2, qt.Equals, "waga") 65 v2, err = v.AsInt() 66 qt.Check(t, err, qt.IsNil) 67 qt.Check(t, v2, qt.Equals, int64(3)) 68 69 qt.Check(t, itr.Done(), qt.IsTrue) 70 k, v, err = itr.Next() 71 qt.Check(t, err, qt.Equals, datamodel.ErrIteratorOverread{}) 72 qt.Check(t, k, qt.IsNil) 73 qt.Check(t, v, qt.IsNil) 74 }) 75 t.Run("reads for absent keys error sensibly", func(t *testing.T) { 76 v, err := n.LookupByString("nope") 77 qt.Check(t, err, qt.ErrorAs, &datamodel.ErrNotExists{}) 78 qt.Check(t, err, qt.ErrorMatches, `key not found: "nope"`) 79 qt.Check(t, v, qt.IsNil) 80 }) 81 }) 82 t.Run("repeated key should error", func(t *testing.T) { 83 nb := np.NewBuilder() 84 ma, err := nb.BeginMap(3) 85 if err != nil { 86 panic(err) 87 } 88 if err := ma.AssembleKey().AssignString("whee"); err != nil { 89 panic(err) 90 } 91 if err := ma.AssembleValue().AssignInt(1); err != nil { 92 panic(err) 93 } 94 if err := ma.AssembleKey().AssignString("whee"); err != nil { 95 qt.Check(t, err, qt.ErrorAs, &datamodel.ErrRepeatedMapKey{}) 96 // No string assertion at present -- how that should be presented for typed stuff is unsettled 97 // (and if it's clever, it'll differ from untyped, which will mean no assertion possible!). 98 } 99 }) 100 t.Run("using expired child assemblers should panic", func(t *testing.T) { 101 nb := np.NewBuilder() 102 ma, err := nb.BeginMap(3) 103 must.NotError(err) 104 105 // Assemble a key, and then try to assign it again. Latter should fail. 106 ka := ma.AssembleKey() 107 must.NotError(ka.AssignString("whee")) 108 func() { 109 defer func() { recover() }() 110 ka.AssignString("woo") 111 t.Fatal("must not be reached") 112 }() 113 114 // Assemble a value, and then try to assign it again. Latter should fail. 115 // (This does assume your system can continue after disregarding the last error.) 116 va := ma.AssembleValue() 117 must.NotError(va.AssignInt(1)) 118 func() { 119 defer func() { recover() }() 120 va.AssignInt(2) 121 t.Fatal("must not be reached") 122 }() 123 124 // ... and neither of these should've had visible effects! 125 qt.Check(t, ma.Finish(), qt.IsNil) 126 n := nb.Build() 127 qt.Check(t, n.Length(), qt.Equals, int64(1)) 128 v, err := n.LookupByString("whee") 129 qt.Check(t, err, qt.IsNil) 130 v2, err := v.AsInt() 131 qt.Check(t, err, qt.IsNil) 132 qt.Check(t, v2, qt.Equals, int64(1)) 133 }) 134 t.Run("builder reset works", func(t *testing.T) { 135 // TODO 136 }) 137 } 138 139 func SpecTestMapStrMapStrInt(t *testing.T, np datamodel.NodePrototype) { 140 t.Run("map<str,map<str,int>>", func(t *testing.T) { 141 nb := np.NewBuilder() 142 ma, err := nb.BeginMap(3) 143 must.NotError(err) 144 must.NotError(ma.AssembleKey().AssignString("whee")) 145 func(ma datamodel.MapAssembler, err error) { 146 must.NotError(ma.AssembleKey().AssignString("m1k1")) 147 must.NotError(ma.AssembleValue().AssignInt(1)) 148 must.NotError(ma.AssembleKey().AssignString("m1k2")) 149 must.NotError(ma.AssembleValue().AssignInt(2)) 150 must.NotError(ma.Finish()) 151 }(ma.AssembleValue().BeginMap(2)) 152 must.NotError(ma.AssembleKey().AssignString("woot")) 153 func(ma datamodel.MapAssembler, err error) { 154 must.NotError(ma.AssembleKey().AssignString("m2k1")) 155 must.NotError(ma.AssembleValue().AssignInt(3)) 156 must.NotError(ma.AssembleKey().AssignString("m2k2")) 157 must.NotError(ma.AssembleValue().AssignInt(4)) 158 must.NotError(ma.Finish()) 159 }(ma.AssembleValue().BeginMap(2)) 160 must.NotError(ma.AssembleKey().AssignString("waga")) 161 func(ma datamodel.MapAssembler, err error) { 162 must.NotError(ma.AssembleKey().AssignString("m3k1")) 163 must.NotError(ma.AssembleValue().AssignInt(5)) 164 must.NotError(ma.AssembleKey().AssignString("m3k2")) 165 must.NotError(ma.AssembleValue().AssignInt(6)) 166 must.NotError(ma.Finish()) 167 }(ma.AssembleValue().BeginMap(2)) 168 must.NotError(ma.Finish()) 169 n := nb.Build() 170 171 t.Run("reads back out", func(t *testing.T) { 172 qt.Check(t, n.Length(), qt.Equals, int64(3)) 173 174 v, err := n.LookupByString("woot") 175 qt.Check(t, err, qt.IsNil) 176 v2, err := v.LookupByString("m2k1") 177 qt.Check(t, err, qt.IsNil) 178 v3, err := v2.AsInt() 179 qt.Check(t, err, qt.IsNil) 180 qt.Check(t, v3, qt.Equals, int64(3)) 181 v2, err = v.LookupByString("m2k2") 182 qt.Check(t, err, qt.IsNil) 183 v3, err = v2.AsInt() 184 qt.Check(t, err, qt.IsNil) 185 qt.Check(t, v3, qt.Equals, int64(4)) 186 }) 187 }) 188 } 189 190 func SpecTestMapStrListStr(t *testing.T, np datamodel.NodePrototype) { 191 t.Run("map<str,list<str>>", func(t *testing.T) { 192 nb := np.NewBuilder() 193 ma, err := nb.BeginMap(3) 194 must.NotError(err) 195 must.NotError(ma.AssembleKey().AssignString("asdf")) 196 func(la datamodel.ListAssembler, err error) { 197 must.NotError(la.AssembleValue().AssignString("eleven")) 198 must.NotError(la.AssembleValue().AssignString("twelve")) 199 must.NotError(la.AssembleValue().AssignString("thirteen")) 200 must.NotError(la.Finish()) 201 }(ma.AssembleValue().BeginList(3)) 202 must.NotError(ma.AssembleKey().AssignString("qwer")) 203 func(la datamodel.ListAssembler, err error) { 204 must.NotError(la.AssembleValue().AssignString("twentyone")) 205 must.NotError(la.AssembleValue().AssignString("twentytwo")) 206 must.NotError(la.Finish()) 207 }(ma.AssembleValue().BeginList(2)) 208 must.NotError(ma.AssembleKey().AssignString("zxcv")) 209 func(la datamodel.ListAssembler, err error) { 210 must.NotError(la.AssembleValue().AssignString("thirtyone")) 211 must.NotError(la.Finish()) 212 }(ma.AssembleValue().BeginList(1)) 213 must.NotError(ma.Finish()) 214 n := nb.Build() 215 216 t.Run("reads back out", func(t *testing.T) { 217 qt.Check(t, n.Length(), qt.Equals, int64(3)) 218 219 v, err := n.LookupByString("qwer") 220 qt.Check(t, err, qt.IsNil) 221 v2, err := v.LookupByIndex(1) 222 qt.Check(t, err, qt.IsNil) 223 v3, err := v2.AsString() 224 qt.Check(t, err, qt.IsNil) 225 qt.Check(t, v3, qt.Equals, "twentytwo") 226 }) 227 }) 228 }