1package toml 2 3import ( 4 "strconv" 5 "testing" 6 "time" 7) 8 9type customString string 10 11type stringer struct{} 12 13func (s stringer) String() string { 14 return "stringer" 15} 16 17func validate(t *testing.T, path string, object interface{}) { 18 switch o := object.(type) { 19 case *Tree: 20 for key, tree := range o.values { 21 validate(t, path+"."+key, tree) 22 } 23 case []*Tree: 24 for index, tree := range o { 25 validate(t, path+"."+strconv.Itoa(index), tree) 26 } 27 case *tomlValue: 28 switch o.value.(type) { 29 case int64, uint64, bool, string, float64, time.Time, 30 []int64, []uint64, []bool, []string, []float64, []time.Time: 31 default: 32 t.Fatalf("tomlValue at key %s containing incorrect type %T", path, o.value) 33 } 34 default: 35 t.Fatalf("value at key %s is of incorrect type %T", path, object) 36 } 37 t.Logf("validation ok %s as %T", path, object) 38} 39 40func validateTree(t *testing.T, tree *Tree) { 41 validate(t, "", tree) 42} 43 44func TestTreeCreateToTree(t *testing.T) { 45 data := map[string]interface{}{ 46 "a_string": "bar", 47 "an_int": 42, 48 "time": time.Now(), 49 "int8": int8(2), 50 "int16": int16(2), 51 "int32": int32(2), 52 "uint8": uint8(2), 53 "uint16": uint16(2), 54 "uint32": uint32(2), 55 "float32": float32(2), 56 "a_bool": false, 57 "stringer": stringer{}, 58 "nested": map[string]interface{}{ 59 "foo": "bar", 60 }, 61 "array": []string{"a", "b", "c"}, 62 "array_uint": []uint{uint(1), uint(2)}, 63 "array_table": []map[string]interface{}{map[string]interface{}{"sub_map": 52}}, 64 "array_times": []time.Time{time.Now(), time.Now()}, 65 "map_times": map[string]time.Time{"now": time.Now()}, 66 "custom_string_map_key": map[customString]interface{}{customString("custom"): "custom"}, 67 } 68 tree, err := TreeFromMap(data) 69 if err != nil { 70 t.Fatal("unexpected error:", err) 71 } 72 validateTree(t, tree) 73} 74 75func TestTreeCreateToTreeInvalidLeafType(t *testing.T) { 76 _, err := TreeFromMap(map[string]interface{}{"foo": t}) 77 expected := "cannot convert type *testing.T to Tree" 78 if err.Error() != expected { 79 t.Fatalf("expected error %s, got %s", expected, err.Error()) 80 } 81} 82 83func TestTreeCreateToTreeInvalidMapKeyType(t *testing.T) { 84 _, err := TreeFromMap(map[string]interface{}{"foo": map[int]interface{}{2: 1}}) 85 expected := "map key needs to be a string, not int (int)" 86 if err.Error() != expected { 87 t.Fatalf("expected error %s, got %s", expected, err.Error()) 88 } 89} 90 91func TestTreeCreateToTreeInvalidArrayMemberType(t *testing.T) { 92 _, err := TreeFromMap(map[string]interface{}{"foo": []*testing.T{t}}) 93 expected := "cannot convert type *testing.T to Tree" 94 if err.Error() != expected { 95 t.Fatalf("expected error %s, got %s", expected, err.Error()) 96 } 97} 98 99func TestTreeCreateToTreeInvalidTableGroupType(t *testing.T) { 100 _, err := TreeFromMap(map[string]interface{}{"foo": []map[string]interface{}{map[string]interface{}{"hello": t}}}) 101 expected := "cannot convert type *testing.T to Tree" 102 if err.Error() != expected { 103 t.Fatalf("expected error %s, got %s", expected, err.Error()) 104 } 105} 106 107func TestRoundTripArrayOfTables(t *testing.T) { 108 orig := "\n[[stuff]]\n name = \"foo\"\n things = [\"a\",\"b\"]\n" 109 tree, err := Load(orig) 110 if err != nil { 111 t.Fatalf("unexpected error: %s", err) 112 } 113 114 m := tree.ToMap() 115 116 tree, err = TreeFromMap(m) 117 if err != nil { 118 t.Fatalf("unexpected error: %s", err) 119 } 120 want := orig 121 got := tree.String() 122 123 if got != want { 124 t.Errorf("want:\n%s\ngot:\n%s", want, got) 125 } 126} 127