package xml import ( "bytes" "fmt" "math" "math/big" "strconv" "testing" ) var ( oneInt = new(big.Int).SetInt64(1) oneFloat = new(big.Float).SetFloat64(1.0) ) func TestValue(t *testing.T) { nested := StartElement{Name: Name{Local: "nested"}} cases := map[string]struct { setter func(Value) expected string }{ "string value": { setter: func(value Value) { value.String("foo") }, expected: `foo`, }, "string escaped": { setter: func(value Value) { value.String("{\"foo\":\"bar\"}") }, expected: fmt.Sprintf("{%sfoo%s:%sbar%s}", escQuot, escQuot, escQuot, escQuot), }, "integer": { setter: func(value Value) { value.Long(1024) }, expected: `1024`, }, "float": { setter: func(value Value) { value.Double(1e20) }, expected: `100000000000000000000`, }, "float exponent component": { setter: func(value Value) { value.Double(3e22) }, expected: `3e+22`, }, "boolean true": { setter: func(value Value) { value.Boolean(true) }, expected: `true`, }, "boolean false": { setter: func(value Value) { value.Boolean(false) }, expected: `false`, }, "encode bytes": { setter: func(value Value) { value.Base64EncodeBytes([]byte("foo bar")) }, expected: `Zm9vIGJhcg==`, }, "encode bytes nil": { setter: func(value Value) { value.Base64EncodeBytes(nil) }, expected: ``, }, "object": { setter: func(value Value) { defer value.Close() value.MemberElement(nested).String("value") }, expected: `value`, }, "null": { setter: func(value Value) { value.Close() }, expected: ``, }, "nullWithRoot": { setter: func(value Value) { defer value.Close() o := value.MemberElement(nested) defer o.Close() }, expected: ``, }, "write text": { setter: func(value Value) { defer value.Close() o := value.MemberElement(nested) o.Write([]byte(`{"nested":"value"}`), false) }, expected: `{"nested":"value"}`, }, "write escaped text": { setter: func(value Value) { defer value.Close() o := value.MemberElement(nested) o.Write([]byte(`{"nested":"value"}`), true) }, expected: fmt.Sprintf("{%snested%s:%svalue%s}", escQuot, escQuot, escQuot, escQuot), }, "bigInteger": { setter: func(value Value) { v := new(big.Int).SetInt64(math.MaxInt64) value.BigInteger(v.Sub(v, oneInt)) }, expected: strconv.FormatInt(math.MaxInt64-1, 10), }, "bigInteger > int64": { setter: func(value Value) { v := new(big.Int).SetInt64(math.MaxInt64) value.BigInteger(v.Add(v, oneInt)) }, expected: "9223372036854775808", }, "bigInteger < int64": { setter: func(value Value) { v := new(big.Int).SetInt64(math.MinInt64) value.BigInteger(v.Sub(v, oneInt)) }, expected: "-9223372036854775809", }, "bigFloat": { setter: func(value Value) { v := new(big.Float).SetFloat64(math.MaxFloat64) value.BigDecimal(v.Sub(v, oneFloat)) }, expected: strconv.FormatFloat(math.MaxFloat64-1, 'e', -1, 64), }, "bigFloat fits in int64": { setter: func(value Value) { v := new(big.Float).SetInt64(math.MaxInt64) value.BigDecimal(v) }, expected: "9223372036854775807", }, } scratch := make([]byte, 64) for name, tt := range cases { t.Run(name, func(t *testing.T) { b := bytes.NewBuffer(nil) root := StartElement{Name: Name{Local: "root"}} value := newValue(b, &scratch, root) tt.setter(value) if e, a := []byte(""+tt.expected+""), b.Bytes(); bytes.Compare(e, a) != 0 { t.Errorf("expected %+q, but got %+q", e, a) } }) } } func TestWrappedValue(t *testing.T) { buffer := bytes.NewBuffer(nil) scratch := make([]byte, 64) func() { root := StartElement{Name: Name{Local: "root"}} object := newValue(buffer, &scratch, root) defer object.Close() foo := StartElement{Name: Name{Local: "foo"}} faz := StartElement{Name: Name{Local: "faz"}} object.MemberElement(foo).String("bar") object.MemberElement(faz).String("baz") }() e := []byte(`barbaz`) if a := buffer.Bytes(); bytes.Compare(e, a) != 0 { t.Errorf("expected %+q, but got %+q", e, a) } } func TestWrappedValueWithNameSpaceAndAttributes(t *testing.T) { buffer := bytes.NewBuffer(nil) scratch := make([]byte, 64) func() { root := StartElement{Name: Name{Local: "root"}} object := newValue(buffer, &scratch, root) defer object.Close() foo := StartElement{Name: Name{Local: "foo"}, Attr: []Attr{ NewNamespaceAttribute("newspace", "https://endpoint.com"), NewAttribute("attrName", "attrValue"), }} faz := StartElement{Name: Name{Local: "faz"}} object.MemberElement(foo).String("bar") object.MemberElement(faz).String("baz") }() e := []byte(`barbaz`) if a := buffer.Bytes(); bytes.Compare(e, a) != 0 { t.Errorf("expected %+q, but got %+q", e, a) } }