Integrated multiple file-based test suites (BurntSushi, iarna and my own) into the unit tests. BurntSushi's tests are also still supported using the test interface implementation from cmd/burntsushi-tester.
This commit is contained in:
parent
ec3a47da8d
commit
7227fdcb93
2
FIXME
2
FIXME
|
@ -1,2 +0,0 @@
|
||||||
key-no-eol I do accept "key1=1 key2=1". The spec does not deny that.
|
|
||||||
|
|
11
Makefile
11
Makefile
|
@ -1,11 +1,8 @@
|
||||||
all: build
|
|
||||||
|
|
||||||
build:
|
|
||||||
@(cd cmd/toml-test-decoder; go build)
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@(cd ast; go test | grep -v ^PASS)
|
@(cd ast; go test | grep -v ^PASS)
|
||||||
@(cd parse; go test | grep -v ^PASS)
|
@(cd parse; go test | grep -v ^PASS)
|
||||||
|
|
||||||
sushi-test: build
|
test-sushi:
|
||||||
@(cd cmd/toml-test-decoder; go build; ${GOPATH}/bin/toml-test ./toml-test-decoder)
|
@(cd cmd/burntsushi-tester; go build)
|
||||||
|
@echo -n "BurntSushi tests: "
|
||||||
|
@(cd cmd/burntsushi-tester && ${GOPATH}/bin/toml-test ./burntsushi-tester)
|
||||||
|
|
|
@ -1,86 +1,61 @@
|
||||||
// Command toml-test-decoder satisfies BurntSushi's toml-test interface for testing
|
package ast
|
||||||
// TOML decoders. Namely, it accepts TOML on stdin and outputs JSON on stdout.
|
|
||||||
// See: https://github.com/BurntSushi/toml-test
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.makaay.nl/mauricem/go-toml/ast"
|
|
||||||
"git.makaay.nl/mauricem/go-toml/parse"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
// MakeSushi generates a JSON string for an ast Table, which is compatible
|
||||||
log.SetFlags(0)
|
// with BurntSushi's TOML testing tool (https://github.com/BurntSushi/toml-test)
|
||||||
|
func (t Table) MakeSushi() string {
|
||||||
flag.Usage = usage
|
return MakeSushi(NewValue(TypeTable, t))
|
||||||
flag.Parse()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func usage() {
|
// MakeSushi generates a JSON string for an ast Value, which is compatible
|
||||||
log.Printf("Usage: %s < toml-file\n", path.Base(os.Args[0]))
|
// with BurntSushi's TOML testing tool (https://github.com/BurntSushi/toml-test)
|
||||||
flag.PrintDefaults()
|
func MakeSushi(value *Value) string {
|
||||||
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if flag.NArg() != 0 {
|
|
||||||
flag.Usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
toml, err := parse.Run(os.Stdin)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error decoding TOML: %s", err)
|
|
||||||
} else {
|
|
||||||
sushi := makeSushi(ast.NewValue(ast.TypeTable, toml))
|
|
||||||
fmt.Println(sushi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeSushi(value *ast.Value) string {
|
|
||||||
switch value.Type {
|
switch value.Type {
|
||||||
case ast.TypeString:
|
case TypeString:
|
||||||
return renderValue("string", value.Data[0].(string))
|
return renderValue("string", value.Data[0].(string))
|
||||||
case ast.TypeInteger:
|
case TypeInteger:
|
||||||
return renderValue("integer", fmt.Sprintf("%d", value.Data[0].(int64)))
|
return renderValue("integer", fmt.Sprintf("%d", value.Data[0].(int64)))
|
||||||
case ast.TypeFloat:
|
case TypeFloat:
|
||||||
return renderValue("float", fmt.Sprintf("%v", value.Data[0].(float64)))
|
return renderValue("float", fmt.Sprintf("%v", value.Data[0].(float64)))
|
||||||
case ast.TypeBool:
|
case TypeBool:
|
||||||
return renderValue("bool", fmt.Sprintf("%t", value.Data[0].(bool)))
|
return renderValue("bool", fmt.Sprintf("%t", value.Data[0].(bool)))
|
||||||
case ast.TypeOffsetDateTime:
|
case TypeOffsetDateTime:
|
||||||
return renderValue("datetime", value.Data[0].(time.Time).Format(time.RFC3339Nano))
|
return renderValue("datetime", value.Data[0].(time.Time).Format(time.RFC3339Nano))
|
||||||
case ast.TypeLocalDateTime:
|
case TypeLocalDateTime:
|
||||||
return renderValue("local_datetime", value.Data[0].(time.Time).Format("2006-01-02 15:04:05.999999999"))
|
return renderValue("local_datetime", value.Data[0].(time.Time).Format("2006-01-02 15:04:05.999999999"))
|
||||||
case ast.TypeLocalDate:
|
case TypeLocalDate:
|
||||||
return renderValue("local_date", value.Data[0].(time.Time).Format("2006-01-02"))
|
return renderValue("local_date", value.Data[0].(time.Time).Format("2006-01-02"))
|
||||||
case ast.TypeLocalTime:
|
case TypeLocalTime:
|
||||||
return renderValue("local_time", value.Data[0].(time.Time).Format("15:04:05.999999999"))
|
return renderValue("local_time", value.Data[0].(time.Time).Format("15:04:05.999999999"))
|
||||||
case ast.TypeArrayOfTables:
|
case TypeArrayOfTables:
|
||||||
fallthrough
|
fallthrough
|
||||||
case ast.TypeArray:
|
case TypeArray:
|
||||||
|
// BurntSushi's tests sees [ {inline: "table"}, {array: "definitions"} ]
|
||||||
|
// as an array of tables, so here we accomodate for that situation
|
||||||
|
// by checking for that case and render such inline array definition
|
||||||
|
// as if it were an [[array.of.tables]].
|
||||||
values := make([]string, len(value.Data))
|
values := make([]string, len(value.Data))
|
||||||
isArrayOfTables := false
|
isArrayOfTables := false
|
||||||
for i, value := range value.Data {
|
for i, value := range value.Data {
|
||||||
isArrayOfTables = value.(*ast.Value).Type == ast.TypeTable
|
isArrayOfTables = value.(*Value).Type == TypeTable
|
||||||
values[i] = makeSushi(value.(*ast.Value))
|
values[i] = MakeSushi(value.(*Value))
|
||||||
}
|
}
|
||||||
if isArrayOfTables {
|
if isArrayOfTables {
|
||||||
return fmt.Sprintf("[%s]", strings.Join(values, ", "))
|
return fmt.Sprintf("[%s]", strings.Join(values, ", "))
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf(`{"type": "array", "value": [%s]}`, strings.Join(values, ", "))
|
return fmt.Sprintf(`{"type": "array", "value": [%s]}`, strings.Join(values, ", "))
|
||||||
}
|
}
|
||||||
case ast.TypeImplicitTable:
|
case TypeImplicitTable:
|
||||||
fallthrough
|
fallthrough
|
||||||
case ast.TypeTable:
|
case TypeTable:
|
||||||
pairs := value.Data[0].(ast.Table)
|
pairs := value.Data[0].(Table)
|
||||||
keys := make([]string, len(pairs))
|
keys := make([]string, len(pairs))
|
||||||
i := 0
|
i := 0
|
||||||
for k := range pairs {
|
for k := range pairs {
|
||||||
|
@ -90,7 +65,7 @@ func makeSushi(value *ast.Value) string {
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
values := make([]string, len(pairs))
|
values := make([]string, len(pairs))
|
||||||
for i, k := range keys {
|
for i, k := range keys {
|
||||||
values[i] = fmt.Sprintf("%q: %s", k, makeSushi(pairs[k]))
|
values[i] = fmt.Sprintf("%q: %s", k, MakeSushi(pairs[k]))
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("{%s}", strings.Join(values, ", "))
|
return fmt.Sprintf("{%s}", strings.Join(values, ", "))
|
||||||
default:
|
default:
|
||||||
|
@ -99,5 +74,13 @@ func makeSushi(value *ast.Value) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderValue(t string, v string) string {
|
func renderValue(t string, v string) string {
|
||||||
return fmt.Sprintf("{%q: %q, %q: %q}", "type", t, "value", v)
|
return fmt.Sprintf("{%q: %q, %q: %s}", "type", t, "value", toJSON(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
func toJSON(s string) string {
|
||||||
|
j, err := json.Marshal(s)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("unable to JSON encode %q: %s", s, err))
|
||||||
|
}
|
||||||
|
return string(j)
|
||||||
}
|
}
|
Binary file not shown.
|
@ -0,0 +1,41 @@
|
||||||
|
// Command burntsushi-tester satisfies BurntSushi's toml-test interface for testing
|
||||||
|
// TOML decoders. Namely, it accepts TOML on stdin and outputs JSON on stdout.
|
||||||
|
// See: https://github.com/BurntSushi/toml-test
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"git.makaay.nl/mauricem/go-toml/parse"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
log.SetFlags(0)
|
||||||
|
|
||||||
|
flag.Usage = usage
|
||||||
|
flag.Parse()
|
||||||
|
}
|
||||||
|
|
||||||
|
func usage() {
|
||||||
|
log.Printf("Usage: %s < <path to TOML-file>\n", path.Base(os.Args[0]))
|
||||||
|
flag.PrintDefaults()
|
||||||
|
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if flag.NArg() != 0 {
|
||||||
|
flag.Usage()
|
||||||
|
}
|
||||||
|
|
||||||
|
toml, err := parse.Run(os.Stdin)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error decoding TOML: %s", err)
|
||||||
|
} else {
|
||||||
|
fmt.Println(toml.MakeSushi())
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
## Test suites
|
||||||
|
|
||||||
|
This folder holds test suites for testing the TOML parser.
|
||||||
|
Besides tests that I defined myself, there are also tests that were imported
|
||||||
|
from other test suites:
|
||||||
|
|
||||||
|
* https://github.com/BurntSushi/toml-test/tree/master/tests
|
||||||
|
* https://github.com/iarna/toml-spec-tests
|
||||||
|
|
||||||
|
In only used the .toml files from these test sets and created my own .json
|
||||||
|
files. They are compatible with the BurntSushi's test format.
|
|
@ -0,0 +1 @@
|
||||||
|
arrays-and-ints = [1, ["Arrays are not integers."]]
|
|
@ -0,0 +1 @@
|
||||||
|
ints-and-floats = [1, 1.1]
|
|
@ -0,0 +1 @@
|
||||||
|
strings-and-ints = ["hi", 42]
|
|
@ -0,0 +1 @@
|
||||||
|
no-leads = 1987-7-05T17:45:00Z
|
|
@ -0,0 +1 @@
|
||||||
|
no-secs = 1987-07-05T17:45Z
|
|
@ -0,0 +1 @@
|
||||||
|
no-t = 1987-07-0517:45:00Z
|
|
@ -0,0 +1 @@
|
||||||
|
with-milli = 1987-07-5T17:45:00.12Z
|
|
@ -0,0 +1,5 @@
|
||||||
|
[fruit]
|
||||||
|
type = "apple"
|
||||||
|
|
||||||
|
[fruit.type]
|
||||||
|
apple = "yes"
|
|
@ -0,0 +1,2 @@
|
||||||
|
dupe = false
|
||||||
|
dupe = true
|
|
@ -0,0 +1,2 @@
|
||||||
|
[a]
|
||||||
|
[a]
|
|
@ -0,0 +1 @@
|
||||||
|
[naughty..naughty]
|
|
@ -0,0 +1 @@
|
||||||
|
[]
|
|
@ -0,0 +1 @@
|
||||||
|
leading-zero = -03.14
|
|
@ -0,0 +1 @@
|
||||||
|
leading-zero = +03.14
|
|
@ -0,0 +1 @@
|
||||||
|
leading-zero = 03.14
|
|
@ -0,0 +1,2 @@
|
||||||
|
answer = .12345
|
||||||
|
neganswer = -.12345
|
|
@ -0,0 +1,2 @@
|
||||||
|
answer = 1.
|
||||||
|
neganswer = -1.
|
|
@ -0,0 +1 @@
|
||||||
|
bad = 1._2
|
|
@ -0,0 +1 @@
|
||||||
|
bad = 1.2_
|
|
@ -0,0 +1 @@
|
||||||
|
bad = 1_.2
|
|
@ -0,0 +1 @@
|
||||||
|
bad = _1.2
|
|
@ -0,0 +1,2 @@
|
||||||
|
simple = { a = 1
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
leading-zero = -012
|
|
@ -0,0 +1 @@
|
||||||
|
leading-zero = +012
|
|
@ -0,0 +1 @@
|
||||||
|
leading-zero = 012
|
|
@ -0,0 +1 @@
|
||||||
|
bad = 123_
|
|
@ -0,0 +1 @@
|
||||||
|
bad = _123
|
|
@ -0,0 +1 @@
|
||||||
|
bad = 1__23
|
|
@ -0,0 +1 @@
|
||||||
|
[[agencies]] owner = "S Cjelli"
|
|
@ -0,0 +1 @@
|
||||||
|
[error] this = "should not be here"
|
|
@ -0,0 +1 @@
|
||||||
|
= 1
|
|
@ -0,0 +1 @@
|
||||||
|
a# = 1
|
|
@ -0,0 +1,2 @@
|
||||||
|
a
|
||||||
|
= 1
|
|
@ -0,0 +1 @@
|
||||||
|
a = 1 b = 2
|
|
@ -0,0 +1 @@
|
||||||
|
[abc = 1
|
|
@ -0,0 +1 @@
|
||||||
|
[
|
|
@ -0,0 +1 @@
|
||||||
|
a b = 1
|
|
@ -0,0 +1,3 @@
|
||||||
|
[a]
|
||||||
|
[xyz = 5
|
||||||
|
[b]
|
|
@ -0,0 +1 @@
|
||||||
|
key= = 1
|
|
@ -0,0 +1 @@
|
||||||
|
[ [table]]
|
|
@ -0,0 +1,4 @@
|
||||||
|
json_like = {
|
||||||
|
first = "Tom",
|
||||||
|
last = "Preston-Werner"
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
[[table] ]
|
|
@ -0,0 +1 @@
|
||||||
|
naughty = "\xAg"
|
|
@ -0,0 +1 @@
|
||||||
|
invalid-codepoint = "This string contains a non scalar unicode codepoint \uD801"
|
|
@ -0,0 +1 @@
|
||||||
|
invalid-escape = "This string has a bad \a escape character."
|
|
@ -0,0 +1 @@
|
||||||
|
invalid-escape = "This string has a bad \/ escape character."
|
|
@ -0,0 +1 @@
|
||||||
|
str = "val\ue"
|
|
@ -0,0 +1 @@
|
||||||
|
answer = "\x33"
|
|
@ -0,0 +1 @@
|
||||||
|
no-ending-quote = "One time, at band camp
|
|
@ -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"
|
|
@ -0,0 +1,2 @@
|
||||||
|
[[albums]
|
||||||
|
name = "Born to Run"
|
|
@ -0,0 +1,2 @@
|
||||||
|
[[]]
|
||||||
|
name = "Born to Run"
|
|
@ -0,0 +1 @@
|
||||||
|
[]
|
|
@ -0,0 +1,2 @@
|
||||||
|
[a]b]
|
||||||
|
zyx = 42
|
|
@ -0,0 +1,2 @@
|
||||||
|
[a[b]
|
||||||
|
zyx = 42
|
|
@ -0,0 +1 @@
|
||||||
|
[invalid key]
|
|
@ -0,0 +1,2 @@
|
||||||
|
[key#group]
|
||||||
|
answer = 42
|
|
@ -0,0 +1,4 @@
|
||||||
|
array = [
|
||||||
|
"Is there life after an array separator?", No
|
||||||
|
"Entry"
|
||||||
|
]
|
|
@ -0,0 +1 @@
|
||||||
|
answer = 42 the ultimate answer?
|
|
@ -0,0 +1 @@
|
||||||
|
string = "Is there life after strings?" No.
|
|
@ -0,0 +1 @@
|
||||||
|
[error] this shouldn't be here
|
|
@ -0,0 +1,4 @@
|
||||||
|
array = [
|
||||||
|
"Is there life before an array separator?" No,
|
||||||
|
"Entry"
|
||||||
|
]
|
|
@ -0,0 +1,5 @@
|
||||||
|
array = [
|
||||||
|
"Entry 1",
|
||||||
|
I don't belong,
|
||||||
|
"Entry 2",
|
||||||
|
]
|
|
@ -0,0 +1 @@
|
||||||
|
arr6 = [ 1, 2.0 ] # INVALID
|
|
@ -0,0 +1,4 @@
|
||||||
|
# INVALID TOML DOC
|
||||||
|
fruit = []
|
||||||
|
|
||||||
|
[[fruit]] # Not allowed
|
|
@ -0,0 +1,10 @@
|
||||||
|
# INVALID TOML DOC
|
||||||
|
[[fruit]]
|
||||||
|
name = "apple"
|
||||||
|
|
||||||
|
[[fruit.variety]]
|
||||||
|
name = "red delicious"
|
||||||
|
|
||||||
|
# This table conflicts with the previous table
|
||||||
|
[fruit.variety]
|
||||||
|
name = "granny smith"
|
|
@ -0,0 +1 @@
|
||||||
|
bare!key = 123
|
|
@ -0,0 +1,2 @@
|
||||||
|
barekey
|
||||||
|
= 123
|
|
@ -0,0 +1 @@
|
||||||
|
barekey =
|
|
@ -0,0 +1 @@
|
||||||
|
int = 0123
|
|
@ -0,0 +1 @@
|
||||||
|
key = # INVALID
|
|
@ -0,0 +1,3 @@
|
||||||
|
# THIS IS INVALID
|
||||||
|
a.b = 1
|
||||||
|
a.b.c = 2
|
|
@ -0,0 +1,3 @@
|
||||||
|
# DO NOT DO THIS
|
||||||
|
name = "Tom"
|
||||||
|
name = "Pradyun"
|
|
@ -0,0 +1 @@
|
||||||
|
= "no key name" # INVALID
|
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
a = "null"
|
|
@ -0,0 +1 @@
|
||||||
|
a = "null"
|
|
@ -0,0 +1 @@
|
||||||
|
a = "null"
|
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
a = """null"""
|
|
@ -0,0 +1 @@
|
||||||
|
a = """null"""
|
|
@ -0,0 +1 @@
|
||||||
|
a = """null"""
|
|
@ -0,0 +1 @@
|
||||||
|
a = """\UFFFFFFFF"""
|
|
@ -0,0 +1 @@
|
||||||
|
a = """\U00D80000"""
|
|
@ -0,0 +1 @@
|
||||||
|
a = """\@"""
|
|
@ -0,0 +1 @@
|
||||||
|
a = "\UFFFFFFFF"
|
|
@ -0,0 +1 @@
|
||||||
|
a = "\U00D80000"
|
|
@ -0,0 +1 @@
|
||||||
|
a = "\@"
|
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
a = 'null'
|
|
@ -0,0 +1 @@
|
||||||
|
a = 'null'
|
|
@ -0,0 +1 @@
|
||||||
|
a = 'null'
|
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
a = '''null'''
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue