1// comment this out // // + build testing
2
3// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
4// Use of this source code is governed by a MIT license found in the LICENSE file.
5
6package codec
7
8import (
9	"strings"
10	"time"
11)
12
13const teststrucflexChanCap = 64
14
15// This file contains values used by tests alone.
16// This is where we may try out different things,
17// that other engines may not support or may barf upon
18// e.g. custom extensions for wrapped types, maps with non-string keys, etc.
19
20// Some unused types just stored here
21type Bbool bool
22type Aarray [1]string
23type Sstring string
24type Sstructsmall struct {
25	A int
26}
27
28type Sstructbig struct {
29	A int
30	B bool
31	c string
32	// Sval Sstruct
33	Ssmallptr *Sstructsmall
34	Ssmall    *Sstructsmall
35	Sptr      *Sstructbig
36}
37
38type SstructbigMapBySlice struct {
39	_struct struct{} `codec:",toarray"`
40	A       int
41	B       bool
42	c       string
43	// Sval Sstruct
44	Ssmallptr *Sstructsmall
45	Ssmall    *Sstructsmall
46	Sptr      *Sstructbig
47}
48
49// small struct for testing that codecgen works for unexported types
50type tLowerFirstLetter struct {
51	I int
52	u uint64
53	S string
54	b []byte
55}
56
57// Some used types
58type wrapInt64 int64
59type wrapUint8 uint8
60type wrapBytes []uint8
61
62type AnonInTestStrucIntf struct {
63	Islice []interface{}
64	Ms     map[string]interface{}
65	Nintf  interface{} //don't set this, so we can test for nil
66	T      time.Time
67	Tptr   *time.Time
68}
69
70type missingFielderT1 struct {
71	S string
72	B bool
73	f float64
74	i int64
75}
76
77func (t *missingFielderT1) CodecMissingField(field []byte, value interface{}) bool {
78	// xdebugf(">> calling CodecMissingField with field: %s, value: %v", field, value)
79	switch string(field) {
80	case "F":
81		t.f = value.(float64)
82	case "I":
83		t.i = value.(int64)
84	default:
85		return false
86	}
87	return true
88}
89
90func (t *missingFielderT1) CodecMissingFields() map[string]interface{} {
91	return map[string]interface{}{"F": t.f, "I": t.i}
92}
93
94type missingFielderT2 struct {
95	S string
96	B bool
97	F float64
98	I int64
99}
100
101var testWRepeated512 wrapBytes
102var testStrucTime = time.Date(2012, 2, 2, 2, 2, 2, 2000, time.UTC).UTC()
103
104func init() {
105	var testARepeated512 [512]byte
106	for i := range testARepeated512 {
107		testARepeated512[i] = 'A'
108	}
109	testWRepeated512 = wrapBytes(testARepeated512[:])
110}
111
112type TestStrucFlex struct {
113	_struct struct{} `codec:",omitempty"` //set omitempty for every field
114	TestStrucCommon
115
116	Chstr chan string
117
118	Mis     map[int]string
119	Mbu64   map[bool]struct{}
120	Miwu64s map[int]wrapUint64Slice
121	Mfwss   map[float64]wrapStringSlice
122	Mf32wss map[float32]wrapStringSlice
123	Mui2wss map[uint64]wrapStringSlice
124	Msu2wss map[stringUint64T]wrapStringSlice
125
126	Ci64       wrapInt64
127	Swrapbytes []wrapBytes
128	Swrapuint8 []wrapUint8
129
130	ArrStrUi64T [4]stringUint64T
131
132	Ui64array      [4]uint64
133	Ui64slicearray []*[4]uint64
134
135	SintfAarray []interface{}
136
137	// make this a ptr, so that it could be set or not.
138	// for comparison (e.g. with msgp), give it a struct tag (so it is not inlined),
139	// make this one omitempty (so it is excluded if nil).
140	*AnonInTestStrucIntf `json:",omitempty"`
141
142	//M map[interface{}]interface{}  `json:"-",bson:"-"`
143	Mtsptr     map[string]*TestStrucFlex
144	Mts        map[string]TestStrucFlex
145	Its        []*TestStrucFlex
146	Nteststruc *TestStrucFlex
147}
148
149func emptyTestStrucFlex() *TestStrucFlex {
150	var ts TestStrucFlex
151	// we initialize and start draining the chan, so that we can decode into it without it blocking due to no consumer
152	ts.Chstr = make(chan string, teststrucflexChanCap)
153	go func() {
154		for range ts.Chstr {
155		}
156	}() // drain it
157	return &ts
158}
159
160func newTestStrucFlex(depth, n int, bench, useInterface, useStringKeyOnly bool) (ts *TestStrucFlex) {
161	ts = &TestStrucFlex{
162		Chstr: make(chan string, teststrucflexChanCap),
163
164		Miwu64s: map[int]wrapUint64Slice{
165			5: []wrapUint64{1, 2, 3, 4, 5},
166			3: []wrapUint64{1, 2, 3},
167		},
168
169		Mf32wss: map[float32]wrapStringSlice{
170			5.0: []wrapString{"1.0", "2.0", "3.0", "4.0", "5.0"},
171			3.0: []wrapString{"1.0", "2.0", "3.0"},
172		},
173
174		Mui2wss: map[uint64]wrapStringSlice{
175			5: []wrapString{"1.0", "2.0", "3.0", "4.0", "5.0"},
176			3: []wrapString{"1.0", "2.0", "3.0"},
177		},
178
179		Mfwss: map[float64]wrapStringSlice{
180			5.0: []wrapString{"1.0", "2.0", "3.0", "4.0", "5.0"},
181			3.0: []wrapString{"1.0", "2.0", "3.0"},
182		},
183		Mis: map[int]string{
184			1:   "one",
185			22:  "twenty two",
186			-44: "minus forty four",
187		},
188		Mbu64: map[bool]struct{}{false: {}, true: {}},
189
190		Ci64: -22,
191		Swrapbytes: []wrapBytes{ // lengths of 1, 2, 4, 8, 16, 32, 64, 128, 256,
192			testWRepeated512[:1],
193			testWRepeated512[:2],
194			testWRepeated512[:4],
195			testWRepeated512[:8],
196			testWRepeated512[:16],
197			testWRepeated512[:32],
198			testWRepeated512[:64],
199			testWRepeated512[:128],
200			testWRepeated512[:256],
201			testWRepeated512[:512],
202		},
203		Swrapuint8: []wrapUint8{
204			'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
205		},
206		Ui64array:   [4]uint64{4, 16, 64, 256},
207		ArrStrUi64T: [4]stringUint64T{{"4", 4}, {"3", 3}, {"2", 2}, {"1", 1}},
208		SintfAarray: []interface{}{Aarray{"s"}},
209	}
210
211	numChanSend := cap(ts.Chstr) / 4 // 8
212	for i := 0; i < numChanSend; i++ {
213		ts.Chstr <- strings.Repeat("A", i+1)
214	}
215
216	ts.Ui64slicearray = []*[4]uint64{&ts.Ui64array, &ts.Ui64array}
217
218	if useInterface {
219		ts.AnonInTestStrucIntf = &AnonInTestStrucIntf{
220			Islice: []interface{}{strRpt(n, "true"), true, strRpt(n, "no"), false, uint64(288), float64(0.4)},
221			Ms: map[string]interface{}{
222				strRpt(n, "true"):     strRpt(n, "true"),
223				strRpt(n, "int64(9)"): false,
224			},
225			T: testStrucTime,
226		}
227	}
228
229	populateTestStrucCommon(&ts.TestStrucCommon, n, bench, useInterface, useStringKeyOnly)
230	if depth > 0 {
231		depth--
232		if ts.Mtsptr == nil {
233			ts.Mtsptr = make(map[string]*TestStrucFlex)
234		}
235		if ts.Mts == nil {
236			ts.Mts = make(map[string]TestStrucFlex)
237		}
238		ts.Mtsptr["0"] = newTestStrucFlex(depth, n, bench, useInterface, useStringKeyOnly)
239		ts.Mts["0"] = *(ts.Mtsptr["0"])
240		ts.Its = append(ts.Its, ts.Mtsptr["0"])
241	}
242	return
243}
244