1package toml 2 3import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io/ioutil" 8 "reflect" 9 "strings" 10 "testing" 11 "time" 12) 13 14type basicMarshalTestStruct struct { 15 String string `toml:"string"` 16 StringList []string `toml:"strlist"` 17 Sub basicMarshalTestSubStruct `toml:"subdoc"` 18 SubList []basicMarshalTestSubStruct `toml:"sublist"` 19} 20 21type basicMarshalTestSubStruct struct { 22 String2 string 23} 24 25var basicTestData = basicMarshalTestStruct{ 26 String: "Hello", 27 StringList: []string{"Howdy", "Hey There"}, 28 Sub: basicMarshalTestSubStruct{"One"}, 29 SubList: []basicMarshalTestSubStruct{{"Two"}, {"Three"}}, 30} 31 32var basicTestToml = []byte(`string = "Hello" 33strlist = ["Howdy","Hey There"] 34 35[subdoc] 36 String2 = "One" 37 38[[sublist]] 39 String2 = "Two" 40 41[[sublist]] 42 String2 = "Three" 43`) 44 45func TestBasicMarshal(t *testing.T) { 46 result, err := Marshal(basicTestData) 47 if err != nil { 48 t.Fatal(err) 49 } 50 expected := basicTestToml 51 if !bytes.Equal(result, expected) { 52 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) 53 } 54} 55 56func TestBasicUnmarshal(t *testing.T) { 57 result := basicMarshalTestStruct{} 58 err := Unmarshal(basicTestToml, &result) 59 expected := basicTestData 60 if err != nil { 61 t.Fatal(err) 62 } 63 if !reflect.DeepEqual(result, expected) { 64 t.Errorf("Bad unmarshal: expected %v, got %v", expected, result) 65 } 66} 67 68type testDoc struct { 69 Title string `toml:"title"` 70 Basics testDocBasics `toml:"basic"` 71 BasicLists testDocBasicLists `toml:"basic_lists"` 72 BasicMap map[string]string `toml:"basic_map"` 73 Subdocs testDocSubs `toml:"subdoc"` 74 SubDocList []testSubDoc `toml:"subdoclist"` 75 SubDocPtrs []*testSubDoc `toml:"subdocptrs"` 76 err int `toml:"shouldntBeHere"` 77 unexported int `toml:"shouldntBeHere"` 78 Unexported2 int `toml:"-"` 79} 80 81type testDocBasics struct { 82 Bool bool `toml:"bool"` 83 Date time.Time `toml:"date"` 84 Float float32 `toml:"float"` 85 Int int `toml:"int"` 86 Uint uint `toml:"uint"` 87 String *string `toml:"string"` 88 unexported int `toml:"shouldntBeHere"` 89} 90 91type testDocBasicLists struct { 92 Bools []bool `toml:"bools"` 93 Dates []time.Time `toml:"dates"` 94 Floats []*float32 `toml:"floats"` 95 Ints []int `toml:"ints"` 96 Strings []string `toml:"strings"` 97 UInts []uint `toml:"uints"` 98} 99 100type testDocSubs struct { 101 First testSubDoc `toml:"first"` 102 Second *testSubDoc `toml:"second"` 103} 104 105type testSubDoc struct { 106 Name string `toml:"name"` 107 unexported int `toml:"shouldntBeHere"` 108} 109 110var biteMe = "Bite me" 111var float1 float32 = 12.3 112var float2 float32 = 45.6 113var float3 float32 = 78.9 114var subdoc = testSubDoc{"Second", 0} 115 116var docData = testDoc{ 117 Title: "TOML Marshal Testing", 118 unexported: 0, 119 Unexported2: 0, 120 Basics: testDocBasics{ 121 Bool: true, 122 Date: time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC), 123 Float: 123.4, 124 Int: 5000, 125 Uint: 5001, 126 String: &biteMe, 127 unexported: 0, 128 }, 129 BasicLists: testDocBasicLists{ 130 Bools: []bool{true, false, true}, 131 Dates: []time.Time{ 132 time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC), 133 time.Date(1980, 5, 27, 7, 32, 0, 0, time.UTC), 134 }, 135 Floats: []*float32{&float1, &float2, &float3}, 136 Ints: []int{8001, 8001, 8002}, 137 Strings: []string{"One", "Two", "Three"}, 138 UInts: []uint{5002, 5003}, 139 }, 140 BasicMap: map[string]string{ 141 "one": "one", 142 "two": "two", 143 }, 144 Subdocs: testDocSubs{ 145 First: testSubDoc{"First", 0}, 146 Second: &subdoc, 147 }, 148 SubDocList: []testSubDoc{ 149 {"List.First", 0}, 150 {"List.Second", 0}, 151 }, 152 SubDocPtrs: []*testSubDoc{&subdoc}, 153} 154 155func TestDocMarshal(t *testing.T) { 156 result, err := Marshal(docData) 157 if err != nil { 158 t.Fatal(err) 159 } 160 expected, _ := ioutil.ReadFile("marshal_test.toml") 161 if !bytes.Equal(result, expected) { 162 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) 163 } 164} 165 166func TestDocUnmarshal(t *testing.T) { 167 result := testDoc{} 168 tomlData, _ := ioutil.ReadFile("marshal_test.toml") 169 err := Unmarshal(tomlData, &result) 170 expected := docData 171 if err != nil { 172 t.Fatal(err) 173 } 174 if !reflect.DeepEqual(result, expected) { 175 resStr, _ := json.MarshalIndent(result, "", " ") 176 expStr, _ := json.MarshalIndent(expected, "", " ") 177 t.Errorf("Bad unmarshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr) 178 } 179} 180 181func TestDocPartialUnmarshal(t *testing.T) { 182 result := testDocSubs{} 183 184 tree, _ := LoadFile("marshal_test.toml") 185 subTree := tree.Get("subdoc").(*Tree) 186 err := subTree.Unmarshal(&result) 187 expected := docData.Subdocs 188 if err != nil { 189 t.Fatal(err) 190 } 191 if !reflect.DeepEqual(result, expected) { 192 resStr, _ := json.MarshalIndent(result, "", " ") 193 expStr, _ := json.MarshalIndent(expected, "", " ") 194 t.Errorf("Bad partial unmartial: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr) 195 } 196} 197 198type tomlTypeCheckTest struct { 199 name string 200 item interface{} 201 typ int //0=primitive, 1=otherslice, 2=treeslice, 3=tree 202} 203 204func TestTypeChecks(t *testing.T) { 205 tests := []tomlTypeCheckTest{ 206 {"integer", 2, 0}, 207 {"time", time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC), 0}, 208 {"stringlist", []string{"hello", "hi"}, 1}, 209 {"timelist", []time.Time{time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, 1}, 210 {"objectlist", []tomlTypeCheckTest{}, 2}, 211 {"object", tomlTypeCheckTest{}, 3}, 212 } 213 214 for _, test := range tests { 215 expected := []bool{false, false, false, false} 216 expected[test.typ] = true 217 result := []bool{ 218 isPrimitive(reflect.TypeOf(test.item)), 219 isOtherSlice(reflect.TypeOf(test.item)), 220 isTreeSlice(reflect.TypeOf(test.item)), 221 isTree(reflect.TypeOf(test.item)), 222 } 223 if !reflect.DeepEqual(expected, result) { 224 t.Errorf("Bad type check on %q: expected %v, got %v", test.name, expected, result) 225 } 226 } 227} 228 229type unexportedMarshalTestStruct struct { 230 String string `toml:"string"` 231 StringList []string `toml:"strlist"` 232 Sub basicMarshalTestSubStruct `toml:"subdoc"` 233 SubList []basicMarshalTestSubStruct `toml:"sublist"` 234 unexported int `toml:"shouldntBeHere"` 235 Unexported2 int `toml:"-"` 236} 237 238var unexportedTestData = unexportedMarshalTestStruct{ 239 String: "Hello", 240 StringList: []string{"Howdy", "Hey There"}, 241 Sub: basicMarshalTestSubStruct{"One"}, 242 SubList: []basicMarshalTestSubStruct{{"Two"}, {"Three"}}, 243 unexported: 0, 244 Unexported2: 0, 245} 246 247var unexportedTestToml = []byte(`string = "Hello" 248strlist = ["Howdy","Hey There"] 249unexported = 1 250shouldntBeHere = 2 251 252[subdoc] 253 String2 = "One" 254 255[[sublist]] 256 String2 = "Two" 257 258[[sublist]] 259 String2 = "Three" 260`) 261 262func TestUnexportedUnmarshal(t *testing.T) { 263 result := unexportedMarshalTestStruct{} 264 err := Unmarshal(unexportedTestToml, &result) 265 expected := unexportedTestData 266 if err != nil { 267 t.Fatal(err) 268 } 269 if !reflect.DeepEqual(result, expected) { 270 t.Errorf("Bad unexported unmarshal: expected %v, got %v", expected, result) 271 } 272} 273 274type errStruct struct { 275 Bool bool `toml:"bool"` 276 Date time.Time `toml:"date"` 277 Float float64 `toml:"float"` 278 Int int16 `toml:"int"` 279 String *string `toml:"string"` 280} 281 282var errTomls = []string{ 283 "bool = truly\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"", 284 "bool = true\ndate = 1979-05-27T07:3200Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"", 285 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123a4\nint = 5000\nstring = \"Bite me\"", 286 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = j000\nstring = \"Bite me\"", 287 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = Bite me", 288 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = Bite me", 289 "bool = 1\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"", 290 "bool = true\ndate = 1\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"", 291 "bool = true\ndate = 1979-05-27T07:32:00Z\n\"sorry\"\nint = 5000\nstring = \"Bite me\"", 292 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = \"sorry\"\nstring = \"Bite me\"", 293 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = 1", 294} 295 296type mapErr struct { 297 Vals map[string]float64 298} 299 300type intErr struct { 301 Int1 int 302 Int2 int8 303 Int3 int16 304 Int4 int32 305 Int5 int64 306 UInt1 uint 307 UInt2 uint8 308 UInt3 uint16 309 UInt4 uint32 310 UInt5 uint64 311 Flt1 float32 312 Flt2 float64 313} 314 315var intErrTomls = []string{ 316 "Int1 = []\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", 317 "Int1 = 1\nInt2 = []\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", 318 "Int1 = 1\nInt2 = 2\nInt3 = []\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", 319 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = []\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", 320 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = []\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", 321 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = []\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", 322 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = []\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", 323 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = []\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", 324 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = []\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", 325 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = []\nFlt1 = 1.0\nFlt2 = 2.0", 326 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = []\nFlt2 = 2.0", 327 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = []", 328} 329 330func TestErrUnmarshal(t *testing.T) { 331 for ind, toml := range errTomls { 332 result := errStruct{} 333 err := Unmarshal([]byte(toml), &result) 334 if err == nil { 335 t.Errorf("Expected err from case %d\n", ind) 336 } 337 } 338 result2 := mapErr{} 339 err := Unmarshal([]byte("[Vals]\nfred=\"1.2\""), &result2) 340 if err == nil { 341 t.Errorf("Expected err from map") 342 } 343 for ind, toml := range intErrTomls { 344 result3 := intErr{} 345 err := Unmarshal([]byte(toml), &result3) 346 if err == nil { 347 t.Errorf("Expected int err from case %d\n", ind) 348 } 349 } 350} 351 352type emptyMarshalTestStruct struct { 353 Title string `toml:"title"` 354 Bool bool `toml:"bool"` 355 Int int `toml:"int"` 356 String string `toml:"string"` 357 StringList []string `toml:"stringlist"` 358 Ptr *basicMarshalTestStruct `toml:"ptr"` 359 Map map[string]string `toml:"map"` 360} 361 362var emptyTestData = emptyMarshalTestStruct{ 363 Title: "Placeholder", 364 Bool: false, 365 Int: 0, 366 String: "", 367 StringList: []string{}, 368 Ptr: nil, 369 Map: map[string]string{}, 370} 371 372var emptyTestToml = []byte(`bool = false 373int = 0 374string = "" 375stringlist = [] 376title = "Placeholder" 377 378[map] 379`) 380 381type emptyMarshalTestStruct2 struct { 382 Title string `toml:"title"` 383 Bool bool `toml:"bool,omitempty"` 384 Int int `toml:"int, omitempty"` 385 String string `toml:"string,omitempty "` 386 StringList []string `toml:"stringlist,omitempty"` 387 Ptr *basicMarshalTestStruct `toml:"ptr,omitempty"` 388 Map map[string]string `toml:"map,omitempty"` 389} 390 391var emptyTestData2 = emptyMarshalTestStruct2{ 392 Title: "Placeholder", 393 Bool: false, 394 Int: 0, 395 String: "", 396 StringList: []string{}, 397 Ptr: nil, 398 Map: map[string]string{}, 399} 400 401var emptyTestToml2 = []byte(`title = "Placeholder" 402`) 403 404func TestEmptyMarshal(t *testing.T) { 405 result, err := Marshal(emptyTestData) 406 if err != nil { 407 t.Fatal(err) 408 } 409 expected := emptyTestToml 410 if !bytes.Equal(result, expected) { 411 t.Errorf("Bad empty marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) 412 } 413} 414 415func TestEmptyMarshalOmit(t *testing.T) { 416 result, err := Marshal(emptyTestData2) 417 if err != nil { 418 t.Fatal(err) 419 } 420 expected := emptyTestToml2 421 if !bytes.Equal(result, expected) { 422 t.Errorf("Bad empty omit marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) 423 } 424} 425 426func TestEmptyUnmarshal(t *testing.T) { 427 result := emptyMarshalTestStruct{} 428 err := Unmarshal(emptyTestToml, &result) 429 expected := emptyTestData 430 if err != nil { 431 t.Fatal(err) 432 } 433 if !reflect.DeepEqual(result, expected) { 434 t.Errorf("Bad empty unmarshal: expected %v, got %v", expected, result) 435 } 436} 437 438func TestEmptyUnmarshalOmit(t *testing.T) { 439 result := emptyMarshalTestStruct2{} 440 err := Unmarshal(emptyTestToml, &result) 441 expected := emptyTestData2 442 if err != nil { 443 t.Fatal(err) 444 } 445 if !reflect.DeepEqual(result, expected) { 446 t.Errorf("Bad empty omit unmarshal: expected %v, got %v", expected, result) 447 } 448} 449 450type pointerMarshalTestStruct struct { 451 Str *string 452 List *[]string 453 ListPtr *[]*string 454 Map *map[string]string 455 MapPtr *map[string]*string 456 EmptyStr *string 457 EmptyList *[]string 458 EmptyMap *map[string]string 459 DblPtr *[]*[]*string 460} 461 462var pointerStr = "Hello" 463var pointerList = []string{"Hello back"} 464var pointerListPtr = []*string{&pointerStr} 465var pointerMap = map[string]string{"response": "Goodbye"} 466var pointerMapPtr = map[string]*string{"alternate": &pointerStr} 467var pointerTestData = pointerMarshalTestStruct{ 468 Str: &pointerStr, 469 List: &pointerList, 470 ListPtr: &pointerListPtr, 471 Map: &pointerMap, 472 MapPtr: &pointerMapPtr, 473 EmptyStr: nil, 474 EmptyList: nil, 475 EmptyMap: nil, 476} 477 478var pointerTestToml = []byte(`List = ["Hello back"] 479ListPtr = ["Hello"] 480Str = "Hello" 481 482[Map] 483 response = "Goodbye" 484 485[MapPtr] 486 alternate = "Hello" 487`) 488 489func TestPointerMarshal(t *testing.T) { 490 result, err := Marshal(pointerTestData) 491 if err != nil { 492 t.Fatal(err) 493 } 494 expected := pointerTestToml 495 if !bytes.Equal(result, expected) { 496 t.Errorf("Bad pointer marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) 497 } 498} 499 500func TestPointerUnmarshal(t *testing.T) { 501 result := pointerMarshalTestStruct{} 502 err := Unmarshal(pointerTestToml, &result) 503 expected := pointerTestData 504 if err != nil { 505 t.Fatal(err) 506 } 507 if !reflect.DeepEqual(result, expected) { 508 t.Errorf("Bad pointer unmarshal: expected %v, got %v", expected, result) 509 } 510} 511 512func TestUnmarshalTypeMismatch(t *testing.T) { 513 result := pointerMarshalTestStruct{} 514 err := Unmarshal([]byte("List = 123"), &result) 515 if !strings.HasPrefix(err.Error(), "(1, 1): Can't convert 123(int64) to []string(slice)") { 516 t.Errorf("Type mismatch must be reported: got %v", err.Error()) 517 } 518} 519 520type nestedMarshalTestStruct struct { 521 String [][]string 522 //Struct [][]basicMarshalTestSubStruct 523 StringPtr *[]*[]*string 524 // StructPtr *[]*[]*basicMarshalTestSubStruct 525} 526 527var str1 = "Three" 528var str2 = "Four" 529var strPtr = []*string{&str1, &str2} 530var strPtr2 = []*[]*string{&strPtr} 531 532var nestedTestData = nestedMarshalTestStruct{ 533 String: [][]string{{"Five", "Six"}, {"One", "Two"}}, 534 StringPtr: &strPtr2, 535} 536 537var nestedTestToml = []byte(`String = [["Five","Six"],["One","Two"]] 538StringPtr = [["Three","Four"]] 539`) 540 541func TestNestedMarshal(t *testing.T) { 542 result, err := Marshal(nestedTestData) 543 if err != nil { 544 t.Fatal(err) 545 } 546 expected := nestedTestToml 547 if !bytes.Equal(result, expected) { 548 t.Errorf("Bad nested marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) 549 } 550} 551 552func TestNestedUnmarshal(t *testing.T) { 553 result := nestedMarshalTestStruct{} 554 err := Unmarshal(nestedTestToml, &result) 555 expected := nestedTestData 556 if err != nil { 557 t.Fatal(err) 558 } 559 if !reflect.DeepEqual(result, expected) { 560 t.Errorf("Bad nested unmarshal: expected %v, got %v", expected, result) 561 } 562} 563 564type customMarshalerParent struct { 565 Self customMarshaler `toml:"me"` 566 Friends []customMarshaler `toml:"friends"` 567} 568 569type customMarshaler struct { 570 FirsName string 571 LastName string 572} 573 574func (c customMarshaler) MarshalTOML() ([]byte, error) { 575 fullName := fmt.Sprintf("%s %s", c.FirsName, c.LastName) 576 return []byte(fullName), nil 577} 578 579var customMarshalerData = customMarshaler{FirsName: "Sally", LastName: "Fields"} 580var customMarshalerToml = []byte(`Sally Fields`) 581var nestedCustomMarshalerData = customMarshalerParent{ 582 Self: customMarshaler{FirsName: "Maiku", LastName: "Suteda"}, 583 Friends: []customMarshaler{customMarshalerData}, 584} 585var nestedCustomMarshalerToml = []byte(`friends = ["Sally Fields"] 586me = "Maiku Suteda" 587`) 588 589func TestCustomMarshaler(t *testing.T) { 590 result, err := Marshal(customMarshalerData) 591 if err != nil { 592 t.Fatal(err) 593 } 594 expected := customMarshalerToml 595 if !bytes.Equal(result, expected) { 596 t.Errorf("Bad custom marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) 597 } 598} 599 600func TestNestedCustomMarshaler(t *testing.T) { 601 result, err := Marshal(nestedCustomMarshalerData) 602 if err != nil { 603 t.Fatal(err) 604 } 605 expected := nestedCustomMarshalerToml 606 if !bytes.Equal(result, expected) { 607 t.Errorf("Bad nested custom marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) 608 } 609} 610 611var commentTestToml = []byte(` 612# it's a comment on type 613[postgres] 614 # isCommented = "dvalue" 615 noComment = "cvalue" 616 617 # A comment on AttrB with a 618 # break line 619 password = "bvalue" 620 621 # A comment on AttrA 622 user = "avalue" 623 624 [[postgres.My]] 625 626 # a comment on my on typeC 627 My = "Foo" 628 629 [[postgres.My]] 630 631 # a comment on my on typeC 632 My = "Baar" 633`) 634 635func TestMarshalComment(t *testing.T) { 636 type TypeC struct { 637 My string `comment:"a comment on my on typeC"` 638 } 639 type TypeB struct { 640 AttrA string `toml:"user" comment:"A comment on AttrA"` 641 AttrB string `toml:"password" comment:"A comment on AttrB with a\n break line"` 642 AttrC string `toml:"noComment"` 643 AttrD string `toml:"isCommented" commented:"true"` 644 My []TypeC 645 } 646 type TypeA struct { 647 TypeB TypeB `toml:"postgres" comment:"it's a comment on type"` 648 } 649 650 ta := []TypeC{{My: "Foo"}, {My: "Baar"}} 651 config := TypeA{TypeB{AttrA: "avalue", AttrB: "bvalue", AttrC: "cvalue", AttrD: "dvalue", My: ta}} 652 result, err := Marshal(config) 653 if err != nil { 654 t.Fatal(err) 655 } 656 expected := commentTestToml 657 if !bytes.Equal(result, expected) { 658 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) 659 } 660} 661 662type mapsTestStruct struct { 663 Simple map[string]string 664 Paths map[string]string 665 Other map[string]float64 666 X struct { 667 Y struct { 668 Z map[string]bool 669 } 670 } 671} 672 673var mapsTestData = mapsTestStruct{ 674 Simple: map[string]string{ 675 "one plus one": "two", 676 "next": "three", 677 }, 678 Paths: map[string]string{ 679 "/this/is/a/path": "/this/is/also/a/path", 680 "/heloo.txt": "/tmp/lololo.txt", 681 }, 682 Other: map[string]float64{ 683 "testing": 3.9999, 684 }, 685 X: struct{ Y struct{ Z map[string]bool } }{ 686 Y: struct{ Z map[string]bool }{ 687 Z: map[string]bool{ 688 "is.Nested": true, 689 }, 690 }, 691 }, 692} 693var mapsTestToml = []byte(` 694[Other] 695 "testing" = 3.9999 696 697[Paths] 698 "/heloo.txt" = "/tmp/lololo.txt" 699 "/this/is/a/path" = "/this/is/also/a/path" 700 701[Simple] 702 "next" = "three" 703 "one plus one" = "two" 704 705[X] 706 707 [X.Y] 708 709 [X.Y.Z] 710 "is.Nested" = true 711`) 712 713func TestEncodeQuotedMapKeys(t *testing.T) { 714 var buf bytes.Buffer 715 if err := NewEncoder(&buf).QuoteMapKeys(true).Encode(mapsTestData); err != nil { 716 t.Fatal(err) 717 } 718 result := buf.Bytes() 719 expected := mapsTestToml 720 if !bytes.Equal(result, expected) { 721 t.Errorf("Bad maps marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) 722 } 723} 724 725func TestDecodeQuotedMapKeys(t *testing.T) { 726 result := mapsTestStruct{} 727 err := NewDecoder(bytes.NewBuffer(mapsTestToml)).Decode(&result) 728 expected := mapsTestData 729 if err != nil { 730 t.Fatal(err) 731 } 732 if !reflect.DeepEqual(result, expected) { 733 t.Errorf("Bad maps unmarshal: expected %v, got %v", expected, result) 734 } 735} 736 737type structArrayNoTag struct { 738 A struct { 739 B []int64 740 C []int64 741 } 742} 743 744func TestMarshalArray(t *testing.T) { 745 expected := []byte(` 746[A] 747 B = [1,2,3] 748 C = [1] 749`) 750 751 m := structArrayNoTag{ 752 A: struct { 753 B []int64 754 C []int64 755 }{ 756 B: []int64{1, 2, 3}, 757 C: []int64{1}, 758 }, 759 } 760 761 b, err := Marshal(m) 762 763 if err != nil { 764 t.Fatal(err) 765 } 766 767 if !bytes.Equal(b, expected) { 768 t.Errorf("Bad arrays marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b) 769 } 770} 771 772func TestMarshalArrayOnePerLine(t *testing.T) { 773 expected := []byte(` 774[A] 775 B = [ 776 1, 777 2, 778 3, 779 ] 780 C = [1] 781`) 782 783 m := structArrayNoTag{ 784 A: struct { 785 B []int64 786 C []int64 787 }{ 788 B: []int64{1, 2, 3}, 789 C: []int64{1}, 790 }, 791 } 792 793 var buf bytes.Buffer 794 encoder := NewEncoder(&buf).ArraysWithOneElementPerLine(true) 795 err := encoder.Encode(m) 796 797 if err != nil { 798 t.Fatal(err) 799 } 800 801 b := buf.Bytes() 802 803 if !bytes.Equal(b, expected) { 804 t.Errorf("Bad arrays marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b) 805 } 806} 807