func TestCompositeTypes(t *testing.T) {
	var (
		jmref = jmr("jmr")
		jmval = jmv([]string{"a", "b", "c"})
	)
	testdata := []interface{}{
		[]uint{},
		[]int{1, 2, 3},
		[]int(nil),
		(*[]int)(nil),
		[]string{"a", "b", "c"},
		[2]bool{true, false},
		(*[4]string)(nil),
		map[string]int{"a": 1, "b": 2},
		&map[int]string{1: "a", 2: "b"},
		(map[string]int)(nil),
		time.Now(),
		3*time.Minute + 35*time.Second,
		jmref,
		&jmref,
		jmval,
		&jmval,
	}
	for _, v := range testdata {
		marshalCompare(t, v, "")
	}
}
TestCompositeTypes tests the marshaling of composite types.
package jettison
import (
	"bytes"
	"context"
	"crypto/rand"
	"encoding/json"
	"errors"
	"fmt"
	"math"
	"math/big"
	"net"
	"reflect"
	"regexp"
	"strconv"
	"sync"
	"testing"
	"time"
)
type (
	jmr string
	jmv []string
)
func (*jmr) MarshalJSON() ([]byte, error) { return []byte(`"XYZ"`), nil }
func (jmv) MarshalJSON() ([]byte, error)  { return []byte(`"ZYX"`), nil }
type (
	mapss struct {
		M map[string]string
	}
	inner struct {
		M map[string]string
	}
	outer struct {
		M map[string]inner
	}
	z struct {
		S []byte
	}
	y struct {
		P float64 `json:"p,omitempty"`
		Q uint64  `json:"q,omitempty"`
		R uint8
	}
	x struct {
		A  *string `json:"a,string"`
		B1 int64   `json:"b1,string"`
		B2 uint16  `json:"b2"`
		C  *bool   `json:"c,string"`
		D  float32
		E1 *[]int
		E2 []string
		E3 []jmr
		F1 [4]string
		F2 [1]jmr
		F3 *[1]jmr
		G1 map[int]*string
		G2 map[string]*map[string]string
		G3 map[int]map[string]map[int]string
		G4 map[string]mapss
		G5 outer
		G6 map[int]jmr
		G7 map[int]*jmr
		G8 map[int]bool `json:",omitempty"`
		H1 jmr
		H2 *jmr
		H3 jmv
		H4 *jmv
		I  time.Time
		J  time.Duration
		K  json.Number
		L  json.RawMessage
		M1 interface{}
		M2 interface{}
		N  struct{}
		X  *x
		*y
		z `json:"z"`
	}
)
var (
	s  = "Loreum"
	b  = true
	m  = map[string]string{"b": "c"}
	xx = x{
		A:  &s,
		B1: -42,
		B2: 42,
		C:  &b,
		D:  math.MaxFloat32,
		E1: &[]int{1, 2, 3},
		E2: []string{"x", "y", "z"},
		E3: []jmr{"1"},
		F1: [4]string{"a", "b", "c", "d"},
		F2: [1]jmr{"1"},
		F3: &[1]jmr{"1"},
		G1: map[int]*string{2: &s, 3: new(string)},
		G2: map[string]*map[string]string{"a": &m},
		G3: map[int]map[string]map[int]string{1: {"a": {2: "b"}}},
		G4: map[string]mapss{"1": {M: map[string]string{"2": "3"}}},
		G5: outer{map[string]inner{"outer": {map[string]string{"key": "val"}}}},
		G6: map[int]jmr{1: "jmr"},
		G7: map[int]*jmr{1: new(jmr)},
		G8: map[int]bool{},
		H1: "jmp",
		H2: nil,
		H3: nil,
		H4: nil,
		I:  time.Now(),
		J:  3 * time.Minute,
		K:  "3.14",
		L:  []byte(`{ "a":"b" }`),
		M1: uint32(255),
		M2: &s,
		X:  &x{H1: "jmv"},
		y:  &y{R: math.MaxUint8},
		z:  z{S: []byte("Loreum")},
	}
)
func marshalCompare(t *testing.T, v interface{}, name string) {
	jb1, err := Marshal(v)
	if err != nil {
		t.Fatal(err)
	}
	jb2, err := MarshalOpts(v)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(jb1, jb2) {
		t.Error("non-equal outputs for Marshal and MarshalOpts")
	}
	jb3, err := Append([]byte(nil), v)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(jb1, jb3) {
		t.Error("non-equal outputs for Marshal and Append")
	}
	sb, err := json.Marshal(v)
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("standard: %s", string(sb))
	t.Logf("jettison: %s", string(jb1))
	if !bytes.Equal(jb1, sb) {
		t.Errorf("%s: non-equal outputs", name)
	}
}
func marshalCompareError(t *testing.T, v interface{}, name string) {
	_, errj := Marshal(v)
	if errj == nil {
		t.Fatalf("expected non-nil error")
	}
	_, errs := json.Marshal(v)
	if errs == nil {
		t.Fatalf("expected non-nil error")
	}
	t.Logf("standard: %s", errs)
	t.Logf("jettison: %s", errj)
	if errs.Error() != errj.Error() {
		t.Errorf("%s: non-equal outputs", name)
	}
}
func TestAll(t *testing.T) {
	marshalCompare(t, nil, "nil")
	marshalCompare(t, xx, "non-pointer")
	marshalCompare(t, &xx, "pointer")
}
func TestInvalidEncodeOpts(t *testing.T) {
	for _, opt := range []Option{
		TimeLayout(""),
		DurationFormat(DurationFmt(-1)),
		DurationFormat(DurationFmt(6)),
		WithContext(nil),  
	} {
		_, err1 := MarshalOpts(struct{}{}, opt)
		_, err2 := AppendOpts([]byte(nil), struct{}{}, opt)
		for _, err := range []error{err1, err2} {
			if err != nil {
				e, ok := err.(*InvalidOptionError)
				if !ok {
					t.Errorf("got %T, want InvalidOptionError", err)
				}
				if e.Error() == "" {
					t.Errorf("expected non-empty error message")
				}
			} else {
				t.Error("expected non-nil error")
			}
		}
	}
}
func TestBasicTypes(t *testing.T) {
	testdata := []interface{}{
		true,
		false,
		"Loreum",
		int8(math.MaxInt8),
		int16(math.MaxInt16),
		int32(math.MaxInt32),
		int64(math.MaxInt64),
		uint8(math.MaxUint8),
		uint16(math.MaxUint16),
		uint32(math.MaxUint32),
		uint64(math.MaxUint64),
		uintptr(0xBEEF),
		(*bool)(nil),
		(*int)(nil),
		(*string)(nil),
	}
	for _, v := range testdata {
		marshalCompare(t, v, "")
	}
}