package json import ( "bufio" "main/walk" "strings" "testing" "encoding/json" ) type writeTester struct { writer *JSONWriter output *strings.Builder t *testing.T } func (t writeTester) write(value walk.Value, path ...interface{}) writeTester { var pathValues []walk.Value for _, segment := range path { switch s := segment.(type) { case int: pathValues = append(pathValues, walk.NumberScalar(s)) case string: pathValues = append(pathValues, walk.StringStructure(s)) default: panic("Invalid path segment type") } } t.writer.Write(walk.WalkItem { Value: []walk.Value{value}, Path: pathValues, }) return t } func (t writeTester) expect(expected interface{}) writeTester { t.writer.AssertDone() output := t.output.String() var actual interface{} err := json.Unmarshal([]byte(output), &actual) if err != nil { t.t.Log("Produced invalid JSON:") t.t.Log(output) t.t.FailNow() } expectedBytes, err1 := json.Marshal(expected) actualBytes, err2 := json.Marshal(actual) if err1 != nil || err2 != nil { panic("Error marshalling") } expectedString := string(expectedBytes) actualString := string(actualBytes) if expectedString != actualString { t.t.Log("Expected:") t.t.Log(expectedString) t.t.Log("Found:") t.t.Log(actualString) t.t.FailNow() } return t } func tester(t *testing.T) writeTester { var output strings.Builder return writeTester { writer: NewJSONWriter(bufio.NewWriter(&output)), output: &output, t: t, } } func TestImplicitStructures(t *testing.T) { tester(t).write( walk.NullScalar{}, 0, "test", 0, ).expect( []interface{}{ map[string]interface{}{ "test": []interface{}{ nil, }, }, }, ) } func TestExplicitMap(t *testing.T) { tester(t).write( make(walk.MapStructure), ).write( walk.NullScalar{}, "test", ).expect( map[string]interface{}{ "test": nil, }, ) } func TestExplicitNested(t *testing.T) { tester(t).write( make(walk.MapStructure), ).write( make(walk.MapStructure), "first", ).write( make(walk.MapStructure), "first", "second", ).write( walk.StringStructure("test"), "first", "second", "third", ).expect( map[string]interface{}{ "first": map[string]interface{}{ "second": map[string]interface{}{ "third": "test", }, }, }, ) } func TestArrayOfMaps(t *testing.T) { tester(t).write( walk.ArrayStructure{}, ).write( make(walk.MapStructure), 0, ).write( walk.NumberScalar(0), 0, "number", ).write( make(walk.MapStructure), 1, ).write( walk.NumberScalar(1), 1, "nested", "number", ).write( make(walk.MapStructure), 2, ).write( walk.NumberScalar(2), 2, "number", ).expect( []interface{}{ map[string]interface{}{ "number": 0, }, map[string]interface{}{ "nested": map[string]interface{}{ "number": 1, }, }, map[string]interface{}{ "number": 2, }, }, ) } func TestStructures1(t *testing.T) { tester(t).write( make(walk.MapStructure), ).write( make(walk.MapStructure), "map", ).write( walk.ArrayStructure{}, "array", ).expect( map[string]interface{}{ "map": map[string]interface{}{}, "array": []interface{}{}, }, ) }