github.com/markdicksonjr/dot@v0.8.7/get_test.go (about) 1 package dot 2 3 import ( 4 "math" 5 "testing" 6 ) 7 8 func TestGet_Struct(t *testing.T) { 9 type SampleStructA struct { 10 Text string 11 } 12 13 type SampleStruct struct { 14 A SampleStructA 15 B int 16 C string 17 Slice []int 18 } 19 20 sample := SampleStruct{ 21 A: SampleStructA{ 22 Text: "sf", 23 }, 24 B: 8, 25 C: "something", 26 Slice: []int{5, 6}, 27 } 28 29 // nested get, make "a" lowercase to demonstrate case-insensitivity 30 aText, err := Get(sample, "a.Text") 31 if err != nil { 32 t.Fail() 33 } 34 if aText == nil { 35 t.Fatal("dot-prop get failed") 36 } 37 if aText.(string) != "sf" { 38 t.Fatal("failed to dot-prop get string") 39 } 40 41 // root get of base type 42 bInt, err := Get(sample, "B") 43 if err != nil { 44 t.Fail() 45 } 46 if bInt == nil { 47 t.Fatal("dot-prop get root int failed") 48 } 49 if bInt.(int) != 8 { 50 t.Fatal("failed to dot-prop get root int") 51 } 52 53 // root get of string 54 cText, err := Get(sample, "C") 55 if err != nil { 56 t.Fail() 57 } 58 if cText == nil { 59 t.Fatal("dot-prop get failed") 60 } 61 if cText.(string) != "something" { 62 t.Fatal("failed to dot-prop get root string") 63 } 64 65 // root get of missing prop 66 _, err = Get(sample, "D") 67 if err == nil { 68 t.Fail() 69 } 70 71 // root get of missing sub-prop 72 _, err = Get(sample, "A.x") 73 if err == nil { 74 t.Fail() 75 } 76 77 // get on a nil object 78 rootNil, err := Get(nil, "e") 79 if err != nil { 80 t.Fail() 81 } 82 if rootNil != nil { 83 t.Fatal("got something that should from root have been nil") 84 } 85 86 // test fallback where first property is found, make A upper-case to demonstrate 87 // case insensitivity, along with the assertions above on "a" 88 firstProp, err := Get(sample, "A.Text", "B") 89 if err != nil { 90 t.Fail() 91 } 92 if firstProp == nil { 93 t.Fatal("dot-prop fallback get failed") 94 } 95 if firstProp.(string) != "sf" { 96 t.Fatal("failed to dot-prop get string with fallback") 97 } 98 99 // test fallback where first property is nil 100 secondProp, err := Get(sample, "A.bogus", "B", "C") 101 if err != nil { 102 t.Fail() 103 } 104 if secondProp == nil { 105 t.Fatal("dot-prop fallback get failed") 106 } 107 if secondProp.(int) != 8 { 108 t.Fatal("failed to dot-prop get string with fallback") 109 } 110 111 // test fallback where no property is available 112 _, err = Get(sample, "A.bogus", "bogus", "foo") 113 if err == nil { 114 t.Fail() 115 } 116 117 // test getting a slice from the object 118 _, err = Get(sample, "Slice") 119 if err != nil { 120 t.Fail() 121 } 122 } 123 124 func TestGet_EscapedDotInMap(t *testing.T) { 125 tMap := map[string]interface{} { 126 "t.b": "r", 127 } 128 res, err := Get(tMap, "t\\.b") 129 if err != nil { 130 t.Fatal(err) 131 } 132 if res == nil { 133 t.Fatal("unexpected nil result") 134 } 135 } 136 137 func BenchmarkGet_Map(b *testing.B) { 138 data := map[string]interface{}{ 139 "A": map[string]interface{}{ 140 "Z": 1, 141 "AA": 0, 142 }, 143 } 144 145 aGet, _ := Get(data, "A") 146 if aGet == nil { 147 b.Fatal("got nil 'A'") 148 } 149 150 azGet, _ := Get(data, "A.Z") 151 if azGetInt, _ := CoerceInt64(azGet); azGetInt != 1 { 152 b.Fatal("A.Z was not 1") 153 } 154 } 155 156 func TestGetInt64(t *testing.T) { 157 data := make(map[string]interface{}) 158 a := make(map[string]interface{}) 159 a["b"] = 5 160 a["c"] = 6.5 161 a["d"] = int32(7) 162 a["e"] = "should be 0" 163 a["f"] = int64(9) 164 a["g"] = false 165 data["a"] = a 166 167 // test coercion of int 168 if GetInt64(data, "a.b") != 5 { 169 t.Error("a.b was not 5") 170 } 171 172 // test simple get of float flooring 173 if GetInt64(data, "a.c") != 6 { 174 t.Error("a.c was not 6") 175 } 176 177 // test coercion of float32 178 if GetInt64(data, "a.d") != 7 { // will be some rounding error in float32 179 t.Error("a.d was not 7") 180 } 181 182 // test that incompatible coercion results in 0 183 if GetInt64(data, "a.e") != 0 { 184 t.Error("a.e was not 0") 185 } 186 187 // test that coercion on nil results in 0 188 if GetInt64(nil, "a.e") != 0 { 189 t.Error("GetInt64 on nil was not 0") 190 } 191 192 // test simple get of target type 193 if GetInt64(data, "a.g") != 0 { 194 t.Error("a.c was not 0") 195 } 196 197 // test that coercion on explicit int64 198 if GetInt64(data, "a.f") != 9 { 199 t.Error("GetInt64 on explicitly int64 not correct") 200 } 201 202 // test fallback 203 if GetInt64(data, "x", "a.b") != 5 { 204 t.Error("fallback did not fall back to the correct value") 205 } 206 } 207 208 func TestGetFloat64(t *testing.T) { 209 data := make(map[string]interface{}) 210 a := make(map[string]interface{}) 211 a["b"] = 5 212 a["c"] = 6.5 213 a["d"] = float32(7.8) 214 a["e"] = "should be 0" 215 a["f"] = "32.5" 216 a["g"] = []byte("61.8") 217 data["a"] = a 218 219 // test coercion of int 220 if GetFloat64(data, "a.b") != 5 { 221 t.Error("a.b was not 5") 222 } 223 224 // test simple get of target type 225 if GetFloat64(data, "a.c") != 6.5 { 226 t.Error("a.c was not 6.5") 227 } 228 229 // test coercion of float32 230 if math.Floor(GetFloat64(data, "a.d")*10)/10 != 7.8 { // will be some rounding error in float32 231 t.Error("a.d was not 7.8") 232 } 233 234 // test that incompatible coercion results in 0 235 if GetFloat64(data, "a.e") != 0 { // will be some rounding error in float32 236 t.Error("a.e was not 0") 237 } 238 239 // test that coercion on string rep of float yields the float val 240 if GetFloat64(data, "a.f") != 32.5 { 241 t.Error("GetFloat64 on '32.5' was not 32.5") 242 } 243 244 // test that coercion on byte slice rep of float yields the float val 245 if GetFloat64(data, "a.g") != 61.8 { 246 t.Error("GetFloat64 on byte rep of '61.8' was not 61.8") 247 } 248 249 // test that coercion on nil results in 0 250 if GetFloat64(nil, "a.e") != 0 { 251 t.Error("GetFloat64 on nil was not 0") 252 } 253 254 // test fallback 255 if GetFloat64(data, "x", "a.c") != 6.5 { 256 t.Error("fallback did not fall back to the correct value") 257 } 258 } 259 260 func TestGetString(t *testing.T) { 261 data := make(map[string]interface{}) 262 data["biz"] = "tammy" 263 res := GetString(data, "biz") 264 if res != "tammy" { 265 t.Error("result did not equal tammy") 266 } 267 268 res = GetString(nil, "p") 269 if res != "" { 270 t.Error("GetString on nil was not the empty string") 271 } 272 273 data["obj"] = make(map[string]interface{}) 274 res = GetString(data, "obj") 275 if res != "" { 276 t.Error("result was non-empty when it should not be") 277 } 278 } 279 280 func TestGetStringFromFloatCoercion(t *testing.T) { 281 data := make(map[string]interface{}) 282 data["rough"] = 89.12 283 res := GetString(data, "rough") 284 if res != "89.12" { 285 t.Error("result did not equal 89.12 as a string") 286 } 287 } 288 289 func TestGetStringFromIntCoercion(t *testing.T) { 290 data := make(map[string]interface{}) 291 data["rough"] = 801 292 res := GetString(data, "rough") 293 if res != "801" { 294 t.Error("result did not equal 801 as a string") 295 } 296 } 297 298 func TestGetStringFallback(t *testing.T) { 299 data := make(map[string]interface{}) 300 data["b"] = "todd" 301 res := GetString(data, "a", "b") 302 if res != "todd" { 303 t.Error("result did not equal todd - it should have fallen back") 304 } 305 } 306 307 func TestGetStringFallbackMiss(t *testing.T) { 308 data := make(map[string]interface{}) 309 data["b"] = "todd" 310 res := GetString(data, "a", "c") 311 if res != "" { 312 t.Error("result did not equal '' when no match was found during fallback") 313 } 314 } 315 316 func TestCoerceStringFromPtr(t *testing.T) { 317 str := "test" 318 if v, ok := CoerceString(&str); ok == false || v != "test" { 319 t.Error("result did not equal 'test' when coercing string pointer") 320 } 321 } 322 323 func TestCoerceStringFromBool(t *testing.T) { 324 if v, ok := CoerceString(true); ok == false || v != "true" { 325 t.Error("result did not equal 'true' when coercing string") 326 } 327 328 if v, ok := CoerceString(false); ok == false || v != "false" { 329 t.Error("result did not equal 'false' when coercing string") 330 } 331 }