Make ToString() return an error instead of panic (#117)

Fixes #100
This commit is contained in:
Thomas Pelletier
2017-01-15 18:49:11 -08:00
committed by GitHub
parent ee2c0b51cf
commit a1f048ba24
3 changed files with 47 additions and 9 deletions
+4 -1
View File
@@ -673,7 +673,10 @@ func TestToString(t *testing.T) {
t.Errorf("Test failed to parse: %v", err) t.Errorf("Test failed to parse: %v", err)
return return
} }
result := tree.ToString() result, err := tree.ToString()
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" expected := "\n[foo]\n\n [[foo.bar]]\n a = 42\n\n [[foo.bar]]\n a = 69\n"
if result != expected { if result != expected {
t.Errorf("Expected got '%s', expected '%s'", result, expected) t.Errorf("Expected got '%s', expected '%s'", result, expected)
+26 -6
View File
@@ -87,7 +87,7 @@ func toTomlValue(item interface{}, indent int) string {
case nil: case nil:
return "" return ""
default: default:
panic(fmt.Sprintf("unsupported value type %T: %v", value, value)) panic(fmt.Errorf("unsupported value type %T: %v", value, value))
} }
} }
@@ -154,6 +154,23 @@ func (t *TomlTree) toToml(indent, keyspace string) string {
return strings.Join(resultChunks, "") return strings.Join(resultChunks, "")
} }
// Same as ToToml(), but does not panic and returns an error
func (t *TomlTree) toTomlSafe(indent, keyspace string) (result string, err error) {
defer func() {
if r := recover(); r != nil {
result = ""
switch x := r.(type) {
case error:
err = x
default:
err = fmt.Errorf("unknown panic: %s", r)
}
}
}()
result = t.toToml(indent, keyspace)
return
}
func convertMapStringString(in map[string]string) map[string]interface{} { func convertMapStringString(in map[string]string) map[string]interface{} {
result := make(map[string]interface{}, len(in)) result := make(map[string]interface{}, len(in))
for k, v := range in { for k, v := range in {
@@ -170,15 +187,18 @@ func convertMapInterfaceInterface(in map[interface{}]interface{}) map[string]int
return result return result
} }
// ToString is an alias for String // ToString generates a human-readable representation of the current tree.
func (t *TomlTree) ToString() string { // Output spans multiple lines, and is suitable for ingest by a TOML parser.
return t.String() // If the conversion cannot be performed, ToString returns a non-nil error.
func (t *TomlTree) ToString() (string, error) {
return t.toTomlSafe("", "")
} }
// String generates a human-readable representation of the current tree. // String generates a human-readable representation of the current tree.
// Output spans multiple lines, and is suitable for ingest by a TOML parser // Alias of ToString.
func (t *TomlTree) String() string { func (t *TomlTree) String() string {
return t.toToml("", "") result, _ := t.ToString()
return result
} }
// ToMap recursively generates a representation of the current tree using map[string]interface{}. // ToMap recursively generates a representation of the current tree using map[string]interface{}.
+17 -2
View File
@@ -1,6 +1,7 @@
package toml package toml
import ( import (
"errors"
"reflect" "reflect"
"strings" "strings"
"testing" "testing"
@@ -15,7 +16,8 @@ points = { x = 1, y = 2 }`)
t.Fatal("Unexpected error:", err) t.Fatal("Unexpected error:", err)
} }
reparsedTree, err := Load(toml.ToString()) tomlString, _ := toml.ToString()
reparsedTree, err := Load(tomlString)
assertTree(t, reparsedTree, err, map[string]interface{}{ assertTree(t, reparsedTree, err, map[string]interface{}{
"name": map[string]interface{}{ "name": map[string]interface{}{
@@ -39,7 +41,7 @@ func TestTomlTreeConversionToStringKeysOrders(t *testing.T) {
foo = 1 foo = 1
bar = "baz2"`) bar = "baz2"`)
stringRepr := tree.ToString() stringRepr, _ := tree.ToString()
t.Log("Intermediate string representation:") t.Log("Intermediate string representation:")
t.Log(stringRepr) t.Log(stringRepr)
@@ -69,6 +71,19 @@ func testMaps(t *testing.T, actual, expected map[string]interface{}) {
} }
} }
func TestToStringTypeConversionError(t *testing.T) {
tree := TomlTree{
values: map[string]interface{}{
"thing": []string{"unsupported"},
},
}
_, err := tree.ToString()
expected := errors.New("unsupported value type []string: [unsupported]")
if err.Error() != expected.Error() {
t.Errorf("expecting error %s, but got %s instead", expected, err)
}
}
func TestTomlTreeConversionToMapSimple(t *testing.T) { func TestTomlTreeConversionToMapSimple(t *testing.T) {
tree, _ := Load("a = 42\nb = 17") tree, _ := Load("a = 42\nb = 17")