aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/README.md1
-rw-r--r--src/test/invalid-encoder/array-mixed-types-ints-and-floats.json15
-rw-r--r--src/test/invalid.rs76
-rw-r--r--src/test/invalid/array-mixed-types-arrays-and-ints.toml1
-rw-r--r--src/test/invalid/array-mixed-types-ints-and-floats.toml1
-rw-r--r--src/test/invalid/array-mixed-types-strings-and-ints.toml1
-rw-r--r--src/test/invalid/datetime-malformed-no-leads.toml1
-rw-r--r--src/test/invalid/datetime-malformed-no-secs.toml1
-rw-r--r--src/test/invalid/datetime-malformed-no-t.toml1
-rw-r--r--src/test/invalid/datetime-malformed-no-z.toml1
-rw-r--r--src/test/invalid/datetime-malformed-with-milli.toml1
-rw-r--r--src/test/invalid/duplicate-key-table.toml5
-rw-r--r--src/test/invalid/duplicate-keys.toml2
-rw-r--r--src/test/invalid/duplicate-tables.toml2
-rw-r--r--src/test/invalid/empty-implicit-table.toml1
-rw-r--r--src/test/invalid/empty-table.toml1
-rw-r--r--src/test/invalid/float-no-leading-zero.toml2
-rw-r--r--src/test/invalid/float-no-trailing-digits.toml2
-rw-r--r--src/test/invalid/key-two-equals.toml1
-rw-r--r--src/test/invalid/string-bad-byte-escape.toml1
-rw-r--r--src/test/invalid/string-bad-escape.toml1
-rw-r--r--src/test/invalid/string-byte-escapes.toml1
-rw-r--r--src/test/invalid/string-no-close.toml1
-rw-r--r--src/test/invalid/table-array-implicit.toml14
-rw-r--r--src/test/invalid/table-array-malformed-bracket.toml2
-rw-r--r--src/test/invalid/table-array-malformed-empty.toml2
-rw-r--r--src/test/invalid/table-nested-brackets-close.toml2
-rw-r--r--src/test/invalid/table-nested-brackets-open.toml2
-rw-r--r--src/test/invalid/text-after-array-entries.toml4
-rw-r--r--src/test/invalid/text-after-integer.toml1
-rw-r--r--src/test/invalid/text-after-string.toml1
-rw-r--r--src/test/invalid/text-after-table.toml1
-rw-r--r--src/test/invalid/text-before-array-separator.toml4
-rw-r--r--src/test/invalid/text-in-array.toml5
-rw-r--r--src/test/mod.rs2
-rw-r--r--src/test/valid.rs163
-rw-r--r--src/test/valid/array-empty.json11
-rw-r--r--src/test/valid/array-empty.toml1
-rw-r--r--src/test/valid/array-nospaces.json10
-rw-r--r--src/test/valid/array-nospaces.toml1
-rw-r--r--src/test/valid/arrays-hetergeneous.json19
-rw-r--r--src/test/valid/arrays-hetergeneous.toml1
-rw-r--r--src/test/valid/arrays-nested.json13
-rw-r--r--src/test/valid/arrays-nested.toml1
-rw-r--r--src/test/valid/arrays.json34
-rw-r--r--src/test/valid/arrays.toml9
-rw-r--r--src/test/valid/bool.json4
-rw-r--r--src/test/valid/bool.toml2
-rw-r--r--src/test/valid/comments-everywhere.json12
-rw-r--r--src/test/valid/comments-everywhere.toml24
-rw-r--r--src/test/valid/datetime.json3
-rw-r--r--src/test/valid/datetime.toml1
-rw-r--r--src/test/valid/empty.json1
-rw-r--r--src/test/valid/empty.toml0
-rw-r--r--src/test/valid/example.json14
-rw-r--r--src/test/valid/example.toml5
-rw-r--r--src/test/valid/float.json4
-rw-r--r--src/test/valid/float.toml2
-rw-r--r--src/test/valid/implicit-and-explicit-after.json10
-rw-r--r--src/test/valid/implicit-and-explicit-after.toml5
-rw-r--r--src/test/valid/implicit-and-explicit-before.json10
-rw-r--r--src/test/valid/implicit-and-explicit-before.toml5
-rw-r--r--src/test/valid/implicit-groups.json9
-rw-r--r--src/test/valid/implicit-groups.toml2
-rw-r--r--src/test/valid/integer.json4
-rw-r--r--src/test/valid/integer.toml2
-rw-r--r--src/test/valid/key-equals-nospace.json3
-rw-r--r--src/test/valid/key-equals-nospace.toml1
-rw-r--r--src/test/valid/key-special-chars.json5
-rw-r--r--src/test/valid/key-special-chars.toml1
-rw-r--r--src/test/valid/key-with-pound.json3
-rw-r--r--src/test/valid/key-with-pound.toml1
-rw-r--r--src/test/valid/long-float.json4
-rw-r--r--src/test/valid/long-float.toml2
-rw-r--r--src/test/valid/long-integer.json4
-rw-r--r--src/test/valid/long-integer.toml2
-rw-r--r--src/test/valid/string-escapes.json34
-rw-r--r--src/test/valid/string-escapes.toml8
-rw-r--r--src/test/valid/string-simple.json6
-rw-r--r--src/test/valid/string-simple.toml1
-rw-r--r--src/test/valid/string-with-pound.json7
-rw-r--r--src/test/valid/string-with-pound.toml2
-rw-r--r--src/test/valid/table-array-implicit.json7
-rw-r--r--src/test/valid/table-array-implicit.toml2
-rw-r--r--src/test/valid/table-array-many.json16
-rw-r--r--src/test/valid/table-array-many.toml11
-rw-r--r--src/test/valid/table-array-nest.json18
-rw-r--r--src/test/valid/table-array-nest.toml17
-rw-r--r--src/test/valid/table-array-one.json8
-rw-r--r--src/test/valid/table-array-one.toml3
-rw-r--r--src/test/valid/table-empty.json3
-rw-r--r--src/test/valid/table-empty.toml1
-rw-r--r--src/test/valid/table-sub-empty.json3
-rw-r--r--src/test/valid/table-sub-empty.toml2
-rw-r--r--src/test/valid/table-whitespace.json3
-rw-r--r--src/test/valid/table-whitespace.toml1
-rw-r--r--src/test/valid/table-with-pound.json5
-rw-r--r--src/test/valid/table-with-pound.toml2
-rw-r--r--src/test/valid/unicode-escape.json3
-rw-r--r--src/test/valid/unicode-escape.toml1
-rw-r--r--src/test/valid/unicode-literal.json3
-rw-r--r--src/test/valid/unicode-literal.toml1
102 files changed, 736 insertions, 0 deletions
diff --git a/src/test/README.md b/src/test/README.md
new file mode 100644
index 0000000..ebbc01c
--- /dev/null
+++ b/src/test/README.md
@@ -0,0 +1 @@
+Tests are from https://github.com/BurntSushi/toml-test
diff --git a/src/test/invalid-encoder/array-mixed-types-ints-and-floats.json b/src/test/invalid-encoder/array-mixed-types-ints-and-floats.json
new file mode 100644
index 0000000..b7920a0
--- /dev/null
+++ b/src/test/invalid-encoder/array-mixed-types-ints-and-floats.json
@@ -0,0 +1,15 @@
+{
+ "ints-and-floats": {
+ "type": "array",
+ "value": [
+ {
+ "type": "integer",
+ "value": "1"
+ },
+ {
+ "type": "float",
+ "value": "1.0"
+ }
+ ]
+ }
+}
diff --git a/src/test/invalid.rs b/src/test/invalid.rs
new file mode 100644
index 0000000..9f86d13
--- /dev/null
+++ b/src/test/invalid.rs
@@ -0,0 +1,76 @@
+use {Parser};
+
+fn run(toml: &str) {
+ let mut p = Parser::new(toml);
+ let table = p.parse();
+ assert!(p.errors.len() > 0);
+ assert!(table.is_none());
+}
+
+macro_rules! test( ($name:ident, $toml:expr) => (
+ #[test]
+ fn $name() { run($toml); }
+) )
+
+test!(array_mixed_types_arrays_and_ints,
+ include_str!("invalid/array-mixed-types-arrays-and-ints.toml"))
+test!(array_mixed_types_ints_and_floats,
+ include_str!("invalid/array-mixed-types-ints-and-floats.toml"))
+test!(array_mixed_types_strings_and_ints,
+ include_str!("invalid/array-mixed-types-strings-and-ints.toml"))
+test!(datetime_malformed_no_leads,
+ include_str!("invalid/datetime-malformed-no-leads.toml"))
+test!(datetime_malformed_no_secs,
+ include_str!("invalid/datetime-malformed-no-secs.toml"))
+test!(datetime_malformed_no_t,
+ include_str!("invalid/datetime-malformed-no-t.toml"))
+test!(datetime_malformed_no_z,
+ include_str!("invalid/datetime-malformed-no-z.toml"))
+test!(datetime_malformed_with_milli,
+ include_str!("invalid/datetime-malformed-with-milli.toml"))
+test!(duplicate_keys,
+ include_str!("invalid/duplicate-keys.toml"))
+test!(duplicate_key_table,
+ include_str!("invalid/duplicate-key-table.toml"))
+test!(duplicate_tables,
+ include_str!("invalid/duplicate-tables.toml"))
+test!(empty_implicit_table,
+ include_str!("invalid/empty-implicit-table.toml"))
+test!(empty_table,
+ include_str!("invalid/empty-table.toml"))
+test!(float_no_leading_zero,
+ include_str!("invalid/float-no-leading-zero.toml"))
+test!(float_no_trailing_digits,
+ include_str!("invalid/float-no-trailing-digits.toml"))
+test!(key_two_equals,
+ include_str!("invalid/key-two-equals.toml"))
+test!(string_bad_byte_escape,
+ include_str!("invalid/string-bad-byte-escape.toml"))
+test!(string_bad_escape,
+ include_str!("invalid/string-bad-escape.toml"))
+test!(string_byte_escapes,
+ include_str!("invalid/string-byte-escapes.toml"))
+test!(string_no_close,
+ include_str!("invalid/string-no-close.toml"))
+test!(table_array_implicit,
+ include_str!("invalid/table-array-implicit.toml"))
+test!(table_array_malformed_bracket,
+ include_str!("invalid/table-array-malformed-bracket.toml"))
+test!(table_array_malformed_empty,
+ include_str!("invalid/table-array-malformed-empty.toml"))
+test!(table_nested_brackets_close,
+ include_str!("invalid/table-nested-brackets-close.toml"))
+test!(table_nested_brackets_open,
+ include_str!("invalid/table-nested-brackets-open.toml"))
+test!(text_after_array_entries,
+ include_str!("invalid/text-after-array-entries.toml"))
+test!(text_after_integer,
+ include_str!("invalid/text-after-integer.toml"))
+test!(text_after_string,
+ include_str!("invalid/text-after-string.toml"))
+test!(text_after_table,
+ include_str!("invalid/text-after-table.toml"))
+test!(text_before_array_separator,
+ include_str!("invalid/text-before-array-separator.toml"))
+test!(text_in_array,
+ include_str!("invalid/text-in-array.toml"))
diff --git a/src/test/invalid/array-mixed-types-arrays-and-ints.toml b/src/test/invalid/array-mixed-types-arrays-and-ints.toml
new file mode 100644
index 0000000..051ec73
--- /dev/null
+++ b/src/test/invalid/array-mixed-types-arrays-and-ints.toml
@@ -0,0 +1 @@
+arrays-and-ints = [1, ["Arrays are not integers."]]
diff --git a/src/test/invalid/array-mixed-types-ints-and-floats.toml b/src/test/invalid/array-mixed-types-ints-and-floats.toml
new file mode 100644
index 0000000..51ebe80
--- /dev/null
+++ b/src/test/invalid/array-mixed-types-ints-and-floats.toml
@@ -0,0 +1 @@
+ints-and-floats = [1, 1.0]
diff --git a/src/test/invalid/array-mixed-types-strings-and-ints.toml b/src/test/invalid/array-mixed-types-strings-and-ints.toml
new file mode 100644
index 0000000..f348308
--- /dev/null
+++ b/src/test/invalid/array-mixed-types-strings-and-ints.toml
@@ -0,0 +1 @@
+strings-and-ints = ["hi", 42]
diff --git a/src/test/invalid/datetime-malformed-no-leads.toml b/src/test/invalid/datetime-malformed-no-leads.toml
new file mode 100644
index 0000000..123f173
--- /dev/null
+++ b/src/test/invalid/datetime-malformed-no-leads.toml
@@ -0,0 +1 @@
+no-leads = 1987-7-05T17:45:00Z
diff --git a/src/test/invalid/datetime-malformed-no-secs.toml b/src/test/invalid/datetime-malformed-no-secs.toml
new file mode 100644
index 0000000..ba93900
--- /dev/null
+++ b/src/test/invalid/datetime-malformed-no-secs.toml
@@ -0,0 +1 @@
+no-secs = 1987-07-05T17:45Z
diff --git a/src/test/invalid/datetime-malformed-no-t.toml b/src/test/invalid/datetime-malformed-no-t.toml
new file mode 100644
index 0000000..617e3c5
--- /dev/null
+++ b/src/test/invalid/datetime-malformed-no-t.toml
@@ -0,0 +1 @@
+no-t = 1987-07-0517:45:00Z
diff --git a/src/test/invalid/datetime-malformed-no-z.toml b/src/test/invalid/datetime-malformed-no-z.toml
new file mode 100644
index 0000000..cf66b1e
--- /dev/null
+++ b/src/test/invalid/datetime-malformed-no-z.toml
@@ -0,0 +1 @@
+no-z = 1987-07-05T17:45:00
diff --git a/src/test/invalid/datetime-malformed-with-milli.toml b/src/test/invalid/datetime-malformed-with-milli.toml
new file mode 100644
index 0000000..eef792f
--- /dev/null
+++ b/src/test/invalid/datetime-malformed-with-milli.toml
@@ -0,0 +1 @@
+with-milli = 1987-07-5T17:45:00.12Z
diff --git a/src/test/invalid/duplicate-key-table.toml b/src/test/invalid/duplicate-key-table.toml
new file mode 100644
index 0000000..cedf05f
--- /dev/null
+++ b/src/test/invalid/duplicate-key-table.toml
@@ -0,0 +1,5 @@
+[fruit]
+type = "apple"
+
+[fruit.type]
+apple = "yes"
diff --git a/src/test/invalid/duplicate-keys.toml b/src/test/invalid/duplicate-keys.toml
new file mode 100644
index 0000000..9b5aee0
--- /dev/null
+++ b/src/test/invalid/duplicate-keys.toml
@@ -0,0 +1,2 @@
+dupe = false
+dupe = true
diff --git a/src/test/invalid/duplicate-tables.toml b/src/test/invalid/duplicate-tables.toml
new file mode 100644
index 0000000..8ddf49b
--- /dev/null
+++ b/src/test/invalid/duplicate-tables.toml
@@ -0,0 +1,2 @@
+[a]
+[a]
diff --git a/src/test/invalid/empty-implicit-table.toml b/src/test/invalid/empty-implicit-table.toml
new file mode 100644
index 0000000..0cc36d0
--- /dev/null
+++ b/src/test/invalid/empty-implicit-table.toml
@@ -0,0 +1 @@
+[naughty..naughty]
diff --git a/src/test/invalid/empty-table.toml b/src/test/invalid/empty-table.toml
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/src/test/invalid/empty-table.toml
@@ -0,0 +1 @@
+[]
diff --git a/src/test/invalid/float-no-leading-zero.toml b/src/test/invalid/float-no-leading-zero.toml
new file mode 100644
index 0000000..cab76bf
--- /dev/null
+++ b/src/test/invalid/float-no-leading-zero.toml
@@ -0,0 +1,2 @@
+answer = .12345
+neganswer = -.12345
diff --git a/src/test/invalid/float-no-trailing-digits.toml b/src/test/invalid/float-no-trailing-digits.toml
new file mode 100644
index 0000000..cbff2d0
--- /dev/null
+++ b/src/test/invalid/float-no-trailing-digits.toml
@@ -0,0 +1,2 @@
+answer = 1.
+neganswer = -1.
diff --git a/src/test/invalid/key-two-equals.toml b/src/test/invalid/key-two-equals.toml
new file mode 100644
index 0000000..25a0378
--- /dev/null
+++ b/src/test/invalid/key-two-equals.toml
@@ -0,0 +1 @@
+key= = 1
diff --git a/src/test/invalid/string-bad-byte-escape.toml b/src/test/invalid/string-bad-byte-escape.toml
new file mode 100644
index 0000000..4c7be59
--- /dev/null
+++ b/src/test/invalid/string-bad-byte-escape.toml
@@ -0,0 +1 @@
+naughty = "\xAg"
diff --git a/src/test/invalid/string-bad-escape.toml b/src/test/invalid/string-bad-escape.toml
new file mode 100644
index 0000000..60acb0c
--- /dev/null
+++ b/src/test/invalid/string-bad-escape.toml
@@ -0,0 +1 @@
+invalid-escape = "This string has a bad \a escape character."
diff --git a/src/test/invalid/string-byte-escapes.toml b/src/test/invalid/string-byte-escapes.toml
new file mode 100644
index 0000000..e94452a
--- /dev/null
+++ b/src/test/invalid/string-byte-escapes.toml
@@ -0,0 +1 @@
+answer = "\x33"
diff --git a/src/test/invalid/string-no-close.toml b/src/test/invalid/string-no-close.toml
new file mode 100644
index 0000000..0c292fc
--- /dev/null
+++ b/src/test/invalid/string-no-close.toml
@@ -0,0 +1 @@
+no-ending-quote = "One time, at band camp
diff --git a/src/test/invalid/table-array-implicit.toml b/src/test/invalid/table-array-implicit.toml
new file mode 100644
index 0000000..05f2507
--- /dev/null
+++ b/src/test/invalid/table-array-implicit.toml
@@ -0,0 +1,14 @@
+# This test is a bit tricky. It should fail because the first use of
+# `[[albums.songs]]` without first declaring `albums` implies that `albums`
+# must be a table. The alternative would be quite weird. Namely, it wouldn't
+# comply with the TOML spec: "Each double-bracketed sub-table will belong to
+# the most *recently* defined table element *above* it."
+#
+# This is in contrast to the *valid* test, table-array-implicit where
+# `[[albums.songs]]` works by itself, so long as `[[albums]]` isn't declared
+# later. (Although, `[albums]` could be.)
+[[albums.songs]]
+name = "Glory Days"
+
+[[albums]]
+name = "Born in the USA"
diff --git a/src/test/invalid/table-array-malformed-bracket.toml b/src/test/invalid/table-array-malformed-bracket.toml
new file mode 100644
index 0000000..39c73b0
--- /dev/null
+++ b/src/test/invalid/table-array-malformed-bracket.toml
@@ -0,0 +1,2 @@
+[[albums]
+name = "Born to Run"
diff --git a/src/test/invalid/table-array-malformed-empty.toml b/src/test/invalid/table-array-malformed-empty.toml
new file mode 100644
index 0000000..a470ca3
--- /dev/null
+++ b/src/test/invalid/table-array-malformed-empty.toml
@@ -0,0 +1,2 @@
+[[]]
+name = "Born to Run"
diff --git a/src/test/invalid/table-nested-brackets-close.toml b/src/test/invalid/table-nested-brackets-close.toml
new file mode 100644
index 0000000..c8b5a67
--- /dev/null
+++ b/src/test/invalid/table-nested-brackets-close.toml
@@ -0,0 +1,2 @@
+[a]b]
+zyx = 42
diff --git a/src/test/invalid/table-nested-brackets-open.toml b/src/test/invalid/table-nested-brackets-open.toml
new file mode 100644
index 0000000..246d7e9
--- /dev/null
+++ b/src/test/invalid/table-nested-brackets-open.toml
@@ -0,0 +1,2 @@
+[a[b]
+zyx = 42
diff --git a/src/test/invalid/text-after-array-entries.toml b/src/test/invalid/text-after-array-entries.toml
new file mode 100644
index 0000000..1a72890
--- /dev/null
+++ b/src/test/invalid/text-after-array-entries.toml
@@ -0,0 +1,4 @@
+array = [
+ "Is there life after an array separator?", No
+ "Entry"
+]
diff --git a/src/test/invalid/text-after-integer.toml b/src/test/invalid/text-after-integer.toml
new file mode 100644
index 0000000..42de7af
--- /dev/null
+++ b/src/test/invalid/text-after-integer.toml
@@ -0,0 +1 @@
+answer = 42 the ultimate answer?
diff --git a/src/test/invalid/text-after-string.toml b/src/test/invalid/text-after-string.toml
new file mode 100644
index 0000000..c92a6f1
--- /dev/null
+++ b/src/test/invalid/text-after-string.toml
@@ -0,0 +1 @@
+string = "Is there life after strings?" No.
diff --git a/src/test/invalid/text-after-table.toml b/src/test/invalid/text-after-table.toml
new file mode 100644
index 0000000..87da9db
--- /dev/null
+++ b/src/test/invalid/text-after-table.toml
@@ -0,0 +1 @@
+[error] this shouldn't be here
diff --git a/src/test/invalid/text-before-array-separator.toml b/src/test/invalid/text-before-array-separator.toml
new file mode 100644
index 0000000..9b06a39
--- /dev/null
+++ b/src/test/invalid/text-before-array-separator.toml
@@ -0,0 +1,4 @@
+array = [
+ "Is there life before an array separator?" No,
+ "Entry"
+]
diff --git a/src/test/invalid/text-in-array.toml b/src/test/invalid/text-in-array.toml
new file mode 100644
index 0000000..a6a6c42
--- /dev/null
+++ b/src/test/invalid/text-in-array.toml
@@ -0,0 +1,5 @@
+array = [
+ "Entry 1",
+ I don't belong,
+ "Entry 2",
+]
diff --git a/src/test/mod.rs b/src/test/mod.rs
new file mode 100644
index 0000000..6f2c7bd
--- /dev/null
+++ b/src/test/mod.rs
@@ -0,0 +1,2 @@
+mod valid;
+mod invalid;
diff --git a/src/test/valid.rs b/src/test/valid.rs
new file mode 100644
index 0000000..335e908
--- /dev/null
+++ b/src/test/valid.rs
@@ -0,0 +1,163 @@
+extern crate serialize;
+
+use std::num::strconv;
+use std::collections::TreeMap;
+use self::serialize::json;
+
+use {Parser, Value, Table, String, Integer, Float, Boolean, Datetime, Array};
+
+fn to_json(toml: Value) -> json::Json {
+ fn doit(s: &str, json: json::Json) -> json::Json {
+ let mut map = box TreeMap::new();
+ map.insert("type".to_string(), json::String(s.to_string()));
+ map.insert("value".to_string(), json);
+ json::Object(map)
+ }
+ match toml {
+ String(s) => doit("string", json::String(s)),
+ Integer(i) => doit("integer", json::String(i.to_str())),
+ Float(f) => doit("float", json::String({
+ let (bytes, _) =
+ strconv::float_to_str_bytes_common(f, 10, true,
+ strconv::SignNeg,
+ strconv::DigMax(15),
+ strconv::ExpNone,
+ false);
+ let s = String::from_utf8(bytes).unwrap();
+ if s.as_slice().contains(".") {s} else {format!("{}.0", s)}
+ })),
+ Boolean(b) => doit("bool", json::String(b.to_str())),
+ Datetime(s) => doit("datetime", json::String(s)),
+ Array(arr) => {
+ let is_table = match arr.as_slice().head() {
+ Some(&Table(..)) => true,
+ _ => false,
+ };
+ let json = json::List(arr.move_iter().map(to_json).collect());
+ if is_table {json} else {doit("array", json)}
+ }
+ Table(table) => json::Object(box table.move_iter().map(|(k, v)| {
+ (k, to_json(v))
+ }).collect()),
+ }
+}
+
+fn run(toml: &str, json: &str) {
+ let mut p = Parser::new(toml);
+ let table = p.parse();
+ assert!(p.errors.len() == 0, "had_errors: {}",
+ p.errors.iter().map(|e| {
+ (e.desc.clone(), toml.slice(e.lo - 5, e.hi + 5))
+ }).collect::<Vec<(String, &str)>>());
+ assert!(table.is_some());
+ let table = table.unwrap();
+
+ let json = json::from_str(json).unwrap();
+ let toml_json = to_json(Table(table));
+ assert!(json == toml_json,
+ "expected\n{}\ngot\n{}\n",
+ json.to_pretty_str(),
+ toml_json.to_pretty_str());
+}
+
+macro_rules! test( ($name:ident, $toml:expr, $json:expr) => (
+ #[test]
+ fn $name() { run($toml, $json); }
+) )
+
+test!(array_empty,
+ include_str!("valid/array-empty.toml"),
+ include_str!("valid/array-empty.json"))
+test!(array_nospaces,
+ include_str!("valid/array-nospaces.toml"),
+ include_str!("valid/array-nospaces.json"))
+test!(arrays_hetergeneous,
+ include_str!("valid/arrays-hetergeneous.toml"),
+ include_str!("valid/arrays-hetergeneous.json"))
+test!(arrays,
+ include_str!("valid/arrays.toml"),
+ include_str!("valid/arrays.json"))
+test!(arrays_nested,
+ include_str!("valid/arrays-nested.toml"),
+ include_str!("valid/arrays-nested.json"))
+test!(empty,
+ include_str!("valid/empty.toml"),
+ include_str!("valid/empty.json"))
+test!(bool,
+ include_str!("valid/bool.toml"),
+ include_str!("valid/bool.json"))
+test!(datetime,
+ include_str!("valid/datetime.toml"),
+ include_str!("valid/datetime.json"))
+test!(example,
+ include_str!("valid/example.toml"),
+ include_str!("valid/example.json"))
+test!(float,
+ include_str!("valid/float.toml"),
+ include_str!("valid/float.json"))
+test!(implicit_and_explicit_after,
+ include_str!("valid/implicit-and-explicit-after.toml"),
+ include_str!("valid/implicit-and-explicit-after.json"))
+test!(implicit_and_explicit_before,
+ include_str!("valid/implicit-and-explicit-before.toml"),
+ include_str!("valid/implicit-and-explicit-before.json"))
+test!(implicit_groups,
+ include_str!("valid/implicit-groups.toml"),
+ include_str!("valid/implicit-groups.json"))
+test!(integer,
+ include_str!("valid/integer.toml"),
+ include_str!("valid/integer.json"))
+test!(key_equals_nospace,
+ include_str!("valid/key-equals-nospace.toml"),
+ include_str!("valid/key-equals-nospace.json"))
+test!(key_special_chars,
+ include_str!("valid/key-special-chars.toml"),
+ include_str!("valid/key-special-chars.json"))
+test!(key_with_pound,
+ include_str!("valid/key-with-pound.toml"),
+ include_str!("valid/key-with-pound.json"))
+test!(long_float,
+ include_str!("valid/long-float.toml"),
+ include_str!("valid/long-float.json"))
+test!(long_integer,
+ include_str!("valid/long-integer.toml"),
+ include_str!("valid/long-integer.json"))
+test!(string_escapes,
+ include_str!("valid/string-escapes.toml"),
+ include_str!("valid/string-escapes.json"))
+test!(string_simple,
+ include_str!("valid/string-simple.toml"),
+ include_str!("valid/string-simple.json"))
+test!(string_with_pound,
+ include_str!("valid/string-with-pound.toml"),
+ include_str!("valid/string-with-pound.json"))
+test!(table_array_implicit,
+ include_str!("valid/table-array-implicit.toml"),
+ include_str!("valid/table-array-implicit.json"))
+test!(table_array_many,
+ include_str!("valid/table-array-many.toml"),
+ include_str!("valid/table-array-many.json"))
+test!(table_array_nest,
+ include_str!("valid/table-array-nest.toml"),
+ include_str!("valid/table-array-nest.json"))
+test!(table_array_one,
+ include_str!("valid/table-array-one.toml"),
+ include_str!("valid/table-array-one.json"))
+test!(table_empty,
+ include_str!("valid/table-empty.toml"),
+ include_str!("valid/table-empty.json"))
+test!(table_sub_empty,
+ include_str!("valid/table-sub-empty.toml"),
+ include_str!("valid/table-sub-empty.json"))
+test!(table_whitespace,
+ include_str!("valid/table-whitespace.toml"),
+ include_str!("valid/table-whitespace.json"))
+test!(table_with_pound,
+ include_str!("valid/table-with-pound.toml"),
+ include_str!("valid/table-with-pound.json"))
+test!(unicode_escape,
+ include_str!("valid/unicode-escape.toml"),
+ include_str!("valid/unicode-escape.json"))
+test!(unicode_literal,
+ include_str!("valid/unicode-literal.toml"),
+ include_str!("valid/unicode-literal.json"))
diff --git a/src/test/valid/array-empty.json b/src/test/valid/array-empty.json
new file mode 100644
index 0000000..2fbf256
--- /dev/null
+++ b/src/test/valid/array-empty.json
@@ -0,0 +1,11 @@
+{
+ "thevoid": { "type": "array", "value": [
+ {"type": "array", "value": [
+ {"type": "array", "value": [
+ {"type": "array", "value": [
+ {"type": "array", "value": []}
+ ]}
+ ]}
+ ]}
+ ]}
+}
diff --git a/src/test/valid/array-empty.toml b/src/test/valid/array-empty.toml
new file mode 100644
index 0000000..fa58dc6
--- /dev/null
+++ b/src/test/valid/array-empty.toml
@@ -0,0 +1 @@
+thevoid = [[[[[]]]]]
diff --git a/src/test/valid/array-nospaces.json b/src/test/valid/array-nospaces.json
new file mode 100644
index 0000000..1833d61
--- /dev/null
+++ b/src/test/valid/array-nospaces.json
@@ -0,0 +1,10 @@
+{
+ "ints": {
+ "type": "array",
+ "value": [
+ {"type": "integer", "value": "1"},
+ {"type": "integer", "value": "2"},
+ {"type": "integer", "value": "3"}
+ ]
+ }
+}
diff --git a/src/test/valid/array-nospaces.toml b/src/test/valid/array-nospaces.toml
new file mode 100644
index 0000000..6618936
--- /dev/null
+++ b/src/test/valid/array-nospaces.toml
@@ -0,0 +1 @@
+ints = [1,2,3]
diff --git a/src/test/valid/arrays-hetergeneous.json b/src/test/valid/arrays-hetergeneous.json
new file mode 100644
index 0000000..e703739
--- /dev/null
+++ b/src/test/valid/arrays-hetergeneous.json
@@ -0,0 +1,19 @@
+{
+ "mixed": {
+ "type": "array",
+ "value": [
+ {"type": "array", "value": [
+ {"type": "integer", "value": "1"},
+ {"type": "integer", "value": "2"}
+ ]},
+ {"type": "array", "value": [
+ {"type": "string", "value": "a"},
+ {"type": "string", "value": "b"}
+ ]},
+ {"type": "array", "value": [
+ {"type": "float", "value": "1.0"},
+ {"type": "float", "value": "2.0"}
+ ]}
+ ]
+ }
+}
diff --git a/src/test/valid/arrays-hetergeneous.toml b/src/test/valid/arrays-hetergeneous.toml
new file mode 100644
index 0000000..91fcbdf
--- /dev/null
+++ b/src/test/valid/arrays-hetergeneous.toml
@@ -0,0 +1 @@
+mixed = [[1, 2], ["a", "b"], [1.0, 2.0]]
diff --git a/src/test/valid/arrays-nested.json b/src/test/valid/arrays-nested.json
new file mode 100644
index 0000000..d21920c
--- /dev/null
+++ b/src/test/valid/arrays-nested.json
@@ -0,0 +1,13 @@
+{
+ "nest": {
+ "type": "array",
+ "value": [
+ {"type": "array", "value": [
+ {"type": "string", "value": "a"}
+ ]},
+ {"type": "array", "value": [
+ {"type": "string", "value": "b"}
+ ]}
+ ]
+ }
+}
diff --git a/src/test/valid/arrays-nested.toml b/src/test/valid/arrays-nested.toml
new file mode 100644
index 0000000..ce33022
--- /dev/null
+++ b/src/test/valid/arrays-nested.toml
@@ -0,0 +1 @@
+nest = [["a"], ["b"]]
diff --git a/src/test/valid/arrays.json b/src/test/valid/arrays.json
new file mode 100644
index 0000000..4d16d8a
--- /dev/null
+++ b/src/test/valid/arrays.json
@@ -0,0 +1,34 @@
+{
+ "ints": {
+ "type": "array",
+ "value": [
+ {"type": "integer", "value": "1"},
+ {"type": "integer", "value": "2"},
+ {"type": "integer", "value": "3"}
+ ]
+ },
+ "floats": {
+ "type": "array",
+ "value": [
+ {"type": "float", "value": "1.0"},
+ {"type": "float", "value": "2.0"},
+ {"type": "float", "value": "3.0"}
+ ]
+ },
+ "strings": {
+ "type": "array",
+ "value": [
+ {"type": "string", "value": "a"},
+ {"type": "string", "value": "b"},
+ {"type": "string", "value": "c"}
+ ]
+ },
+ "dates": {
+ "type": "array",
+ "value": [
+ {"type": "datetime", "value": "1987-07-05T17:45:00Z"},
+ {"type": "datetime", "value": "1979-05-27T07:32:00Z"},
+ {"type": "datetime", "value": "2006-06-01T11:00:00Z"}
+ ]
+ }
+}
diff --git a/src/test/valid/arrays.toml b/src/test/valid/arrays.toml
new file mode 100644
index 0000000..6d6440d
--- /dev/null
+++ b/src/test/valid/arrays.toml
@@ -0,0 +1,9 @@
+ints = [1, 2, 3]
+floats = [1.0, 2.0, 3.0]
+strings = ["a", "b", "c"]
+dates = [
+ 1987-07-05T17:45:00Z,
+ 1979-05-27T07:32:00Z,
+ 2006-06-01T11:00:00Z,
+]
+
diff --git a/src/test/valid/bool.json b/src/test/valid/bool.json
new file mode 100644
index 0000000..ae368e9
--- /dev/null
+++ b/src/test/valid/bool.json
@@ -0,0 +1,4 @@
+{
+ "f": {"type": "bool", "value": "false"},
+ "t": {"type": "bool", "value": "true"}
+}
diff --git a/src/test/valid/bool.toml b/src/test/valid/bool.toml
new file mode 100644
index 0000000..a8a829b
--- /dev/null
+++ b/src/test/valid/bool.toml
@@ -0,0 +1,2 @@
+t = true
+f = false
diff --git a/src/test/valid/comments-everywhere.json b/src/test/valid/comments-everywhere.json
new file mode 100644
index 0000000..e69a2e9
--- /dev/null
+++ b/src/test/valid/comments-everywhere.json
@@ -0,0 +1,12 @@
+{
+ "group": {
+ "answer": {"type": "integer", "value": "42"},
+ "more": {
+ "type": "array",
+ "value": [
+ {"type": "integer", "value": "42"},
+ {"type": "integer", "value": "42"}
+ ]
+ }
+ }
+}
diff --git a/src/test/valid/comments-everywhere.toml b/src/test/valid/comments-everywhere.toml
new file mode 100644
index 0000000..3dca74c
--- /dev/null
+++ b/src/test/valid/comments-everywhere.toml
@@ -0,0 +1,24 @@
+# Top comment.
+ # Top comment.
+# Top comment.
+
+# [no-extraneous-groups-please]
+
+[group] # Comment
+answer = 42 # Comment
+# no-extraneous-keys-please = 999
+# Inbetween comment.
+more = [ # Comment
+ # What about multiple # comments?
+ # Can you handle it?
+ #
+ # Evil.
+# Evil.
+ 42, 42, # Comments within arrays are fun.
+ # What about multiple # comments?
+ # Can you handle it?
+ #
+ # Evil.
+# Evil.
+# ] Did I fool you?
+] # Hopefully not.
diff --git a/src/test/valid/datetime.json b/src/test/valid/datetime.json
new file mode 100644
index 0000000..2ca93ce
--- /dev/null
+++ b/src/test/valid/datetime.json
@@ -0,0 +1,3 @@
+{
+ "bestdayever": {"type": "datetime", "value": "1987-07-05T17:45:00Z"}
+}
diff --git a/src/test/valid/datetime.toml b/src/test/valid/datetime.toml
new file mode 100644
index 0000000..2e99340
--- /dev/null
+++ b/src/test/valid/datetime.toml
@@ -0,0 +1 @@
+bestdayever = 1987-07-05T17:45:00Z
diff --git a/src/test/valid/empty.json b/src/test/valid/empty.json
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/src/test/valid/empty.json
@@ -0,0 +1 @@
+{}
diff --git a/src/test/valid/empty.toml b/src/test/valid/empty.toml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/test/valid/empty.toml
diff --git a/src/test/valid/example.json b/src/test/valid/example.json
new file mode 100644
index 0000000..48aa907
--- /dev/null
+++ b/src/test/valid/example.json
@@ -0,0 +1,14 @@
+{
+ "best-day-ever": {"type": "datetime", "value": "1987-07-05T17:45:00Z"},
+ "numtheory": {
+ "boring": {"type": "bool", "value": "false"},
+ "perfection": {
+ "type": "array",
+ "value": [
+ {"type": "integer", "value": "6"},
+ {"type": "integer", "value": "28"},
+ {"type": "integer", "value": "496"}
+ ]
+ }
+ }
+}
diff --git a/src/test/valid/example.toml b/src/test/valid/example.toml
new file mode 100644
index 0000000..8cb02e0
--- /dev/null
+++ b/src/test/valid/example.toml
@@ -0,0 +1,5 @@
+best-day-ever = 1987-07-05T17:45:00Z
+
+[numtheory]
+boring = false
+perfection = [6, 28, 496]
diff --git a/src/test/valid/float.json b/src/test/valid/float.json
new file mode 100644
index 0000000..b8a2e97
--- /dev/null
+++ b/src/test/valid/float.json
@@ -0,0 +1,4 @@
+{
+ "pi": {"type": "float", "value": "3.14"},
+ "negpi": {"type": "float", "value": "-3.14"}
+}
diff --git a/src/test/valid/float.toml b/src/test/valid/float.toml
new file mode 100644
index 0000000..7c528d2
--- /dev/null
+++ b/src/test/valid/float.toml
@@ -0,0 +1,2 @@
+pi = 3.14
+negpi = -3.14
diff --git a/src/test/valid/implicit-and-explicit-after.json b/src/test/valid/implicit-and-explicit-after.json
new file mode 100644
index 0000000..374bd09
--- /dev/null
+++ b/src/test/valid/implicit-and-explicit-after.json
@@ -0,0 +1,10 @@
+{
+ "a": {
+ "better": {"type": "integer", "value": "43"},
+ "b": {
+ "c": {
+ "answer": {"type": "integer", "value": "42"}
+ }
+ }
+ }
+}
diff --git a/src/test/valid/implicit-and-explicit-after.toml b/src/test/valid/implicit-and-explicit-after.toml
new file mode 100644
index 0000000..c0e8865
--- /dev/null
+++ b/src/test/valid/implicit-and-explicit-after.toml
@@ -0,0 +1,5 @@
+[a.b.c]
+answer = 42
+
+[a]
+better = 43
diff --git a/src/test/valid/implicit-and-explicit-before.json b/src/test/valid/implicit-and-explicit-before.json
new file mode 100644
index 0000000..374bd09
--- /dev/null
+++ b/src/test/valid/implicit-and-explicit-before.json
@@ -0,0 +1,10 @@
+{
+ "a": {
+ "better": {"type": "integer", "value": "43"},
+ "b": {
+ "c": {
+ "answer": {"type": "integer", "value": "42"}
+ }
+ }
+ }
+}
diff --git a/src/test/valid/implicit-and-explicit-before.toml b/src/test/valid/implicit-and-explicit-before.toml
new file mode 100644
index 0000000..eee68ff
--- /dev/null
+++ b/src/test/valid/implicit-and-explicit-before.toml
@@ -0,0 +1,5 @@
+[a]
+better = 43
+
+[a.b.c]
+answer = 42
diff --git a/src/test/valid/implicit-groups.json b/src/test/valid/implicit-groups.json
new file mode 100644
index 0000000..fbae7fc
--- /dev/null
+++ b/src/test/valid/implicit-groups.json
@@ -0,0 +1,9 @@
+{
+ "a": {
+ "b": {
+ "c": {
+ "answer": {"type": "integer", "value": "42"}
+ }
+ }
+ }
+}
diff --git a/src/test/valid/implicit-groups.toml b/src/test/valid/implicit-groups.toml
new file mode 100644
index 0000000..b6333e4
--- /dev/null
+++ b/src/test/valid/implicit-groups.toml
@@ -0,0 +1,2 @@
+[a.b.c]
+answer = 42
diff --git a/src/test/valid/integer.json b/src/test/valid/integer.json
new file mode 100644
index 0000000..61985a1
--- /dev/null
+++ b/src/test/valid/integer.json
@@ -0,0 +1,4 @@
+{
+ "answer": {"type": "integer", "value": "42"},
+ "neganswer": {"type": "integer", "value": "-42"}
+}
diff --git a/src/test/valid/integer.toml b/src/test/valid/integer.toml
new file mode 100644
index 0000000..c4f6297
--- /dev/null
+++ b/src/test/valid/integer.toml
@@ -0,0 +1,2 @@
+answer = 42
+neganswer = -42
diff --git a/src/test/valid/key-equals-nospace.json b/src/test/valid/key-equals-nospace.json
new file mode 100644
index 0000000..1f8709a
--- /dev/null
+++ b/src/test/valid/key-equals-nospace.json
@@ -0,0 +1,3 @@
+{
+ "answer": {"type": "integer", "value": "42"}
+}
diff --git a/src/test/valid/key-equals-nospace.toml b/src/test/valid/key-equals-nospace.toml
new file mode 100644
index 0000000..560901c
--- /dev/null
+++ b/src/test/valid/key-equals-nospace.toml
@@ -0,0 +1 @@
+answer=42
diff --git a/src/test/valid/key-special-chars.json b/src/test/valid/key-special-chars.json
new file mode 100644
index 0000000..6550ebd
--- /dev/null
+++ b/src/test/valid/key-special-chars.json
@@ -0,0 +1,5 @@
+{
+ "~!@#$^&*()_+-`1234567890[]\\|/?><.,;:'": {
+ "type": "integer", "value": "1"
+ }
+}
diff --git a/src/test/valid/key-special-chars.toml b/src/test/valid/key-special-chars.toml
new file mode 100644
index 0000000..8b3fc51
--- /dev/null
+++ b/src/test/valid/key-special-chars.toml
@@ -0,0 +1 @@
+~!@#$^&*()_+-`1234567890[]\|/?><.,;:' = 1
diff --git a/src/test/valid/key-with-pound.json b/src/test/valid/key-with-pound.json
new file mode 100644
index 0000000..ee39e1d
--- /dev/null
+++ b/src/test/valid/key-with-pound.json
@@ -0,0 +1,3 @@
+{
+ "key#name": {"type": "integer", "value": "5"}
+}
diff --git a/src/test/valid/key-with-pound.toml b/src/test/valid/key-with-pound.toml
new file mode 100644
index 0000000..1c54f53
--- /dev/null
+++ b/src/test/valid/key-with-pound.toml
@@ -0,0 +1 @@
+key#name = 5
diff --git a/src/test/valid/long-float.json b/src/test/valid/long-float.json
new file mode 100644
index 0000000..8ceed47
--- /dev/null
+++ b/src/test/valid/long-float.json
@@ -0,0 +1,4 @@
+{
+ "longpi": {"type": "float", "value": "3.141592653589793"},
+ "neglongpi": {"type": "float", "value": "-3.141592653589793"}
+}
diff --git a/src/test/valid/long-float.toml b/src/test/valid/long-float.toml
new file mode 100644
index 0000000..9558ae4
--- /dev/null
+++ b/src/test/valid/long-float.toml
@@ -0,0 +1,2 @@
+longpi = 3.141592653589793
+neglongpi = -3.141592653589793
diff --git a/src/test/valid/long-integer.json b/src/test/valid/long-integer.json
new file mode 100644
index 0000000..16c331e
--- /dev/null
+++ b/src/test/valid/long-integer.json
@@ -0,0 +1,4 @@
+{
+ "answer": {"type": "integer", "value": "9223372036854775807"},
+ "neganswer": {"type": "integer", "value": "-9223372036854775808"}
+}
diff --git a/src/test/valid/long-integer.toml b/src/test/valid/long-integer.toml
new file mode 100644
index 0000000..424a13a
--- /dev/null
+++ b/src/test/valid/long-integer.toml
@@ -0,0 +1,2 @@
+answer = 9223372036854775807
+neganswer = -9223372036854775808
diff --git a/src/test/valid/string-escapes.json b/src/test/valid/string-escapes.json
new file mode 100644
index 0000000..ca71d30
--- /dev/null
+++ b/src/test/valid/string-escapes.json
@@ -0,0 +1,34 @@
+{
+ "backspace": {
+ "type": "string",
+ "value": "This string has a \u0008 backspace character."
+ },
+ "tab": {
+ "type": "string",
+ "value": "This string has a \u0009 tab character."
+ },
+ "newline": {
+ "type": "string",
+ "value": "This string has a \u000A new line character."
+ },
+ "formfeed": {
+ "type": "string",
+ "value": "This string has a \u000C form feed character."
+ },
+ "carriage": {
+ "type": "string",
+ "value": "This string has a \u000D carriage return character."
+ },
+ "quote": {
+ "type": "string",
+ "value": "This string has a \u0022 quote character."
+ },
+ "slash": {
+ "type": "string",
+ "value": "This string has a \u002F slash character."
+ },
+ "backslash": {
+ "type": "string",
+ "value": "This string has a \u005C backslash character."
+ }
+}
diff --git a/src/test/valid/string-escapes.toml b/src/test/valid/string-escapes.toml
new file mode 100644
index 0000000..2d64500
--- /dev/null
+++ b/src/test/valid/string-escapes.toml
@@ -0,0 +1,8 @@
+backspace = "This string has a \b backspace character."
+tab = "This string has a \t tab character."
+newline = "This string has a \n new line character."
+formfeed = "This string has a \f form feed character."
+carriage = "This string has a \r carriage return character."
+quote = "This string has a \" quote character."
+slash = "This string has a \/ slash character."
+backslash = "This string has a \\ backslash character."
diff --git a/src/test/valid/string-simple.json b/src/test/valid/string-simple.json
new file mode 100644
index 0000000..2e05f99
--- /dev/null
+++ b/src/test/valid/string-simple.json
@@ -0,0 +1,6 @@
+{
+ "answer": {
+ "type": "string",
+ "value": "You are not drinking enough whisky."
+ }
+}
diff --git a/src/test/valid/string-simple.toml b/src/test/valid/string-simple.toml
new file mode 100644
index 0000000..e17ade6
--- /dev/null
+++ b/src/test/valid/string-simple.toml
@@ -0,0 +1 @@
+answer = "You are not drinking enough whisky."
diff --git a/src/test/valid/string-with-pound.json b/src/test/valid/string-with-pound.json
new file mode 100644
index 0000000..33cdc9c
--- /dev/null
+++ b/src/test/valid/string-with-pound.json
@@ -0,0 +1,7 @@
+{
+ "pound": {"type": "string", "value": "We see no # comments here."},
+ "poundcomment": {
+ "type": "string",
+ "value": "But there are # some comments here."
+ }
+}
diff --git a/src/test/valid/string-with-pound.toml b/src/test/valid/string-with-pound.toml
new file mode 100644
index 0000000..5fd8746
--- /dev/null
+++ b/src/test/valid/string-with-pound.toml
@@ -0,0 +1,2 @@
+pound = "We see no # comments here."
+poundcomment = "But there are # some comments here." # Did I # mess you up?
diff --git a/src/test/valid/table-array-implicit.json b/src/test/valid/table-array-implicit.json
new file mode 100644
index 0000000..32e4640
--- /dev/null
+++ b/src/test/valid/table-array-implicit.json
@@ -0,0 +1,7 @@
+{
+ "albums": {
+ "songs": [
+ {"name": {"type": "string", "value": "Glory Days"}}
+ ]
+ }
+}
diff --git a/src/test/valid/table-array-implicit.toml b/src/test/valid/table-array-implicit.toml
new file mode 100644
index 0000000..3157ac9
--- /dev/null
+++ b/src/test/valid/table-array-implicit.toml
@@ -0,0 +1,2 @@
+[[albums.songs]]
+name = "Glory Days"
diff --git a/src/test/valid/table-array-many.json b/src/test/valid/table-array-many.json
new file mode 100644
index 0000000..84df2da
--- /dev/null
+++ b/src/test/valid/table-array-many.json
@@ -0,0 +1,16 @@
+{
+ "people": [
+ {
+ "first_name": {"type": "string", "value": "Bruce"},
+ "last_name": {"type": "string", "value": "Springsteen"}
+ },
+ {
+ "first_name": {"type": "string", "value": "Eric"},
+ "last_name": {"type": "string", "value": "Clapton"}
+ },
+ {
+ "first_name": {"type": "string", "value": "Bob"},
+ "last_name": {"type": "string", "value": "Seger"}
+ }
+ ]
+}
diff --git a/src/test/valid/table-array-many.toml b/src/test/valid/table-array-many.toml
new file mode 100644
index 0000000..46062be
--- /dev/null
+++ b/src/test/valid/table-array-many.toml
@@ -0,0 +1,11 @@
+[[people]]
+first_name = "Bruce"
+last_name = "Springsteen"
+
+[[people]]
+first_name = "Eric"
+last_name = "Clapton"
+
+[[people]]
+first_name = "Bob"
+last_name = "Seger"
diff --git a/src/test/valid/table-array-nest.json b/src/test/valid/table-array-nest.json
new file mode 100644
index 0000000..c117afa
--- /dev/null
+++ b/src/test/valid/table-array-nest.json
@@ -0,0 +1,18 @@
+{
+ "albums": [
+ {
+ "name": {"type": "string", "value": "Born to Run"},
+ "songs": [
+ {"name": {"type": "string", "value": "Jungleland"}},
+ {"name": {"type": "string", "value": "Meeting Across the River"}}
+ ]
+ },
+ {
+ "name": {"type": "string", "value": "Born in the USA"},
+ "songs": [
+ {"name": {"type": "string", "value": "Glory Days"}},
+ {"name": {"type": "string", "value": "Dancing in the Dark"}}
+ ]
+ }
+ ]
+}
diff --git a/src/test/valid/table-array-nest.toml b/src/test/valid/table-array-nest.toml
new file mode 100644
index 0000000..d659a3d
--- /dev/null
+++ b/src/test/valid/table-array-nest.toml
@@ -0,0 +1,17 @@
+[[albums]]
+name = "Born to Run"
+
+ [[albums.songs]]
+ name = "Jungleland"
+
+ [[albums.songs]]
+ name = "Meeting Across the River"
+
+[[albums]]
+name = "Born in the USA"
+
+ [[albums.songs]]
+ name = "Glory Days"
+
+ [[albums.songs]]
+ name = "Dancing in the Dark"
diff --git a/src/test/valid/table-array-one.json b/src/test/valid/table-array-one.json
new file mode 100644
index 0000000..d75faae
--- /dev/null
+++ b/src/test/valid/table-array-one.json
@@ -0,0 +1,8 @@
+{
+ "people": [
+ {
+ "first_name": {"type": "string", "value": "Bruce"},
+ "last_name": {"type": "string", "value": "Springsteen"}
+ }
+ ]
+}
diff --git a/src/test/valid/table-array-one.toml b/src/test/valid/table-array-one.toml
new file mode 100644
index 0000000..cd7e1b6
--- /dev/null
+++ b/src/test/valid/table-array-one.toml
@@ -0,0 +1,3 @@
+[[people]]
+first_name = "Bruce"
+last_name = "Springsteen"
diff --git a/src/test/valid/table-empty.json b/src/test/valid/table-empty.json
new file mode 100644
index 0000000..6f3873a
--- /dev/null
+++ b/src/test/valid/table-empty.json
@@ -0,0 +1,3 @@
+{
+ "a": {}
+}
diff --git a/src/test/valid/table-empty.toml b/src/test/valid/table-empty.toml
new file mode 100644
index 0000000..8bb6a0a
--- /dev/null
+++ b/src/test/valid/table-empty.toml
@@ -0,0 +1 @@
+[a]
diff --git a/src/test/valid/table-sub-empty.json b/src/test/valid/table-sub-empty.json
new file mode 100644
index 0000000..9787770
--- /dev/null
+++ b/src/test/valid/table-sub-empty.json
@@ -0,0 +1,3 @@
+{
+ "a": { "b": {} }
+}
diff --git a/src/test/valid/table-sub-empty.toml b/src/test/valid/table-sub-empty.toml
new file mode 100644
index 0000000..70b7fe1
--- /dev/null
+++ b/src/test/valid/table-sub-empty.toml
@@ -0,0 +1,2 @@
+[a]
+[a.b]
diff --git a/src/test/valid/table-whitespace.json b/src/test/valid/table-whitespace.json
new file mode 100644
index 0000000..3a73ec8
--- /dev/null
+++ b/src/test/valid/table-whitespace.json
@@ -0,0 +1,3 @@
+{
+ "valid key": {}
+}
diff --git a/src/test/valid/table-whitespace.toml b/src/test/valid/table-whitespace.toml
new file mode 100644
index 0000000..798756c
--- /dev/null
+++ b/src/test/valid/table-whitespace.toml
@@ -0,0 +1 @@
+[valid key]
diff --git a/src/test/valid/table-with-pound.json b/src/test/valid/table-with-pound.json
new file mode 100644
index 0000000..5e594e4
--- /dev/null
+++ b/src/test/valid/table-with-pound.json
@@ -0,0 +1,5 @@
+{
+ "key#group": {
+ "answer": {"type": "integer", "value": "42"}
+ }
+}
diff --git a/src/test/valid/table-with-pound.toml b/src/test/valid/table-with-pound.toml
new file mode 100644
index 0000000..e7b777e
--- /dev/null
+++ b/src/test/valid/table-with-pound.toml
@@ -0,0 +1,2 @@
+[key#group]
+answer = 42
diff --git a/src/test/valid/unicode-escape.json b/src/test/valid/unicode-escape.json
new file mode 100644
index 0000000..deda62c
--- /dev/null
+++ b/src/test/valid/unicode-escape.json
@@ -0,0 +1,3 @@
+{
+ "answer": {"type": "string", "value": "\u03B4"}
+}
diff --git a/src/test/valid/unicode-escape.toml b/src/test/valid/unicode-escape.toml
new file mode 100644
index 0000000..057ce15
--- /dev/null
+++ b/src/test/valid/unicode-escape.toml
@@ -0,0 +1 @@
+answer = "\u03B4"
diff --git a/src/test/valid/unicode-literal.json b/src/test/valid/unicode-literal.json
new file mode 100644
index 0000000..00aa2f8
--- /dev/null
+++ b/src/test/valid/unicode-literal.json
@@ -0,0 +1,3 @@
+{
+ "answer": {"type": "string", "value": "δ"}
+}
diff --git a/src/test/valid/unicode-literal.toml b/src/test/valid/unicode-literal.toml
new file mode 100644
index 0000000..c65723c
--- /dev/null
+++ b/src/test/valid/unicode-literal.toml
@@ -0,0 +1 @@
+answer = "δ"