5849898283
Unit tests functional and coverage back to 100% Add more routes to dictionary, add more credentials, add default port 5554, rename cameradar logs ENV variable, improve unit test readability, remove tmp file
377 lines
9.3 KiB
Go
377 lines
9.3 KiB
Go
package toml
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
type failingWriter struct {
|
|
failAt int
|
|
written int
|
|
buffer bytes.Buffer
|
|
}
|
|
|
|
func (f *failingWriter) Write(p []byte) (n int, err error) {
|
|
count := len(p)
|
|
toWrite := f.failAt - (count + f.written)
|
|
if toWrite < 0 {
|
|
toWrite = 0
|
|
}
|
|
if toWrite > count {
|
|
f.written += count
|
|
f.buffer.Write(p)
|
|
return count, nil
|
|
}
|
|
|
|
f.buffer.Write(p[:toWrite])
|
|
f.written = f.failAt
|
|
return toWrite, fmt.Errorf("failingWriter failed after writing %d bytes", f.written)
|
|
}
|
|
|
|
func assertErrorString(t *testing.T, expected string, err error) {
|
|
expectedErr := errors.New(expected)
|
|
if err == nil || err.Error() != expectedErr.Error() {
|
|
t.Errorf("expecting error %s, but got %s instead", expected, err)
|
|
}
|
|
}
|
|
|
|
func TestTreeWriteToEmptyTable(t *testing.T) {
|
|
doc := `[[empty-tables]]
|
|
[[empty-tables]]`
|
|
|
|
toml, err := Load(doc)
|
|
if err != nil {
|
|
t.Fatal("Unexpected Load error:", err)
|
|
}
|
|
tomlString, err := toml.ToTomlString()
|
|
if err != nil {
|
|
t.Fatal("Unexpected ToTomlString error:", err)
|
|
}
|
|
|
|
expected := `
|
|
[[empty-tables]]
|
|
|
|
[[empty-tables]]
|
|
`
|
|
|
|
if tomlString != expected {
|
|
t.Fatalf("Expected:\n%s\nGot:\n%s", expected, tomlString)
|
|
}
|
|
}
|
|
|
|
func TestTreeWriteToTomlString(t *testing.T) {
|
|
toml, err := Load(`name = { first = "Tom", last = "Preston-Werner" }
|
|
points = { x = 1, y = 2 }`)
|
|
|
|
if err != nil {
|
|
t.Fatal("Unexpected error:", err)
|
|
}
|
|
|
|
tomlString, _ := toml.ToTomlString()
|
|
reparsedTree, err := Load(tomlString)
|
|
|
|
assertTree(t, reparsedTree, err, map[string]interface{}{
|
|
"name": map[string]interface{}{
|
|
"first": "Tom",
|
|
"last": "Preston-Werner",
|
|
},
|
|
"points": map[string]interface{}{
|
|
"x": int64(1),
|
|
"y": int64(2),
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestTreeWriteToTomlStringSimple(t *testing.T) {
|
|
tree, err := Load("[foo]\n\n[[foo.bar]]\na = 42\n\n[[foo.bar]]\na = 69\n")
|
|
if err != nil {
|
|
t.Errorf("Test failed to parse: %v", err)
|
|
return
|
|
}
|
|
result, err := tree.ToTomlString()
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %s", err)
|
|
}
|
|
expected := "\n[foo]\n\n [[foo.bar]]\n a = 42\n\n [[foo.bar]]\n a = 69\n"
|
|
if result != expected {
|
|
t.Errorf("Expected got '%s', expected '%s'", result, expected)
|
|
}
|
|
}
|
|
|
|
func TestTreeWriteToTomlStringKeysOrders(t *testing.T) {
|
|
for i := 0; i < 100; i++ {
|
|
tree, _ := Load(`
|
|
foobar = true
|
|
bar = "baz"
|
|
foo = 1
|
|
[qux]
|
|
foo = 1
|
|
bar = "baz2"`)
|
|
|
|
stringRepr, _ := tree.ToTomlString()
|
|
|
|
t.Log("Intermediate string representation:")
|
|
t.Log(stringRepr)
|
|
|
|
r := strings.NewReader(stringRepr)
|
|
toml, err := LoadReader(r)
|
|
|
|
if err != nil {
|
|
t.Fatal("Unexpected error:", err)
|
|
}
|
|
|
|
assertTree(t, toml, err, map[string]interface{}{
|
|
"foobar": true,
|
|
"bar": "baz",
|
|
"foo": 1,
|
|
"qux": map[string]interface{}{
|
|
"foo": 1,
|
|
"bar": "baz2",
|
|
},
|
|
})
|
|
}
|
|
}
|
|
|
|
func testMaps(t *testing.T, actual, expected map[string]interface{}) {
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
t.Fatal("trees aren't equal.\n", "Expected:\n", expected, "\nActual:\n", actual)
|
|
}
|
|
}
|
|
|
|
func TestTreeWriteToMapSimple(t *testing.T) {
|
|
tree, _ := Load("a = 42\nb = 17")
|
|
|
|
expected := map[string]interface{}{
|
|
"a": int64(42),
|
|
"b": int64(17),
|
|
}
|
|
|
|
testMaps(t, tree.ToMap(), expected)
|
|
}
|
|
|
|
func TestTreeWriteToInvalidTreeSimpleValue(t *testing.T) {
|
|
tree := Tree{values: map[string]interface{}{"foo": int8(1)}}
|
|
_, err := tree.ToTomlString()
|
|
assertErrorString(t, "invalid value type at foo: int8", err)
|
|
}
|
|
|
|
func TestTreeWriteToInvalidTreeTomlValue(t *testing.T) {
|
|
tree := Tree{values: map[string]interface{}{"foo": &tomlValue{value: int8(1), comment: "", position: Position{}}}}
|
|
_, err := tree.ToTomlString()
|
|
assertErrorString(t, "unsupported value type int8: 1", err)
|
|
}
|
|
|
|
func TestTreeWriteToInvalidTreeTomlValueArray(t *testing.T) {
|
|
tree := Tree{values: map[string]interface{}{"foo": &tomlValue{value: int8(1), comment: "", position: Position{}}}}
|
|
_, err := tree.ToTomlString()
|
|
assertErrorString(t, "unsupported value type int8: 1", err)
|
|
}
|
|
|
|
func TestTreeWriteToFailingWriterInSimpleValue(t *testing.T) {
|
|
toml, _ := Load(`a = 2`)
|
|
writer := failingWriter{failAt: 0, written: 0}
|
|
_, err := toml.WriteTo(&writer)
|
|
assertErrorString(t, "failingWriter failed after writing 0 bytes", err)
|
|
}
|
|
|
|
func TestTreeWriteToFailingWriterInTable(t *testing.T) {
|
|
toml, _ := Load(`
|
|
[b]
|
|
a = 2`)
|
|
writer := failingWriter{failAt: 2, written: 0}
|
|
_, err := toml.WriteTo(&writer)
|
|
assertErrorString(t, "failingWriter failed after writing 2 bytes", err)
|
|
|
|
writer = failingWriter{failAt: 13, written: 0}
|
|
_, err = toml.WriteTo(&writer)
|
|
assertErrorString(t, "failingWriter failed after writing 13 bytes", err)
|
|
}
|
|
|
|
func TestTreeWriteToFailingWriterInArray(t *testing.T) {
|
|
toml, _ := Load(`
|
|
[[b]]
|
|
a = 2`)
|
|
writer := failingWriter{failAt: 2, written: 0}
|
|
_, err := toml.WriteTo(&writer)
|
|
assertErrorString(t, "failingWriter failed after writing 2 bytes", err)
|
|
|
|
writer = failingWriter{failAt: 15, written: 0}
|
|
_, err = toml.WriteTo(&writer)
|
|
assertErrorString(t, "failingWriter failed after writing 15 bytes", err)
|
|
}
|
|
|
|
func TestTreeWriteToMapExampleFile(t *testing.T) {
|
|
tree, _ := LoadFile("example.toml")
|
|
expected := map[string]interface{}{
|
|
"title": "TOML Example",
|
|
"owner": map[string]interface{}{
|
|
"name": "Tom Preston-Werner",
|
|
"organization": "GitHub",
|
|
"bio": "GitHub Cofounder & CEO\nLikes tater tots and beer.",
|
|
"dob": time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC),
|
|
},
|
|
"database": map[string]interface{}{
|
|
"server": "192.168.1.1",
|
|
"ports": []interface{}{int64(8001), int64(8001), int64(8002)},
|
|
"connection_max": int64(5000),
|
|
"enabled": true,
|
|
},
|
|
"servers": map[string]interface{}{
|
|
"alpha": map[string]interface{}{
|
|
"ip": "10.0.0.1",
|
|
"dc": "eqdc10",
|
|
},
|
|
"beta": map[string]interface{}{
|
|
"ip": "10.0.0.2",
|
|
"dc": "eqdc10",
|
|
},
|
|
},
|
|
"clients": map[string]interface{}{
|
|
"data": []interface{}{
|
|
[]interface{}{"gamma", "delta"},
|
|
[]interface{}{int64(1), int64(2)},
|
|
},
|
|
},
|
|
}
|
|
testMaps(t, tree.ToMap(), expected)
|
|
}
|
|
|
|
func TestTreeWriteToMapWithTablesInMultipleChunks(t *testing.T) {
|
|
tree, _ := Load(`
|
|
[[menu.main]]
|
|
a = "menu 1"
|
|
b = "menu 2"
|
|
[[menu.main]]
|
|
c = "menu 3"
|
|
d = "menu 4"`)
|
|
expected := map[string]interface{}{
|
|
"menu": map[string]interface{}{
|
|
"main": []interface{}{
|
|
map[string]interface{}{"a": "menu 1", "b": "menu 2"},
|
|
map[string]interface{}{"c": "menu 3", "d": "menu 4"},
|
|
},
|
|
},
|
|
}
|
|
treeMap := tree.ToMap()
|
|
|
|
testMaps(t, treeMap, expected)
|
|
}
|
|
|
|
func TestTreeWriteToMapWithArrayOfInlineTables(t *testing.T) {
|
|
tree, _ := Load(`
|
|
[params]
|
|
language_tabs = [
|
|
{ key = "shell", name = "Shell" },
|
|
{ key = "ruby", name = "Ruby" },
|
|
{ key = "python", name = "Python" }
|
|
]`)
|
|
|
|
expected := map[string]interface{}{
|
|
"params": map[string]interface{}{
|
|
"language_tabs": []interface{}{
|
|
map[string]interface{}{
|
|
"key": "shell",
|
|
"name": "Shell",
|
|
},
|
|
map[string]interface{}{
|
|
"key": "ruby",
|
|
"name": "Ruby",
|
|
},
|
|
map[string]interface{}{
|
|
"key": "python",
|
|
"name": "Python",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
treeMap := tree.ToMap()
|
|
testMaps(t, treeMap, expected)
|
|
}
|
|
|
|
func TestTreeWriteToFloat(t *testing.T) {
|
|
tree, err := Load(`a = 3.0`)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
str, err := tree.ToTomlString()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := `a = 3.0`
|
|
if strings.TrimSpace(str) != strings.TrimSpace(expected) {
|
|
t.Fatalf("Expected:\n%s\nGot:\n%s", expected, str)
|
|
}
|
|
}
|
|
|
|
func TestTreeWriteToSpecialFloat(t *testing.T) {
|
|
expected := `a = +inf
|
|
b = -inf
|
|
c = nan`
|
|
|
|
tree, err := Load(expected)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
str, err := tree.ToTomlString()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if strings.TrimSpace(str) != strings.TrimSpace(expected) {
|
|
t.Fatalf("Expected:\n%s\nGot:\n%s", expected, str)
|
|
}
|
|
}
|
|
|
|
func BenchmarkTreeToTomlString(b *testing.B) {
|
|
toml, err := Load(sampleHard)
|
|
if err != nil {
|
|
b.Fatal("Unexpected error:", err)
|
|
}
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, err := toml.ToTomlString()
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
var sampleHard = `# Test file for TOML
|
|
# Only this one tries to emulate a TOML file written by a user of the kind of parser writers probably hate
|
|
# This part you'll really hate
|
|
|
|
[the]
|
|
test_string = "You'll hate me after this - #" # " Annoying, isn't it?
|
|
|
|
[the.hard]
|
|
test_array = [ "] ", " # "] # ] There you go, parse this!
|
|
test_array2 = [ "Test #11 ]proved that", "Experiment #9 was a success" ]
|
|
# You didn't think it'd as easy as chucking out the last #, did you?
|
|
another_test_string = " Same thing, but with a string #"
|
|
harder_test_string = " And when \"'s are in the string, along with # \"" # "and comments are there too"
|
|
# Things will get harder
|
|
|
|
[the.hard."bit#"]
|
|
"what?" = "You don't think some user won't do that?"
|
|
multi_line_array = [
|
|
"]",
|
|
# ] Oh yes I did
|
|
]
|
|
|
|
# Each of the following keygroups/key value pairs should produce an error. Uncomment to them to test
|
|
|
|
#[error] if you didn't catch this, your parser is broken
|
|
#string = "Anything other than tabs, spaces and newline after a keygroup or key value pair has ended should produce an error unless it is a comment" like this
|
|
#array = [
|
|
# "This might most likely happen in multiline arrays",
|
|
# Like here,
|
|
# "or here,
|
|
# and here"
|
|
# ] End of array comment, forgot the #
|
|
#number = 3.14 pi <--again forgot the # `
|