decode_test.go 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447
  1. package toml
  2. import (
  3. "fmt"
  4. "log"
  5. "math"
  6. "reflect"
  7. "strings"
  8. "testing"
  9. "time"
  10. )
  11. func TestDecodeSimple(t *testing.T) {
  12. var testSimple = `
  13. age = 250
  14. andrew = "gallant"
  15. kait = "brady"
  16. now = 1987-07-05T05:45:00Z
  17. yesOrNo = true
  18. pi = 3.14
  19. colors = [
  20. ["red", "green", "blue"],
  21. ["cyan", "magenta", "yellow", "black"],
  22. ]
  23. [My.Cats]
  24. plato = "cat 1"
  25. cauchy = "cat 2"
  26. `
  27. type cats struct {
  28. Plato string
  29. Cauchy string
  30. }
  31. type simple struct {
  32. Age int
  33. Colors [][]string
  34. Pi float64
  35. YesOrNo bool
  36. Now time.Time
  37. Andrew string
  38. Kait string
  39. My map[string]cats
  40. }
  41. var val simple
  42. _, err := Decode(testSimple, &val)
  43. if err != nil {
  44. t.Fatal(err)
  45. }
  46. now, err := time.Parse("2006-01-02T15:04:05", "1987-07-05T05:45:00")
  47. if err != nil {
  48. panic(err)
  49. }
  50. var answer = simple{
  51. Age: 250,
  52. Andrew: "gallant",
  53. Kait: "brady",
  54. Now: now,
  55. YesOrNo: true,
  56. Pi: 3.14,
  57. Colors: [][]string{
  58. {"red", "green", "blue"},
  59. {"cyan", "magenta", "yellow", "black"},
  60. },
  61. My: map[string]cats{
  62. "Cats": {Plato: "cat 1", Cauchy: "cat 2"},
  63. },
  64. }
  65. if !reflect.DeepEqual(val, answer) {
  66. t.Fatalf("Expected\n-----\n%#v\n-----\nbut got\n-----\n%#v\n",
  67. answer, val)
  68. }
  69. }
  70. func TestDecodeEmbedded(t *testing.T) {
  71. type Dog struct{ Name string }
  72. type Age int
  73. type cat struct{ Name string }
  74. for _, test := range []struct {
  75. label string
  76. input string
  77. decodeInto interface{}
  78. wantDecoded interface{}
  79. }{
  80. {
  81. label: "embedded struct",
  82. input: `Name = "milton"`,
  83. decodeInto: &struct{ Dog }{},
  84. wantDecoded: &struct{ Dog }{Dog{"milton"}},
  85. },
  86. {
  87. label: "embedded non-nil pointer to struct",
  88. input: `Name = "milton"`,
  89. decodeInto: &struct{ *Dog }{},
  90. wantDecoded: &struct{ *Dog }{&Dog{"milton"}},
  91. },
  92. {
  93. label: "embedded nil pointer to struct",
  94. input: ``,
  95. decodeInto: &struct{ *Dog }{},
  96. wantDecoded: &struct{ *Dog }{nil},
  97. },
  98. {
  99. label: "unexported embedded struct",
  100. input: `Name = "socks"`,
  101. decodeInto: &struct{ cat }{},
  102. wantDecoded: &struct{ cat }{cat{"socks"}},
  103. },
  104. {
  105. label: "embedded int",
  106. input: `Age = -5`,
  107. decodeInto: &struct{ Age }{},
  108. wantDecoded: &struct{ Age }{-5},
  109. },
  110. } {
  111. _, err := Decode(test.input, test.decodeInto)
  112. if err != nil {
  113. t.Fatal(err)
  114. }
  115. if !reflect.DeepEqual(test.wantDecoded, test.decodeInto) {
  116. t.Errorf("%s: want decoded == %+v, got %+v",
  117. test.label, test.wantDecoded, test.decodeInto)
  118. }
  119. }
  120. }
  121. func TestDecodeIgnoredFields(t *testing.T) {
  122. type simple struct {
  123. Number int `toml:"-"`
  124. }
  125. const input = `
  126. Number = 123
  127. - = 234
  128. `
  129. var s simple
  130. if _, err := Decode(input, &s); err != nil {
  131. t.Fatal(err)
  132. }
  133. if s.Number != 0 {
  134. t.Errorf("got: %d; want 0", s.Number)
  135. }
  136. }
  137. func TestTableArrays(t *testing.T) {
  138. var tomlTableArrays = `
  139. [[albums]]
  140. name = "Born to Run"
  141. [[albums.songs]]
  142. name = "Jungleland"
  143. [[albums.songs]]
  144. name = "Meeting Across the River"
  145. [[albums]]
  146. name = "Born in the USA"
  147. [[albums.songs]]
  148. name = "Glory Days"
  149. [[albums.songs]]
  150. name = "Dancing in the Dark"
  151. `
  152. type Song struct {
  153. Name string
  154. }
  155. type Album struct {
  156. Name string
  157. Songs []Song
  158. }
  159. type Music struct {
  160. Albums []Album
  161. }
  162. expected := Music{[]Album{
  163. {"Born to Run", []Song{{"Jungleland"}, {"Meeting Across the River"}}},
  164. {"Born in the USA", []Song{{"Glory Days"}, {"Dancing in the Dark"}}},
  165. }}
  166. var got Music
  167. if _, err := Decode(tomlTableArrays, &got); err != nil {
  168. t.Fatal(err)
  169. }
  170. if !reflect.DeepEqual(expected, got) {
  171. t.Fatalf("\n%#v\n!=\n%#v\n", expected, got)
  172. }
  173. }
  174. func TestTableNesting(t *testing.T) {
  175. for _, tt := range []struct {
  176. t string
  177. want []string
  178. }{
  179. {"[a.b.c]", []string{"a", "b", "c"}},
  180. {`[a."b.c"]`, []string{"a", "b.c"}},
  181. {`[a.'b.c']`, []string{"a", "b.c"}},
  182. {`[a.' b ']`, []string{"a", " b "}},
  183. {"[ d.e.f ]", []string{"d", "e", "f"}},
  184. {"[ g . h . i ]", []string{"g", "h", "i"}},
  185. {`[ j . "ʞ" . 'l' ]`, []string{"j", "ʞ", "l"}},
  186. } {
  187. var m map[string]interface{}
  188. if _, err := Decode(tt.t, &m); err != nil {
  189. t.Errorf("Decode(%q): got error: %s", tt.t, err)
  190. continue
  191. }
  192. if keys := extractNestedKeys(m); !reflect.DeepEqual(keys, tt.want) {
  193. t.Errorf("Decode(%q): got nested keys %#v; want %#v",
  194. tt.t, keys, tt.want)
  195. }
  196. }
  197. }
  198. func extractNestedKeys(v map[string]interface{}) []string {
  199. var result []string
  200. for {
  201. if len(v) != 1 {
  202. return result
  203. }
  204. for k, m := range v {
  205. result = append(result, k)
  206. var ok bool
  207. v, ok = m.(map[string]interface{})
  208. if !ok {
  209. return result
  210. }
  211. }
  212. }
  213. }
  214. // Case insensitive matching tests.
  215. // A bit more comprehensive than needed given the current implementation,
  216. // but implementations change.
  217. // Probably still missing demonstrations of some ugly corner cases regarding
  218. // case insensitive matching and multiple fields.
  219. func TestCase(t *testing.T) {
  220. var caseToml = `
  221. tOpString = "string"
  222. tOpInt = 1
  223. tOpFloat = 1.1
  224. tOpBool = true
  225. tOpdate = 2006-01-02T15:04:05Z
  226. tOparray = [ "array" ]
  227. Match = "i should be in Match only"
  228. MatcH = "i should be in MatcH only"
  229. once = "just once"
  230. [nEst.eD]
  231. nEstedString = "another string"
  232. `
  233. type InsensitiveEd struct {
  234. NestedString string
  235. }
  236. type InsensitiveNest struct {
  237. Ed InsensitiveEd
  238. }
  239. type Insensitive struct {
  240. TopString string
  241. TopInt int
  242. TopFloat float64
  243. TopBool bool
  244. TopDate time.Time
  245. TopArray []string
  246. Match string
  247. MatcH string
  248. Once string
  249. OncE string
  250. Nest InsensitiveNest
  251. }
  252. tme, err := time.Parse(time.RFC3339, time.RFC3339[:len(time.RFC3339)-5])
  253. if err != nil {
  254. panic(err)
  255. }
  256. expected := Insensitive{
  257. TopString: "string",
  258. TopInt: 1,
  259. TopFloat: 1.1,
  260. TopBool: true,
  261. TopDate: tme,
  262. TopArray: []string{"array"},
  263. MatcH: "i should be in MatcH only",
  264. Match: "i should be in Match only",
  265. Once: "just once",
  266. OncE: "",
  267. Nest: InsensitiveNest{
  268. Ed: InsensitiveEd{NestedString: "another string"},
  269. },
  270. }
  271. var got Insensitive
  272. if _, err := Decode(caseToml, &got); err != nil {
  273. t.Fatal(err)
  274. }
  275. if !reflect.DeepEqual(expected, got) {
  276. t.Fatalf("\n%#v\n!=\n%#v\n", expected, got)
  277. }
  278. }
  279. func TestPointers(t *testing.T) {
  280. type Object struct {
  281. Type string
  282. Description string
  283. }
  284. type Dict struct {
  285. NamedObject map[string]*Object
  286. BaseObject *Object
  287. Strptr *string
  288. Strptrs []*string
  289. }
  290. s1, s2, s3 := "blah", "abc", "def"
  291. expected := &Dict{
  292. Strptr: &s1,
  293. Strptrs: []*string{&s2, &s3},
  294. NamedObject: map[string]*Object{
  295. "foo": {"FOO", "fooooo!!!"},
  296. "bar": {"BAR", "ba-ba-ba-ba-barrrr!!!"},
  297. },
  298. BaseObject: &Object{"BASE", "da base"},
  299. }
  300. ex1 := `
  301. Strptr = "blah"
  302. Strptrs = ["abc", "def"]
  303. [NamedObject.foo]
  304. Type = "FOO"
  305. Description = "fooooo!!!"
  306. [NamedObject.bar]
  307. Type = "BAR"
  308. Description = "ba-ba-ba-ba-barrrr!!!"
  309. [BaseObject]
  310. Type = "BASE"
  311. Description = "da base"
  312. `
  313. dict := new(Dict)
  314. _, err := Decode(ex1, dict)
  315. if err != nil {
  316. t.Errorf("Decode error: %v", err)
  317. }
  318. if !reflect.DeepEqual(expected, dict) {
  319. t.Fatalf("\n%#v\n!=\n%#v\n", expected, dict)
  320. }
  321. }
  322. func TestDecodeDatetime(t *testing.T) {
  323. const noTimestamp = "2006-01-02T15:04:05"
  324. for _, tt := range []struct {
  325. s string
  326. t string
  327. format string
  328. }{
  329. {"1979-05-27T07:32:00Z", "1979-05-27T07:32:00Z", time.RFC3339},
  330. {"1979-05-27T00:32:00-07:00", "1979-05-27T00:32:00-07:00", time.RFC3339},
  331. {
  332. "1979-05-27T00:32:00.999999-07:00",
  333. "1979-05-27T00:32:00.999999-07:00",
  334. time.RFC3339,
  335. },
  336. {"1979-05-27T07:32:00", "1979-05-27T07:32:00", noTimestamp},
  337. {
  338. "1979-05-27T00:32:00.999999",
  339. "1979-05-27T00:32:00.999999",
  340. noTimestamp,
  341. },
  342. {"1979-05-27", "1979-05-27T00:00:00", noTimestamp},
  343. } {
  344. var x struct{ D time.Time }
  345. input := "d = " + tt.s
  346. if _, err := Decode(input, &x); err != nil {
  347. t.Errorf("Decode(%q): got error: %s", input, err)
  348. continue
  349. }
  350. want, err := time.ParseInLocation(tt.format, tt.t, time.Local)
  351. if err != nil {
  352. panic(err)
  353. }
  354. if !x.D.Equal(want) {
  355. t.Errorf("Decode(%q): got %s; want %s", input, x.D, want)
  356. }
  357. }
  358. }
  359. func TestDecodeBadDatetime(t *testing.T) {
  360. var x struct{ T time.Time }
  361. for _, s := range []string{
  362. "123",
  363. "2006-01-50T00:00:00Z",
  364. "2006-01-30T00:00",
  365. "2006-01-30T",
  366. } {
  367. input := "T = " + s
  368. if _, err := Decode(input, &x); err == nil {
  369. t.Errorf("Expected invalid DateTime error for %q", s)
  370. }
  371. }
  372. }
  373. func TestDecodeMultilineStrings(t *testing.T) {
  374. var x struct {
  375. S string
  376. }
  377. const s0 = `s = """
  378. a b \n c
  379. d e f
  380. """`
  381. if _, err := Decode(s0, &x); err != nil {
  382. t.Fatal(err)
  383. }
  384. if want := "a b \n c\nd e f\n"; x.S != want {
  385. t.Errorf("got: %q; want: %q", x.S, want)
  386. }
  387. const s1 = `s = """a b c\
  388. """`
  389. if _, err := Decode(s1, &x); err != nil {
  390. t.Fatal(err)
  391. }
  392. if want := "a b c"; x.S != want {
  393. t.Errorf("got: %q; want: %q", x.S, want)
  394. }
  395. }
  396. type sphere struct {
  397. Center [3]float64
  398. Radius float64
  399. }
  400. func TestDecodeSimpleArray(t *testing.T) {
  401. var s1 sphere
  402. if _, err := Decode(`center = [0.0, 1.5, 0.0]`, &s1); err != nil {
  403. t.Fatal(err)
  404. }
  405. }
  406. func TestDecodeArrayWrongSize(t *testing.T) {
  407. var s1 sphere
  408. if _, err := Decode(`center = [0.1, 2.3]`, &s1); err == nil {
  409. t.Fatal("Expected array type mismatch error")
  410. }
  411. }
  412. func TestDecodeLargeIntoSmallInt(t *testing.T) {
  413. type table struct {
  414. Value int8
  415. }
  416. var tab table
  417. if _, err := Decode(`value = 500`, &tab); err == nil {
  418. t.Fatal("Expected integer out-of-bounds error.")
  419. }
  420. }
  421. func TestDecodeSizedInts(t *testing.T) {
  422. type table struct {
  423. U8 uint8
  424. U16 uint16
  425. U32 uint32
  426. U64 uint64
  427. U uint
  428. I8 int8
  429. I16 int16
  430. I32 int32
  431. I64 int64
  432. I int
  433. }
  434. answer := table{1, 1, 1, 1, 1, -1, -1, -1, -1, -1}
  435. toml := `
  436. u8 = 1
  437. u16 = 1
  438. u32 = 1
  439. u64 = 1
  440. u = 1
  441. i8 = -1
  442. i16 = -1
  443. i32 = -1
  444. i64 = -1
  445. i = -1
  446. `
  447. var tab table
  448. if _, err := Decode(toml, &tab); err != nil {
  449. t.Fatal(err.Error())
  450. }
  451. if answer != tab {
  452. t.Fatalf("Expected %#v but got %#v", answer, tab)
  453. }
  454. }
  455. func TestDecodeInts(t *testing.T) {
  456. for _, tt := range []struct {
  457. s string
  458. want int64
  459. }{
  460. {"0", 0},
  461. {"+99", 99},
  462. {"-10", -10},
  463. {"1_234_567", 1234567},
  464. {"1_2_3_4", 1234},
  465. {"-9_223_372_036_854_775_808", math.MinInt64},
  466. {"9_223_372_036_854_775_807", math.MaxInt64},
  467. } {
  468. var x struct{ N int64 }
  469. input := "n = " + tt.s
  470. if _, err := Decode(input, &x); err != nil {
  471. t.Errorf("Decode(%q): got error: %s", input, err)
  472. continue
  473. }
  474. if x.N != tt.want {
  475. t.Errorf("Decode(%q): got %d; want %d", input, x.N, tt.want)
  476. }
  477. }
  478. }
  479. func TestDecodeFloats(t *testing.T) {
  480. for _, tt := range []struct {
  481. s string
  482. want float64
  483. }{
  484. {"+1.0", 1},
  485. {"3.1415", 3.1415},
  486. {"-0.01", -0.01},
  487. {"5e+22", 5e22},
  488. {"1e6", 1e6},
  489. {"-2E-2", -2e-2},
  490. {"6.626e-34", 6.626e-34},
  491. {"9_224_617.445_991_228_313", 9224617.445991228313},
  492. {"9_876.54_32e1_0", 9876.5432e10},
  493. } {
  494. var x struct{ N float64 }
  495. input := "n = " + tt.s
  496. if _, err := Decode(input, &x); err != nil {
  497. t.Errorf("Decode(%q): got error: %s", input, err)
  498. continue
  499. }
  500. if x.N != tt.want {
  501. t.Errorf("Decode(%q): got %f; want %f", input, x.N, tt.want)
  502. }
  503. }
  504. }
  505. func TestDecodeMalformedNumbers(t *testing.T) {
  506. for _, tt := range []struct {
  507. s string
  508. want string
  509. }{
  510. {"++99", "expected a digit"},
  511. {"0..1", "must be followed by one or more digits"},
  512. {"0.1.2", "Invalid float value"},
  513. {"1e2.3", "Invalid float value"},
  514. {"1e2e3", "Invalid float value"},
  515. {"_123", "expected value"},
  516. {"123_", "surrounded by digits"},
  517. {"1._23", "surrounded by digits"},
  518. {"1e__23", "surrounded by digits"},
  519. {"123.", "must be followed by one or more digits"},
  520. {"1.e2", "must be followed by one or more digits"},
  521. } {
  522. var x struct{ N interface{} }
  523. input := "n = " + tt.s
  524. _, err := Decode(input, &x)
  525. if err == nil {
  526. t.Errorf("Decode(%q): got nil, want error containing %q",
  527. input, tt.want)
  528. continue
  529. }
  530. if !strings.Contains(err.Error(), tt.want) {
  531. t.Errorf("Decode(%q): got %q, want error containing %q",
  532. input, err, tt.want)
  533. }
  534. }
  535. }
  536. func TestDecodeBadValues(t *testing.T) {
  537. for _, tt := range []struct {
  538. v interface{}
  539. want string
  540. }{
  541. {3, "non-pointer int"},
  542. {(*int)(nil), "nil"},
  543. } {
  544. _, err := Decode(`x = 3`, tt.v)
  545. if err == nil {
  546. t.Errorf("Decode(%v): got nil; want error containing %q",
  547. tt.v, tt.want)
  548. continue
  549. }
  550. if !strings.Contains(err.Error(), tt.want) {
  551. t.Errorf("Decode(%v): got %q; want error containing %q",
  552. tt.v, err, tt.want)
  553. }
  554. }
  555. }
  556. func TestUnmarshaler(t *testing.T) {
  557. var tomlBlob = `
  558. [dishes.hamboogie]
  559. name = "Hamboogie with fries"
  560. price = 10.99
  561. [[dishes.hamboogie.ingredients]]
  562. name = "Bread Bun"
  563. [[dishes.hamboogie.ingredients]]
  564. name = "Lettuce"
  565. [[dishes.hamboogie.ingredients]]
  566. name = "Real Beef Patty"
  567. [[dishes.hamboogie.ingredients]]
  568. name = "Tomato"
  569. [dishes.eggsalad]
  570. name = "Egg Salad with rice"
  571. price = 3.99
  572. [[dishes.eggsalad.ingredients]]
  573. name = "Egg"
  574. [[dishes.eggsalad.ingredients]]
  575. name = "Mayo"
  576. [[dishes.eggsalad.ingredients]]
  577. name = "Rice"
  578. `
  579. m := &menu{}
  580. if _, err := Decode(tomlBlob, m); err != nil {
  581. t.Fatal(err)
  582. }
  583. if len(m.Dishes) != 2 {
  584. t.Log("two dishes should be loaded with UnmarshalTOML()")
  585. t.Errorf("expected %d but got %d", 2, len(m.Dishes))
  586. }
  587. eggSalad := m.Dishes["eggsalad"]
  588. if _, ok := interface{}(eggSalad).(dish); !ok {
  589. t.Errorf("expected a dish")
  590. }
  591. if eggSalad.Name != "Egg Salad with rice" {
  592. t.Errorf("expected the dish to be named 'Egg Salad with rice'")
  593. }
  594. if len(eggSalad.Ingredients) != 3 {
  595. t.Log("dish should be loaded with UnmarshalTOML()")
  596. t.Errorf("expected %d but got %d", 3, len(eggSalad.Ingredients))
  597. }
  598. found := false
  599. for _, i := range eggSalad.Ingredients {
  600. if i.Name == "Rice" {
  601. found = true
  602. break
  603. }
  604. }
  605. if !found {
  606. t.Error("Rice was not loaded in UnmarshalTOML()")
  607. }
  608. // test on a value - must be passed as *
  609. o := menu{}
  610. if _, err := Decode(tomlBlob, &o); err != nil {
  611. t.Fatal(err)
  612. }
  613. }
  614. func TestDecodeInlineTable(t *testing.T) {
  615. input := `
  616. [CookieJar]
  617. Types = {Chocolate = "yummy", Oatmeal = "best ever"}
  618. [Seasons]
  619. Locations = {NY = {Temp = "not cold", Rating = 4}, MI = {Temp = "freezing", Rating = 9}}
  620. `
  621. type cookieJar struct {
  622. Types map[string]string
  623. }
  624. type properties struct {
  625. Temp string
  626. Rating int
  627. }
  628. type seasons struct {
  629. Locations map[string]properties
  630. }
  631. type wrapper struct {
  632. CookieJar cookieJar
  633. Seasons seasons
  634. }
  635. var got wrapper
  636. meta, err := Decode(input, &got)
  637. if err != nil {
  638. t.Fatal(err)
  639. }
  640. want := wrapper{
  641. CookieJar: cookieJar{
  642. Types: map[string]string{
  643. "Chocolate": "yummy",
  644. "Oatmeal": "best ever",
  645. },
  646. },
  647. Seasons: seasons{
  648. Locations: map[string]properties{
  649. "NY": {
  650. Temp: "not cold",
  651. Rating: 4,
  652. },
  653. "MI": {
  654. Temp: "freezing",
  655. Rating: 9,
  656. },
  657. },
  658. },
  659. }
  660. if !reflect.DeepEqual(got, want) {
  661. t.Fatalf("after decode, got:\n\n%#v\n\nwant:\n\n%#v", got, want)
  662. }
  663. if len(meta.keys) != 12 {
  664. t.Errorf("after decode, got %d meta keys; want 12", len(meta.keys))
  665. }
  666. if len(meta.types) != 12 {
  667. t.Errorf("after decode, got %d meta types; want 12", len(meta.types))
  668. }
  669. }
  670. func TestDecodeInlineTableArray(t *testing.T) {
  671. type point struct {
  672. X, Y, Z int
  673. }
  674. var got struct {
  675. Points []point
  676. }
  677. // Example inline table array from the spec.
  678. const in = `
  679. points = [ { x = 1, y = 2, z = 3 },
  680. { x = 7, y = 8, z = 9 },
  681. { x = 2, y = 4, z = 8 } ]
  682. `
  683. if _, err := Decode(in, &got); err != nil {
  684. t.Fatal(err)
  685. }
  686. want := []point{
  687. {X: 1, Y: 2, Z: 3},
  688. {X: 7, Y: 8, Z: 9},
  689. {X: 2, Y: 4, Z: 8},
  690. }
  691. if !reflect.DeepEqual(got.Points, want) {
  692. t.Errorf("got %#v; want %#v", got.Points, want)
  693. }
  694. }
  695. func TestDecodeMalformedInlineTable(t *testing.T) {
  696. for _, tt := range []struct {
  697. s string
  698. want string
  699. }{
  700. {"{,}", "unexpected comma"},
  701. {"{x = 3 y = 4}", "expected a comma or an inline table terminator"},
  702. {"{x=3,,y=4}", "unexpected comma"},
  703. {"{x=3,\ny=4}", "newlines not allowed"},
  704. {"{x=3\n,y=4}", "newlines not allowed"},
  705. } {
  706. var x struct{ A map[string]int }
  707. input := "a = " + tt.s
  708. _, err := Decode(input, &x)
  709. if err == nil {
  710. t.Errorf("Decode(%q): got nil, want error containing %q",
  711. input, tt.want)
  712. continue
  713. }
  714. if !strings.Contains(err.Error(), tt.want) {
  715. t.Errorf("Decode(%q): got %q, want error containing %q",
  716. input, err, tt.want)
  717. }
  718. }
  719. }
  720. type menu struct {
  721. Dishes map[string]dish
  722. }
  723. func (m *menu) UnmarshalTOML(p interface{}) error {
  724. m.Dishes = make(map[string]dish)
  725. data, _ := p.(map[string]interface{})
  726. dishes := data["dishes"].(map[string]interface{})
  727. for n, v := range dishes {
  728. if d, ok := v.(map[string]interface{}); ok {
  729. nd := dish{}
  730. nd.UnmarshalTOML(d)
  731. m.Dishes[n] = nd
  732. } else {
  733. return fmt.Errorf("not a dish")
  734. }
  735. }
  736. return nil
  737. }
  738. type dish struct {
  739. Name string
  740. Price float32
  741. Ingredients []ingredient
  742. }
  743. func (d *dish) UnmarshalTOML(p interface{}) error {
  744. data, _ := p.(map[string]interface{})
  745. d.Name, _ = data["name"].(string)
  746. d.Price, _ = data["price"].(float32)
  747. ingredients, _ := data["ingredients"].([]map[string]interface{})
  748. for _, e := range ingredients {
  749. n, _ := interface{}(e).(map[string]interface{})
  750. name, _ := n["name"].(string)
  751. i := ingredient{name}
  752. d.Ingredients = append(d.Ingredients, i)
  753. }
  754. return nil
  755. }
  756. type ingredient struct {
  757. Name string
  758. }
  759. func TestDecodeSlices(t *testing.T) {
  760. type T struct {
  761. S []string
  762. }
  763. for i, tt := range []struct {
  764. v T
  765. input string
  766. want T
  767. }{
  768. {T{}, "", T{}},
  769. {T{[]string{}}, "", T{[]string{}}},
  770. {T{[]string{"a", "b"}}, "", T{[]string{"a", "b"}}},
  771. {T{}, "S = []", T{[]string{}}},
  772. {T{[]string{}}, "S = []", T{[]string{}}},
  773. {T{[]string{"a", "b"}}, "S = []", T{[]string{}}},
  774. {T{}, `S = ["x"]`, T{[]string{"x"}}},
  775. {T{[]string{}}, `S = ["x"]`, T{[]string{"x"}}},
  776. {T{[]string{"a", "b"}}, `S = ["x"]`, T{[]string{"x"}}},
  777. } {
  778. if _, err := Decode(tt.input, &tt.v); err != nil {
  779. t.Errorf("[%d] %s", i, err)
  780. continue
  781. }
  782. if !reflect.DeepEqual(tt.v, tt.want) {
  783. t.Errorf("[%d] got %#v; want %#v", i, tt.v, tt.want)
  784. }
  785. }
  786. }
  787. func TestDecodePrimitive(t *testing.T) {
  788. type S struct {
  789. P Primitive
  790. }
  791. type T struct {
  792. S []int
  793. }
  794. slicep := func(s []int) *[]int { return &s }
  795. arrayp := func(a [2]int) *[2]int { return &a }
  796. mapp := func(m map[string]int) *map[string]int { return &m }
  797. for i, tt := range []struct {
  798. v interface{}
  799. input string
  800. want interface{}
  801. }{
  802. // slices
  803. {slicep(nil), "", slicep(nil)},
  804. {slicep([]int{}), "", slicep([]int{})},
  805. {slicep([]int{1, 2, 3}), "", slicep([]int{1, 2, 3})},
  806. {slicep(nil), "P = [1,2]", slicep([]int{1, 2})},
  807. {slicep([]int{}), "P = [1,2]", slicep([]int{1, 2})},
  808. {slicep([]int{1, 2, 3}), "P = [1,2]", slicep([]int{1, 2})},
  809. // arrays
  810. {arrayp([2]int{2, 3}), "", arrayp([2]int{2, 3})},
  811. {arrayp([2]int{2, 3}), "P = [3,4]", arrayp([2]int{3, 4})},
  812. // maps
  813. {mapp(nil), "", mapp(nil)},
  814. {mapp(map[string]int{}), "", mapp(map[string]int{})},
  815. {mapp(map[string]int{"a": 1}), "", mapp(map[string]int{"a": 1})},
  816. {mapp(nil), "[P]\na = 2", mapp(map[string]int{"a": 2})},
  817. {mapp(map[string]int{}), "[P]\na = 2", mapp(map[string]int{"a": 2})},
  818. {mapp(map[string]int{"a": 1, "b": 3}), "[P]\na = 2", mapp(map[string]int{"a": 2, "b": 3})},
  819. // structs
  820. {&T{nil}, "[P]", &T{nil}},
  821. {&T{[]int{}}, "[P]", &T{[]int{}}},
  822. {&T{[]int{1, 2, 3}}, "[P]", &T{[]int{1, 2, 3}}},
  823. {&T{nil}, "[P]\nS = [1,2]", &T{[]int{1, 2}}},
  824. {&T{[]int{}}, "[P]\nS = [1,2]", &T{[]int{1, 2}}},
  825. {&T{[]int{1, 2, 3}}, "[P]\nS = [1,2]", &T{[]int{1, 2}}},
  826. } {
  827. var s S
  828. md, err := Decode(tt.input, &s)
  829. if err != nil {
  830. t.Errorf("[%d] Decode error: %s", i, err)
  831. continue
  832. }
  833. if err := md.PrimitiveDecode(s.P, tt.v); err != nil {
  834. t.Errorf("[%d] PrimitiveDecode error: %s", i, err)
  835. continue
  836. }
  837. if !reflect.DeepEqual(tt.v, tt.want) {
  838. t.Errorf("[%d] got %#v; want %#v", i, tt.v, tt.want)
  839. }
  840. }
  841. }
  842. func TestDecodeErrors(t *testing.T) {
  843. for _, s := range []string{
  844. `x="`,
  845. `x='`,
  846. `x='''`,
  847. // Cases found by fuzzing in
  848. // https://github.com/BurntSushi/toml/issues/155.
  849. `""�`, // used to panic with index out of range
  850. `e="""`, // used to hang
  851. } {
  852. var x struct{}
  853. _, err := Decode(s, &x)
  854. if err == nil {
  855. t.Errorf("Decode(%q): got nil error", s)
  856. }
  857. }
  858. }
  859. // Test for https://github.com/BurntSushi/toml/pull/166.
  860. func TestDecodeBoolArray(t *testing.T) {
  861. for _, tt := range []struct {
  862. s string
  863. got interface{}
  864. want interface{}
  865. }{
  866. {
  867. "a = [true, false]",
  868. &struct{ A []bool }{},
  869. &struct{ A []bool }{[]bool{true, false}},
  870. },
  871. {
  872. "a = {a = true, b = false}",
  873. &struct{ A map[string]bool }{},
  874. &struct{ A map[string]bool }{map[string]bool{"a": true, "b": false}},
  875. },
  876. } {
  877. if _, err := Decode(tt.s, tt.got); err != nil {
  878. t.Errorf("Decode(%q): %s", tt.s, err)
  879. continue
  880. }
  881. if !reflect.DeepEqual(tt.got, tt.want) {
  882. t.Errorf("Decode(%q): got %#v; want %#v", tt.s, tt.got, tt.want)
  883. }
  884. }
  885. }
  886. func ExampleMetaData_PrimitiveDecode() {
  887. var md MetaData
  888. var err error
  889. var tomlBlob = `
  890. ranking = ["Springsteen", "J Geils"]
  891. [bands.Springsteen]
  892. started = 1973
  893. albums = ["Greetings", "WIESS", "Born to Run", "Darkness"]
  894. [bands."J Geils"]
  895. started = 1970
  896. albums = ["The J. Geils Band", "Full House", "Blow Your Face Out"]
  897. `
  898. type band struct {
  899. Started int
  900. Albums []string
  901. }
  902. type classics struct {
  903. Ranking []string
  904. Bands map[string]Primitive
  905. }
  906. // Do the initial decode. Reflection is delayed on Primitive values.
  907. var music classics
  908. if md, err = Decode(tomlBlob, &music); err != nil {
  909. log.Fatal(err)
  910. }
  911. // MetaData still includes information on Primitive values.
  912. fmt.Printf("Is `bands.Springsteen` defined? %v\n",
  913. md.IsDefined("bands", "Springsteen"))
  914. // Decode primitive data into Go values.
  915. for _, artist := range music.Ranking {
  916. // A band is a primitive value, so we need to decode it to get a
  917. // real `band` value.
  918. primValue := music.Bands[artist]
  919. var aBand band
  920. if err = md.PrimitiveDecode(primValue, &aBand); err != nil {
  921. log.Fatal(err)
  922. }
  923. fmt.Printf("%s started in %d.\n", artist, aBand.Started)
  924. }
  925. // Check to see if there were any fields left undecoded.
  926. // Note that this won't be empty before decoding the Primitive value!
  927. fmt.Printf("Undecoded: %q\n", md.Undecoded())
  928. // Output:
  929. // Is `bands.Springsteen` defined? true
  930. // Springsteen started in 1973.
  931. // J Geils started in 1970.
  932. // Undecoded: []
  933. }
  934. func ExampleDecode() {
  935. var tomlBlob = `
  936. # Some comments.
  937. [alpha]
  938. ip = "10.0.0.1"
  939. [alpha.config]
  940. Ports = [ 8001, 8002 ]
  941. Location = "Toronto"
  942. Created = 1987-07-05T05:45:00Z
  943. [beta]
  944. ip = "10.0.0.2"
  945. [beta.config]
  946. Ports = [ 9001, 9002 ]
  947. Location = "New Jersey"
  948. Created = 1887-01-05T05:55:00Z
  949. `
  950. type serverConfig struct {
  951. Ports []int
  952. Location string
  953. Created time.Time
  954. }
  955. type server struct {
  956. IP string `toml:"ip,omitempty"`
  957. Config serverConfig `toml:"config"`
  958. }
  959. type servers map[string]server
  960. var config servers
  961. if _, err := Decode(tomlBlob, &config); err != nil {
  962. log.Fatal(err)
  963. }
  964. for _, name := range []string{"alpha", "beta"} {
  965. s := config[name]
  966. fmt.Printf("Server: %s (ip: %s) in %s created on %s\n",
  967. name, s.IP, s.Config.Location,
  968. s.Config.Created.Format("2006-01-02"))
  969. fmt.Printf("Ports: %v\n", s.Config.Ports)
  970. }
  971. // Output:
  972. // Server: alpha (ip: 10.0.0.1) in Toronto created on 1987-07-05
  973. // Ports: [8001 8002]
  974. // Server: beta (ip: 10.0.0.2) in New Jersey created on 1887-01-05
  975. // Ports: [9001 9002]
  976. }
  977. type duration struct {
  978. time.Duration
  979. }
  980. func (d *duration) UnmarshalText(text []byte) error {
  981. var err error
  982. d.Duration, err = time.ParseDuration(string(text))
  983. return err
  984. }
  985. // Example Unmarshaler shows how to decode TOML strings into your own
  986. // custom data type.
  987. func Example_unmarshaler() {
  988. blob := `
  989. [[song]]
  990. name = "Thunder Road"
  991. duration = "4m49s"
  992. [[song]]
  993. name = "Stairway to Heaven"
  994. duration = "8m03s"
  995. `
  996. type song struct {
  997. Name string
  998. Duration duration
  999. }
  1000. type songs struct {
  1001. Song []song
  1002. }
  1003. var favorites songs
  1004. if _, err := Decode(blob, &favorites); err != nil {
  1005. log.Fatal(err)
  1006. }
  1007. // Code to implement the TextUnmarshaler interface for `duration`:
  1008. //
  1009. // type duration struct {
  1010. // time.Duration
  1011. // }
  1012. //
  1013. // func (d *duration) UnmarshalText(text []byte) error {
  1014. // var err error
  1015. // d.Duration, err = time.ParseDuration(string(text))
  1016. // return err
  1017. // }
  1018. for _, s := range favorites.Song {
  1019. fmt.Printf("%s (%s)\n", s.Name, s.Duration)
  1020. }
  1021. // Output:
  1022. // Thunder Road (4m49s)
  1023. // Stairway to Heaven (8m3s)
  1024. }
  1025. // Example StrictDecoding shows how to detect whether there are keys in the
  1026. // TOML document that weren't decoded into the value given. This is useful
  1027. // for returning an error to the user if they've included extraneous fields
  1028. // in their configuration.
  1029. func Example_strictDecoding() {
  1030. var blob = `
  1031. key1 = "value1"
  1032. key2 = "value2"
  1033. key3 = "value3"
  1034. `
  1035. type config struct {
  1036. Key1 string
  1037. Key3 string
  1038. }
  1039. var conf config
  1040. md, err := Decode(blob, &conf)
  1041. if err != nil {
  1042. log.Fatal(err)
  1043. }
  1044. fmt.Printf("Undecoded keys: %q\n", md.Undecoded())
  1045. // Output:
  1046. // Undecoded keys: ["key2"]
  1047. }
  1048. // Example UnmarshalTOML shows how to implement a struct type that knows how to
  1049. // unmarshal itself. The struct must take full responsibility for mapping the
  1050. // values passed into the struct. The method may be used with interfaces in a
  1051. // struct in cases where the actual type is not known until the data is
  1052. // examined.
  1053. func Example_unmarshalTOML() {
  1054. var blob = `
  1055. [[parts]]
  1056. type = "valve"
  1057. id = "valve-1"
  1058. size = 1.2
  1059. rating = 4
  1060. [[parts]]
  1061. type = "valve"
  1062. id = "valve-2"
  1063. size = 2.1
  1064. rating = 5
  1065. [[parts]]
  1066. type = "pipe"
  1067. id = "pipe-1"
  1068. length = 2.1
  1069. diameter = 12
  1070. [[parts]]
  1071. type = "cable"
  1072. id = "cable-1"
  1073. length = 12
  1074. rating = 3.1
  1075. `
  1076. o := &order{}
  1077. err := Unmarshal([]byte(blob), o)
  1078. if err != nil {
  1079. log.Fatal(err)
  1080. }
  1081. fmt.Println(len(o.parts))
  1082. for _, part := range o.parts {
  1083. fmt.Println(part.Name())
  1084. }
  1085. // Code to implement UmarshalJSON.
  1086. // type order struct {
  1087. // // NOTE `order.parts` is a private slice of type `part` which is an
  1088. // // interface and may only be loaded from toml using the
  1089. // // UnmarshalTOML() method of the Umarshaler interface.
  1090. // parts parts
  1091. // }
  1092. // func (o *order) UnmarshalTOML(data interface{}) error {
  1093. // // NOTE the example below contains detailed type casting to show how
  1094. // // the 'data' is retrieved. In operational use, a type cast wrapper
  1095. // // may be preferred e.g.
  1096. // //
  1097. // // func AsMap(v interface{}) (map[string]interface{}, error) {
  1098. // // return v.(map[string]interface{})
  1099. // // }
  1100. // //
  1101. // // resulting in:
  1102. // // d, _ := AsMap(data)
  1103. // //
  1104. // d, _ := data.(map[string]interface{})
  1105. // parts, _ := d["parts"].([]map[string]interface{})
  1106. // for _, p := range parts {
  1107. // typ, _ := p["type"].(string)
  1108. // id, _ := p["id"].(string)
  1109. // // detect the type of part and handle each case
  1110. // switch p["type"] {
  1111. // case "valve":
  1112. // size := float32(p["size"].(float64))
  1113. // rating := int(p["rating"].(int64))
  1114. // valve := &valve{
  1115. // Type: typ,
  1116. // ID: id,
  1117. // Size: size,
  1118. // Rating: rating,
  1119. // }
  1120. // o.parts = append(o.parts, valve)
  1121. // case "pipe":
  1122. // length := float32(p["length"].(float64))
  1123. // diameter := int(p["diameter"].(int64))
  1124. // pipe := &pipe{
  1125. // Type: typ,
  1126. // ID: id,
  1127. // Length: length,
  1128. // Diameter: diameter,
  1129. // }
  1130. // o.parts = append(o.parts, pipe)
  1131. // case "cable":
  1132. // length := int(p["length"].(int64))
  1133. // rating := float32(p["rating"].(float64))
  1134. // cable := &cable{
  1135. // Type: typ,
  1136. // ID: id,
  1137. // Length: length,
  1138. // Rating: rating,
  1139. // }
  1140. // o.parts = append(o.parts, cable)
  1141. // }
  1142. // }
  1143. // return nil
  1144. // }
  1145. // type parts []part
  1146. // type part interface {
  1147. // Name() string
  1148. // }
  1149. // type valve struct {
  1150. // Type string
  1151. // ID string
  1152. // Size float32
  1153. // Rating int
  1154. // }
  1155. // func (v *valve) Name() string {
  1156. // return fmt.Sprintf("VALVE: %s", v.ID)
  1157. // }
  1158. // type pipe struct {
  1159. // Type string
  1160. // ID string
  1161. // Length float32
  1162. // Diameter int
  1163. // }
  1164. // func (p *pipe) Name() string {
  1165. // return fmt.Sprintf("PIPE: %s", p.ID)
  1166. // }
  1167. // type cable struct {
  1168. // Type string
  1169. // ID string
  1170. // Length int
  1171. // Rating float32
  1172. // }
  1173. // func (c *cable) Name() string {
  1174. // return fmt.Sprintf("CABLE: %s", c.ID)
  1175. // }
  1176. // Output:
  1177. // 4
  1178. // VALVE: valve-1
  1179. // VALVE: valve-2
  1180. // PIPE: pipe-1
  1181. // CABLE: cable-1
  1182. }
  1183. type order struct {
  1184. // NOTE `order.parts` is a private slice of type `part` which is an
  1185. // interface and may only be loaded from toml using the UnmarshalTOML()
  1186. // method of the Umarshaler interface.
  1187. parts parts
  1188. }
  1189. func (o *order) UnmarshalTOML(data interface{}) error {
  1190. // NOTE the example below contains detailed type casting to show how
  1191. // the 'data' is retrieved. In operational use, a type cast wrapper
  1192. // may be preferred e.g.
  1193. //
  1194. // func AsMap(v interface{}) (map[string]interface{}, error) {
  1195. // return v.(map[string]interface{})
  1196. // }
  1197. //
  1198. // resulting in:
  1199. // d, _ := AsMap(data)
  1200. //
  1201. d, _ := data.(map[string]interface{})
  1202. parts, _ := d["parts"].([]map[string]interface{})
  1203. for _, p := range parts {
  1204. typ, _ := p["type"].(string)
  1205. id, _ := p["id"].(string)
  1206. // detect the type of part and handle each case
  1207. switch p["type"] {
  1208. case "valve":
  1209. size := float32(p["size"].(float64))
  1210. rating := int(p["rating"].(int64))
  1211. valve := &valve{
  1212. Type: typ,
  1213. ID: id,
  1214. Size: size,
  1215. Rating: rating,
  1216. }
  1217. o.parts = append(o.parts, valve)
  1218. case "pipe":
  1219. length := float32(p["length"].(float64))
  1220. diameter := int(p["diameter"].(int64))
  1221. pipe := &pipe{
  1222. Type: typ,
  1223. ID: id,
  1224. Length: length,
  1225. Diameter: diameter,
  1226. }
  1227. o.parts = append(o.parts, pipe)
  1228. case "cable":
  1229. length := int(p["length"].(int64))
  1230. rating := float32(p["rating"].(float64))
  1231. cable := &cable{
  1232. Type: typ,
  1233. ID: id,
  1234. Length: length,
  1235. Rating: rating,
  1236. }
  1237. o.parts = append(o.parts, cable)
  1238. }
  1239. }
  1240. return nil
  1241. }
  1242. type parts []part
  1243. type part interface {
  1244. Name() string
  1245. }
  1246. type valve struct {
  1247. Type string
  1248. ID string
  1249. Size float32
  1250. Rating int
  1251. }
  1252. func (v *valve) Name() string {
  1253. return fmt.Sprintf("VALVE: %s", v.ID)
  1254. }
  1255. type pipe struct {
  1256. Type string
  1257. ID string
  1258. Length float32
  1259. Diameter int
  1260. }
  1261. func (p *pipe) Name() string {
  1262. return fmt.Sprintf("PIPE: %s", p.ID)
  1263. }
  1264. type cable struct {
  1265. Type string
  1266. ID string
  1267. Length int
  1268. Rating float32
  1269. }
  1270. func (c *cable) Name() string {
  1271. return fmt.Sprintf("CABLE: %s", c.ID)
  1272. }