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  }