func TestMarshalJSON(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bsIn, _ := createDocument(assert)
	parsedDoc, err := gjp.Parse(bsIn, "/")
	assert.Nil(err)
	bsOut, err := parsedDoc.MarshalJSON()
	assert.Nil(err)
	assert.Equal(bsOut, bsIn)
	builtDoc := gjp.NewDocument("/")
	err = builtDoc.SetValueAt("/a/2/x", 1)
	assert.Nil(err)
	err = builtDoc.SetValueAt("/a/4/y", true)
	assert.Nil(err)
	bsIn = []byte(`{"a":[null,null,{"x":1},null,{"y":true}]}`)
	bsOut, err = builtDoc.MarshalJSON()
	assert.Nil(err)
	assert.Equal(bsOut, bsIn)
}
TestMarshalJSON tests building a JSON document again.
package gjp_test
import (
	"encoding/json"
	"errors"
	"testing"
	"time"
	"github.com/tideland/golib/audit"
	"github.com/tideland/golib/gjp"
)
func TestParseError(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bs := []byte(`abc{def`)
	doc, err := gjp.Parse(bs, "/")
	assert.Nil(doc)
	assert.ErrorMatch(err, `.*cannot unmarshal document.*`)
}
func TestClear(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bs, _ := createDocument(assert)
	doc, err := gjp.Parse(bs, "/")
	assert.Nil(err)
	doc.Clear()
	doc.SetValueAt("/", "foo")
	foo := doc.ValueAt("/").AsString("<undefined>")
	assert.Equal(foo, "foo")
}
func TestLength(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bs, _ := createDocument(assert)
	doc, err := gjp.Parse(bs, "/")
	assert.Nil(err)
	l := doc.Length("X")
	assert.Equal(l, -1)
	l = doc.Length("")
	assert.Equal(l, 4)
	l = doc.Length("B")
	assert.Equal(l, 3)
	l = doc.Length("B/2")
	assert.Equal(l, 5)
	l = doc.Length("/B/2/D")
	assert.Equal(l, 2)
	l = doc.Length("/B/1/S")
	assert.Equal(l, 3)
	l = doc.Length("/B/1/S/0")
	assert.Equal(l, 1)
}
func TestProcessing(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bs, _ := createDocument(assert)
	count := 0
	processor := func(path string, value gjp.Value) error {
		count++
		assert.Logf("path %02d  =>  %-10q = %q", count, path, value.AsString("<undefined>"))
		return nil
	}
	doc, err := gjp.Parse(bs, "/")
	assert.Nil(err)
	err = doc.Process(processor)
	assert.Nil(err)
	assert.Equal(count, 27)
	processor = func(path string, value gjp.Value) error {
		return errors.New("ouch")
	}
	err = doc.Process(processor)
	assert.ErrorMatch(err, `.*ouch.*`)
}
func TestSeparator(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bs, lo := createDocument(assert)
	doc, err := gjp.Parse(bs, "/")
	assert.Nil(err)
	sv := doc.ValueAt("A").AsString("illegal")
	assert.Equal(sv, lo.A)
	sv = doc.ValueAt("B/0/A").AsString("illegal")
	assert.Equal(sv, lo.B[0].A)
	sv = doc.ValueAt("/B/1/D/A").AsString("illegal")
	assert.Equal(sv, lo.B[1].D.A)
	sv = doc.ValueAt("/B/2/S").AsString("illegal")
	assert.Equal(sv, "illegal")
	doc, err = gjp.Parse(bs, "::")
	assert.Nil(err)
	sv = doc.ValueAt("A").AsString("illegal")
	assert.Equal(sv, lo.A)
	sv = doc.ValueAt("B::0::A").AsString("illegal")
	assert.Equal(sv, lo.B[0].A)
	sv = doc.ValueAt("B::1::D::A").AsString("illegal")
	assert.Equal(sv, lo.B[1].D.A)
	v := doc.ValueAt("you-wont-find-me")
	assert.True(v.IsUndefined())
}
func TestCompare(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	first, _ := createDocument(assert)
	second := createCompareDocument(assert)
	firstDoc, err := gjp.Parse(first, "/")
	assert.Nil(err)
	secondDoc, err := gjp.Parse(second, "/")
	assert.Nil(err)
	diff, err := gjp.Compare(first, first, "/")
	assert.Nil(err)
	assert.Length(diff.Differences(), 0)
	diff, err = gjp.Compare(first, second, "/")
	assert.Nil(err)
	assert.Length(diff.Differences(), 12)
	diff, err = gjp.CompareDocuments(firstDoc, secondDoc, "/")
	assert.Nil(err)
	assert.Length(diff.Differences(), 12)
	for _, path := range diff.Differences() {
		fv, sv := diff.DifferenceAt(path)
		fvs := fv.AsString("<first undefined>")
		svs := sv.AsString("<second undefined>")
		assert.Different(fvs, svs, path)
	}
	first, err = diff.FirstDocument().MarshalJSON()
	assert.Nil(err)
	second, err = diff.SecondDocument().MarshalJSON()
	assert.Nil(err)
	diff, err = gjp.Compare(first, second, ":")
	assert.Nil(err)
	assert.Length(diff.Differences(), 12)
	first = []byte(`{}`)
	second = []byte(`{"a":[],"b":{},"c":null}`)
	sdocParsed, err := gjp.Parse(second, "/")
	assert.Nil(err)
	sdocMarshalled, err := sdocParsed.MarshalJSON()
	assert.Nil(err)
	assert.Equal(string(sdocMarshalled), string(second))
	diff, err = gjp.Compare(first, second, "/")
	assert.Nil(err)
	assert.Length(diff.Differences(), 4)
	first = []byte(`[]`)
	diff, err = gjp.Compare(first, second, "/")
	assert.Nil(err)
	assert.Length(diff.Differences(), 4)
	first = []byte(`["A", "B", "C"]`)
	diff, err = gjp.Compare(first, second, "/")
	assert.Nil(err)
	assert.Length(diff.Differences(), 6)
	first = []byte(`"foo"`)
	diff, err = gjp.Compare(first, second, "/")
	assert.Nil(err)
	assert.Length(diff.Differences(), 4)
}
func TestString(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bs, _ := createDocument(assert)
	doc, err := gjp.Parse(bs, "/")
	assert.Nil(err)
	sv := doc.ValueAt("A").AsString("illegal")
	assert.Equal(sv, "Level One")
	sv = doc.ValueAt("B/0/B").AsString("illegal")
	assert.Equal(sv, "100")
	sv = doc.ValueAt("B/0/C").AsString("illegal")
	assert.Equal(sv, "true")
	sv = doc.ValueAt("B/0/D/B").AsString("illegal")
	assert.Equal(sv, "10.1")
}
func TestInt(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bs, _ := createDocument(assert)
	doc, err := gjp.Parse(bs, "/")
	assert.Nil(err)
	iv := doc.ValueAt("A").AsInt(-1)
	assert.Equal(iv, -1)
	iv = doc.ValueAt("B/0/B").AsInt(-1)
	assert.Equal(iv, 100)
	iv = doc.ValueAt("B/0/C").AsInt(-1)
	assert.Equal(iv, 1)
	iv = doc.ValueAt("B/0/S/2").AsInt(-1)
	assert.Equal(iv, 1)
	iv = doc.ValueAt("B/0/D/B").AsInt(-1)
	assert.Equal(iv, 10)
}
func TestFloat64(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bs, _ := createDocument(assert)
	doc, err := gjp.Parse(bs, "/")
	assert.Nil(err)
	fv := doc.ValueAt("A").AsFloat64(-1.0)
	assert.Equal(fv, -1.0)
	fv = doc.ValueAt("B/1/B").AsFloat64(-1.0)
	assert.Equal(fv, 200.0)
	fv = doc.ValueAt("B/0/C").AsFloat64(-99)
	assert.Equal(fv, 1.0)
	fv = doc.ValueAt("B/0/S/3").AsFloat64(-1.0)
	assert.Equal(fv, 2.2)
	fv = doc.ValueAt("B/1/D/B").AsFloat64(-1.0)
	assert.Equal(fv, 20.2)
}
func TestBool(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bs, _ := createDocument(assert)
	doc, err := gjp.Parse(bs, "/")
	assert.Nil(err)
	bv := doc.ValueAt("A").AsBool(false)
	assert.Equal(bv, false)
	bv = doc.ValueAt("B/0/C").AsBool(false)
	assert.Equal(bv, true)
	bv = doc.ValueAt("B/0/S/0").AsBool(false)
	assert.Equal(bv, false)
	bv = doc.ValueAt("B/0/S/2").AsBool(false)
	assert.Equal(bv, true)
	bv = doc.ValueAt("B/0/S/4").AsBool(false)
	assert.Equal(bv, true)
}
func TestQuery(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bs, _ := createDocument(assert)
	doc, err := gjp.Parse(bs, "/")
	assert.Nil(err)
	pvs, err := doc.Query("Z/*")
	assert.Nil(err)
	assert.Length(pvs, 0)
	pvs, err = doc.Query("*")
	assert.Nil(err)
	assert.Length(pvs, 27)
	pvs, err = doc.Query("/A")
	assert.Nil(err)
	assert.Length(pvs, 1)
	pvs, err = doc.Query("/B/*")
	assert.Nil(err)
	assert.Length(pvs, 24)
	pvs, err = doc.Query("/B/[01]/*")
	assert.Nil(err)
	assert.Length(pvs, 18)
	pvs, err = doc.Query("/B/[01]/*A")
	assert.Nil(err)
	assert.Length(pvs, 4)
	pvs, err = doc.Query("*/S/*")
	assert.Nil(err)
	assert.Length(pvs, 8)
	pvs, err = doc.Query("*/S/3")
	assert.Nil(err)
	assert.Length(pvs, 1)
	pvs, err = doc.Query("/A")
	assert.Nil(err)
	assert.Equal(pvs[0].Path, "/A")
	assert.Equal(pvs[0].Value.AsString(""), "Level One")
}
func TestBuilding(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	doc := gjp.NewDocument("/")
	err := doc.SetValueAt("", "foo")
	assert.Nil(err)
	sv := doc.ValueAt("").AsString("bar")
	assert.Equal(sv, "foo")
	doc = gjp.NewDocument("/")
	err = doc.SetValueAt("/a/b/x", 1)
	assert.Nil(err)
	err = doc.SetValueAt("/a/b/y", true)
	assert.Nil(err)
	err = doc.SetValueAt("/a/c", "quick brown fox")
	assert.Nil(err)
	err = doc.SetValueAt("/a/d/0/z", 47.11)
	assert.Nil(err)
	err = doc.SetValueAt("/a/d/1/z", nil)
	assert.Nil(err)
	iv := doc.ValueAt("a/b/x").AsInt(0)
	assert.Equal(iv, 1)
	bv := doc.ValueAt("a/b/y").AsBool(false)
	assert.Equal(bv, true)
	sv = doc.ValueAt("a/c").AsString("")
	assert.Equal(sv, "quick brown fox")
	fv := doc.ValueAt("a/d/0/z").AsFloat64(8.15)
	assert.Equal(fv, 47.11)
	nv := doc.ValueAt("a/d/1/z").IsUndefined()
	assert.True(nv)
	pvs, err := doc.Query("*x")
	assert.Nil(err)
	assert.Length(pvs, 1)
	err = doc.SetValueAt("a", "stupid")
	assert.ErrorMatch(err, ".*corrupt.*")
	err = doc.SetValueAt("a/b/x/y", "stupid")
	assert.ErrorMatch(err, ".*corrupt.*")
	err = doc.SetValueAt("/a/b/x", 2)
	assert.Nil(err)
	iv = doc.ValueAt("a/b/x").AsInt(0)
	assert.Equal(iv, 2)
}