201 lines
7.8 KiB
Go
201 lines
7.8 KiB
Go
package ast_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.makaay.nl/mauricem/go-toml/ast"
|
|
)
|
|
|
|
func Test_ConstructSlightlyComplexStructure(t *testing.T) {
|
|
testAST(t, func() (error, *ast.Document) {
|
|
p := ast.NewDocument()
|
|
p.SetKeyValuePair(ast.NewKey("ding"), ast.NewValue(ast.TypeInteger, 10))
|
|
p.SetKeyValuePair(ast.NewKey("dong"), ast.NewValue(ast.TypeString, "not a song"))
|
|
p.OpenTable(ast.NewKey("key1", "key2 a"))
|
|
p.SetKeyValuePair(ast.NewKey("dooh"), ast.NewValue(ast.TypeBoolean, true))
|
|
p.SetKeyValuePair(ast.NewKey("dah"), ast.NewValue(ast.TypeBoolean, false))
|
|
p.OpenTable(ast.NewKey("key1", "key2 b"))
|
|
p.SetKeyValuePair(ast.NewKey("dieh"), ast.NewValue(ast.TypeFloat, 1.111))
|
|
p.SetKeyValuePair(ast.NewKey("duh"), ast.NewValue(ast.TypeFloat, 1.18e-12))
|
|
p.SetKeyValuePair(ast.NewKey("foo", "bar"), ast.NewValue(ast.TypeArrayOfTables, ast.NewValue(ast.TypeInteger, 1), ast.NewValue(ast.TypeInteger, 2)))
|
|
p.OpenArrayOfTables(ast.NewKey("aaah", "table array"))
|
|
p.SetKeyValuePair(ast.NewKey("a"), ast.NewValue(ast.TypeFloat, 1.234))
|
|
p.OpenArrayOfTables(ast.NewKey("aaah", "table array"))
|
|
p.SetKeyValuePair(ast.NewKey("b"), ast.NewValue(ast.TypeFloat, 2.345))
|
|
p.SetKeyValuePair(ast.NewKey("c"), ast.NewValue(ast.TypeString, "bingo!"))
|
|
p.OpenArrayOfTables(ast.NewKey("aaah", "table array"))
|
|
return nil, p
|
|
},
|
|
"",
|
|
`{"aaah": {"table array": [{"a": 1.234}, {"b": 2.345, "c": "bingo!"}, {}]}, `+
|
|
`"ding": 10, "dong": "not a song", `+
|
|
`"key1": {"key2 a": {"dah": false, "dooh": true}, "key2 b": {"dieh": 1.111, "duh": 1.18e-12, "foo": {"bar": [1, 2]}}}}`)
|
|
}
|
|
|
|
func Test_EmptyKeyForCreatingTablePath_Panics(t *testing.T) {
|
|
defer func() {
|
|
r := recover()
|
|
if r.(string) != "makeTablePath(): empty key provided; a key must have at least one key part" {
|
|
t.Fatalf("Did not get the expected panic message")
|
|
}
|
|
}()
|
|
p := ast.NewDocument()
|
|
p.OpenTable(ast.NewKey())
|
|
}
|
|
|
|
func Test_StoreValueInRooTypeTable(t *testing.T) {
|
|
testAST(t, func() (error, *ast.Document) {
|
|
p := ast.NewDocument()
|
|
p.SetKeyValuePair(ast.NewKey("key1"), ast.NewValue(ast.TypeString, "value1"))
|
|
return p.SetKeyValuePair(ast.NewKey("key2"), ast.NewValue(ast.TypeString, "value2")), p
|
|
},
|
|
"",
|
|
`{"key1": "value1", "key2": "value2"}`)
|
|
}
|
|
|
|
func Test_StoreValueWithMultipartKey_CreatesTableHierarchy(t *testing.T) {
|
|
testAST(t, func() (error, *ast.Document) {
|
|
p := ast.NewDocument()
|
|
return p.SetKeyValuePair(ast.NewKey("key1", "key2", "key3"), ast.NewValue(ast.TypeString, "value")), p
|
|
},
|
|
"",
|
|
`{"key1": {"key2": {"key3": "value"}}}`)
|
|
}
|
|
|
|
func Test_StoreDuplicateKeyInRooTypeTable_ReturnsError(t *testing.T) {
|
|
testAST(t, func() (error, *ast.Document) {
|
|
p := ast.NewDocument()
|
|
p.SetKeyValuePair(ast.NewKey("key"), ast.NewValue(ast.TypeString, "value"))
|
|
return p.SetKeyValuePair(ast.NewKey("key"), ast.NewValue(ast.TypeInteger, 321)), p
|
|
},
|
|
`invalid key/value pair: string value already exists at key [key]`,
|
|
`{"key": "value"}`)
|
|
}
|
|
|
|
func Test_StoreValueWithMultipartKey_UnderSubtable_CreatesTableHierarchy(t *testing.T) {
|
|
testAST(t, func() (error, *ast.Document) {
|
|
p := ast.NewDocument()
|
|
p.OpenTable(ast.NewKey("tablekey1", "tablekey2"))
|
|
return p.SetKeyValuePair(ast.NewKey("valuekey1", "valuekey2", "valuekey3"), ast.NewValue(ast.TypeString, "value")), p
|
|
},
|
|
"",
|
|
`{"tablekey1": {"tablekey2": {"valuekey1": {"valuekey2": {"valuekey3": "value"}}}}}`)
|
|
}
|
|
|
|
func Test_StoreKeyPathWherePathContainsNonTableAlready_ReturnsError(t *testing.T) {
|
|
testAST(t, func() (error, *ast.Document) {
|
|
p := ast.NewDocument()
|
|
p.OpenTable(ast.NewKey("key1"))
|
|
p.SetKeyValuePair(ast.NewKey("key2"), ast.NewValue(ast.TypeInteger, 0))
|
|
return p.SetKeyValuePair(ast.NewKey("key2", "key3"), ast.NewValue(ast.TypeString, "value")), p
|
|
},
|
|
`invalid key/value pair: integer value already exists at key [key1->key2]`,
|
|
`{"key1": {"key2": 0}}`)
|
|
}
|
|
|
|
func Test_GivenExistingTableAtKey_CreatingTableAtSameKey_ReturnsError(t *testing.T) {
|
|
testAST(t, func() (error, *ast.Document) {
|
|
p := ast.NewDocument()
|
|
p.OpenTable(ast.NewKey("key1", "key2"))
|
|
return p.OpenTable(ast.NewKey("key1", "key2")), p
|
|
},
|
|
`invalid table: table value already exists at key [key1->key2]`,
|
|
`{"key1": {"key2": {}}}`)
|
|
}
|
|
|
|
func Test_GivenExistingItemAtKey_CreatingTableAtSameKey_ReturnsError(t *testing.T) {
|
|
testAST(t, func() (error, *ast.Document) {
|
|
p := ast.NewDocument()
|
|
p.SetKeyValuePair(ast.NewKey("key"), ast.NewValue(ast.TypeString, "value"))
|
|
return p.OpenTable(ast.NewKey("key")), p
|
|
},
|
|
`invalid table: string value already exists at key [key]`,
|
|
`{"key": "value"}`)
|
|
}
|
|
|
|
func Test_GivenExistingItemInKeyPath_CreatingTable_ReturnsError(t *testing.T) {
|
|
testAST(t, func() (error, *ast.Document) {
|
|
p := ast.NewDocument()
|
|
p.SetKeyValuePair(ast.NewKey("key"), ast.NewValue(ast.TypeString, "value"))
|
|
return p.OpenTable(ast.NewKey("key", "subkey")), p
|
|
},
|
|
`invalid table: string value already exists at key [key]`,
|
|
`{"key": "value"}`)
|
|
}
|
|
|
|
func Test_GivenExistingItemAtDeepKey_CreatingTableAtSameKey_ReturnsError(t *testing.T) {
|
|
testAST(t, func() (error, *ast.Document) {
|
|
p := ast.NewDocument()
|
|
p.OpenTable(ast.NewKey("deep", "table"))
|
|
p.SetKeyValuePair(ast.NewKey("key"), ast.NewValue(ast.TypeInteger, 0))
|
|
return p.OpenTable(ast.NewKey("deep", "table", "key")), p
|
|
},
|
|
`invalid table: integer value already exists at key [deep->table->key]`,
|
|
`{"deep": {"table": {"key": 0}}}`)
|
|
}
|
|
|
|
func Test_GivenExistingItemAtDeepKeyFromSubTable_CreatingTableAtSameKey_ReturnsError(t *testing.T) {
|
|
testAST(t, func() (error, *ast.Document) {
|
|
p := ast.NewDocument()
|
|
p.OpenTable(ast.NewKey("deep", "table"))
|
|
p.SetKeyValuePair(ast.NewKey("key1", "key2"), ast.NewValue(ast.TypeInteger, 0))
|
|
return p.SetKeyValuePair(ast.NewKey("key1", "key2"), ast.NewValue(ast.TypeBoolean, true)), p
|
|
},
|
|
// This test mainly tests the formatting of [deep->table->key1->key2], being a concatenation
|
|
// of the currently active table plus the multipart key for SetKeyValuePair().
|
|
`invalid key/value pair: integer value already exists at key [deep->table->key1->key2]`,
|
|
`{"deep": {"table": {"key1": {"key2": 0}}}}`)
|
|
}
|
|
|
|
func Test_FormattingOfQuotedPathPartInError(t *testing.T) {
|
|
testAST(t, func() (error, *ast.Document) {
|
|
p := ast.NewDocument()
|
|
p.OpenTable(ast.NewKey("must be quoted"))
|
|
p.SetKeyValuePair(ast.NewKey("this one too"), ast.NewValue(ast.TypeInteger, 0))
|
|
return p.SetKeyValuePair(ast.NewKey("this one too"), ast.NewValue(ast.TypeInteger, 0)), p
|
|
},
|
|
`invalid key/value pair: integer value already exists at key ["must be quoted"->"this one too"]`,
|
|
`{"must be quoted": {"this one too": 0}}`)
|
|
}
|
|
|
|
func Test_GivenExistingItemAtKey_CreatingArrayOfTablesAtSameKey_ReturnsError(t *testing.T) {
|
|
testAST(t, func() (error, *ast.Document) {
|
|
p := ast.NewDocument()
|
|
p.Root["key"] = ast.NewValue(ast.TypeString, "value")
|
|
return p.OpenArrayOfTables(ast.NewKey("key")), p
|
|
},
|
|
`invalid table array: string value already exists at key [key]`,
|
|
`{"key": "value"}`)
|
|
}
|
|
|
|
func Test_GivenExistingItemInKeyPath_CreatingArrayOfTables_ReturnsError(t *testing.T) {
|
|
testAST(t, func() (error, *ast.Document) {
|
|
p := ast.NewDocument()
|
|
p.Root["key"] = ast.NewValue(ast.TypeString, "value")
|
|
return p.OpenArrayOfTables(ast.NewKey("key", "subkey")), p
|
|
},
|
|
`invalid table array: string value already exists at key [key]`,
|
|
`{"key": "value"}`)
|
|
}
|
|
|
|
func testAST(t *testing.T, code func() (error, *ast.Document), expectedError string, expectedData string) {
|
|
err, p := code()
|
|
if expectedError == "" {
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error: %s", err)
|
|
}
|
|
} else {
|
|
if err == nil {
|
|
t.Fatalf("An error was expected, but no error was returned")
|
|
} else if err.Error() != expectedError {
|
|
t.Fatalf("Unexpected error:\nexpected: %s\nactual: %s\n", expectedError, err.Error())
|
|
}
|
|
}
|
|
if expectedData == "" {
|
|
return
|
|
}
|
|
if expectedData != p.Root.String() {
|
|
t.Fatalf("Unexpected data after parsing:\nexpected: %s\nactual: %s\n", expectedData, p.Root.String())
|
|
}
|
|
}
|