xref: /aosp_15_r20/build/blueprint/proptools/clone_test.go (revision 1fa6dee971e1612fa5cc0aa5ca2d35a22e2c34a3)
1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2015 Google Inc. All rights reserved.
2*1fa6dee9SAndroid Build Coastguard Worker//
3*1fa6dee9SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*1fa6dee9SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*1fa6dee9SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*1fa6dee9SAndroid Build Coastguard Worker//
7*1fa6dee9SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*1fa6dee9SAndroid Build Coastguard Worker//
9*1fa6dee9SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*1fa6dee9SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*1fa6dee9SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*1fa6dee9SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*1fa6dee9SAndroid Build Coastguard Worker// limitations under the License.
14*1fa6dee9SAndroid Build Coastguard Worker
15*1fa6dee9SAndroid Build Coastguard Workerpackage proptools
16*1fa6dee9SAndroid Build Coastguard Worker
17*1fa6dee9SAndroid Build Coastguard Workerimport (
18*1fa6dee9SAndroid Build Coastguard Worker	"fmt"
19*1fa6dee9SAndroid Build Coastguard Worker	"reflect"
20*1fa6dee9SAndroid Build Coastguard Worker	"testing"
21*1fa6dee9SAndroid Build Coastguard Worker)
22*1fa6dee9SAndroid Build Coastguard Worker
23*1fa6dee9SAndroid Build Coastguard Workervar clonePropertiesTestCases = []struct {
24*1fa6dee9SAndroid Build Coastguard Worker	in  interface{}
25*1fa6dee9SAndroid Build Coastguard Worker	out interface{}
26*1fa6dee9SAndroid Build Coastguard Worker	err error
27*1fa6dee9SAndroid Build Coastguard Worker}{
28*1fa6dee9SAndroid Build Coastguard Worker	// Valid inputs
29*1fa6dee9SAndroid Build Coastguard Worker
30*1fa6dee9SAndroid Build Coastguard Worker	{
31*1fa6dee9SAndroid Build Coastguard Worker		// Clone bool
32*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ B1, B2 bool }{
33*1fa6dee9SAndroid Build Coastguard Worker			B1: true,
34*1fa6dee9SAndroid Build Coastguard Worker			B2: false,
35*1fa6dee9SAndroid Build Coastguard Worker		},
36*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ B1, B2 bool }{
37*1fa6dee9SAndroid Build Coastguard Worker			B1: true,
38*1fa6dee9SAndroid Build Coastguard Worker			B2: false,
39*1fa6dee9SAndroid Build Coastguard Worker		},
40*1fa6dee9SAndroid Build Coastguard Worker	},
41*1fa6dee9SAndroid Build Coastguard Worker	{
42*1fa6dee9SAndroid Build Coastguard Worker		// Clone strings
43*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S string }{
44*1fa6dee9SAndroid Build Coastguard Worker			S: "string1",
45*1fa6dee9SAndroid Build Coastguard Worker		},
46*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S string }{
47*1fa6dee9SAndroid Build Coastguard Worker			S: "string1",
48*1fa6dee9SAndroid Build Coastguard Worker		},
49*1fa6dee9SAndroid Build Coastguard Worker	},
50*1fa6dee9SAndroid Build Coastguard Worker	{
51*1fa6dee9SAndroid Build Coastguard Worker		// Clone slice
52*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S []string }{
53*1fa6dee9SAndroid Build Coastguard Worker			S: []string{"string1"},
54*1fa6dee9SAndroid Build Coastguard Worker		},
55*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S []string }{
56*1fa6dee9SAndroid Build Coastguard Worker			S: []string{"string1"},
57*1fa6dee9SAndroid Build Coastguard Worker		},
58*1fa6dee9SAndroid Build Coastguard Worker	},
59*1fa6dee9SAndroid Build Coastguard Worker	{
60*1fa6dee9SAndroid Build Coastguard Worker		// Clone empty slice
61*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S []string }{
62*1fa6dee9SAndroid Build Coastguard Worker			S: []string{},
63*1fa6dee9SAndroid Build Coastguard Worker		},
64*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S []string }{
65*1fa6dee9SAndroid Build Coastguard Worker			S: []string{},
66*1fa6dee9SAndroid Build Coastguard Worker		},
67*1fa6dee9SAndroid Build Coastguard Worker	},
68*1fa6dee9SAndroid Build Coastguard Worker	{
69*1fa6dee9SAndroid Build Coastguard Worker		// Clone nil slice
70*1fa6dee9SAndroid Build Coastguard Worker		in:  &struct{ S []string }{},
71*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S []string }{},
72*1fa6dee9SAndroid Build Coastguard Worker	},
73*1fa6dee9SAndroid Build Coastguard Worker	{
74*1fa6dee9SAndroid Build Coastguard Worker		// Clone slice of structs
75*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S []struct{ T string } }{
76*1fa6dee9SAndroid Build Coastguard Worker			S: []struct{ T string }{
77*1fa6dee9SAndroid Build Coastguard Worker				{"string1"}, {"string2"},
78*1fa6dee9SAndroid Build Coastguard Worker			},
79*1fa6dee9SAndroid Build Coastguard Worker		},
80*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S []struct{ T string } }{
81*1fa6dee9SAndroid Build Coastguard Worker			S: []struct{ T string }{
82*1fa6dee9SAndroid Build Coastguard Worker				{"string1"}, {"string2"},
83*1fa6dee9SAndroid Build Coastguard Worker			},
84*1fa6dee9SAndroid Build Coastguard Worker		},
85*1fa6dee9SAndroid Build Coastguard Worker	},
86*1fa6dee9SAndroid Build Coastguard Worker	{
87*1fa6dee9SAndroid Build Coastguard Worker		// Clone map
88*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S map[string]string }{
89*1fa6dee9SAndroid Build Coastguard Worker			S: map[string]string{"key": "string1"},
90*1fa6dee9SAndroid Build Coastguard Worker		},
91*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S map[string]string }{
92*1fa6dee9SAndroid Build Coastguard Worker			S: map[string]string{"key": "string1"},
93*1fa6dee9SAndroid Build Coastguard Worker		},
94*1fa6dee9SAndroid Build Coastguard Worker	},
95*1fa6dee9SAndroid Build Coastguard Worker	{
96*1fa6dee9SAndroid Build Coastguard Worker		// Clone empty map
97*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S map[string]string }{
98*1fa6dee9SAndroid Build Coastguard Worker			S: map[string]string{},
99*1fa6dee9SAndroid Build Coastguard Worker		},
100*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S map[string]string }{
101*1fa6dee9SAndroid Build Coastguard Worker			S: map[string]string{},
102*1fa6dee9SAndroid Build Coastguard Worker		},
103*1fa6dee9SAndroid Build Coastguard Worker	},
104*1fa6dee9SAndroid Build Coastguard Worker	{
105*1fa6dee9SAndroid Build Coastguard Worker		// Clone nil map
106*1fa6dee9SAndroid Build Coastguard Worker		in:  &struct{ S map[string]string }{},
107*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S map[string]string }{},
108*1fa6dee9SAndroid Build Coastguard Worker	},
109*1fa6dee9SAndroid Build Coastguard Worker	{
110*1fa6dee9SAndroid Build Coastguard Worker		// Clone pointer to bool
111*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ B1, B2 *bool }{
112*1fa6dee9SAndroid Build Coastguard Worker			B1: BoolPtr(true),
113*1fa6dee9SAndroid Build Coastguard Worker			B2: BoolPtr(false),
114*1fa6dee9SAndroid Build Coastguard Worker		},
115*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ B1, B2 *bool }{
116*1fa6dee9SAndroid Build Coastguard Worker			B1: BoolPtr(true),
117*1fa6dee9SAndroid Build Coastguard Worker			B2: BoolPtr(false),
118*1fa6dee9SAndroid Build Coastguard Worker		},
119*1fa6dee9SAndroid Build Coastguard Worker	},
120*1fa6dee9SAndroid Build Coastguard Worker	{
121*1fa6dee9SAndroid Build Coastguard Worker		// Clone pointer to string
122*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S *string }{
123*1fa6dee9SAndroid Build Coastguard Worker			S: StringPtr("string1"),
124*1fa6dee9SAndroid Build Coastguard Worker		},
125*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S *string }{
126*1fa6dee9SAndroid Build Coastguard Worker			S: StringPtr("string1"),
127*1fa6dee9SAndroid Build Coastguard Worker		},
128*1fa6dee9SAndroid Build Coastguard Worker	},
129*1fa6dee9SAndroid Build Coastguard Worker	{
130*1fa6dee9SAndroid Build Coastguard Worker		// Clone pointer to int64
131*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S *int64 }{
132*1fa6dee9SAndroid Build Coastguard Worker			S: Int64Ptr(5),
133*1fa6dee9SAndroid Build Coastguard Worker		},
134*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S *int64 }{
135*1fa6dee9SAndroid Build Coastguard Worker			S: Int64Ptr(5),
136*1fa6dee9SAndroid Build Coastguard Worker		},
137*1fa6dee9SAndroid Build Coastguard Worker	},
138*1fa6dee9SAndroid Build Coastguard Worker	{
139*1fa6dee9SAndroid Build Coastguard Worker		// Clone struct
140*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S struct{ S string } }{
141*1fa6dee9SAndroid Build Coastguard Worker			S: struct{ S string }{
142*1fa6dee9SAndroid Build Coastguard Worker				S: "string1",
143*1fa6dee9SAndroid Build Coastguard Worker			},
144*1fa6dee9SAndroid Build Coastguard Worker		},
145*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S struct{ S string } }{
146*1fa6dee9SAndroid Build Coastguard Worker			S: struct{ S string }{
147*1fa6dee9SAndroid Build Coastguard Worker				S: "string1",
148*1fa6dee9SAndroid Build Coastguard Worker			},
149*1fa6dee9SAndroid Build Coastguard Worker		},
150*1fa6dee9SAndroid Build Coastguard Worker	},
151*1fa6dee9SAndroid Build Coastguard Worker	{
152*1fa6dee9SAndroid Build Coastguard Worker		// Clone struct pointer
153*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S *struct{ S string } }{
154*1fa6dee9SAndroid Build Coastguard Worker			S: &struct{ S string }{
155*1fa6dee9SAndroid Build Coastguard Worker				S: "string1",
156*1fa6dee9SAndroid Build Coastguard Worker			},
157*1fa6dee9SAndroid Build Coastguard Worker		},
158*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S *struct{ S string } }{
159*1fa6dee9SAndroid Build Coastguard Worker			S: &struct{ S string }{
160*1fa6dee9SAndroid Build Coastguard Worker				S: "string1",
161*1fa6dee9SAndroid Build Coastguard Worker			},
162*1fa6dee9SAndroid Build Coastguard Worker		},
163*1fa6dee9SAndroid Build Coastguard Worker	},
164*1fa6dee9SAndroid Build Coastguard Worker	{
165*1fa6dee9SAndroid Build Coastguard Worker		// Clone interface
166*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S interface{} }{
167*1fa6dee9SAndroid Build Coastguard Worker			S: &struct{ S string }{
168*1fa6dee9SAndroid Build Coastguard Worker				S: "string1",
169*1fa6dee9SAndroid Build Coastguard Worker			},
170*1fa6dee9SAndroid Build Coastguard Worker		},
171*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S interface{} }{
172*1fa6dee9SAndroid Build Coastguard Worker			S: &struct{ S string }{
173*1fa6dee9SAndroid Build Coastguard Worker				S: "string1",
174*1fa6dee9SAndroid Build Coastguard Worker			},
175*1fa6dee9SAndroid Build Coastguard Worker		},
176*1fa6dee9SAndroid Build Coastguard Worker	},
177*1fa6dee9SAndroid Build Coastguard Worker	{
178*1fa6dee9SAndroid Build Coastguard Worker		// Clone nested interface
179*1fa6dee9SAndroid Build Coastguard Worker		in: &struct {
180*1fa6dee9SAndroid Build Coastguard Worker			Nested struct{ S interface{} }
181*1fa6dee9SAndroid Build Coastguard Worker		}{
182*1fa6dee9SAndroid Build Coastguard Worker			Nested: struct{ S interface{} }{
183*1fa6dee9SAndroid Build Coastguard Worker				S: &struct{ S string }{
184*1fa6dee9SAndroid Build Coastguard Worker					S: "string1",
185*1fa6dee9SAndroid Build Coastguard Worker				},
186*1fa6dee9SAndroid Build Coastguard Worker			},
187*1fa6dee9SAndroid Build Coastguard Worker		},
188*1fa6dee9SAndroid Build Coastguard Worker		out: &struct {
189*1fa6dee9SAndroid Build Coastguard Worker			Nested struct{ S interface{} }
190*1fa6dee9SAndroid Build Coastguard Worker		}{
191*1fa6dee9SAndroid Build Coastguard Worker			Nested: struct{ S interface{} }{
192*1fa6dee9SAndroid Build Coastguard Worker				S: &struct{ S string }{
193*1fa6dee9SAndroid Build Coastguard Worker					S: "string1",
194*1fa6dee9SAndroid Build Coastguard Worker				},
195*1fa6dee9SAndroid Build Coastguard Worker			},
196*1fa6dee9SAndroid Build Coastguard Worker		},
197*1fa6dee9SAndroid Build Coastguard Worker	}, {
198*1fa6dee9SAndroid Build Coastguard Worker		// Empty struct
199*1fa6dee9SAndroid Build Coastguard Worker		in:  &struct{}{},
200*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{}{},
201*1fa6dee9SAndroid Build Coastguard Worker	},
202*1fa6dee9SAndroid Build Coastguard Worker	{
203*1fa6dee9SAndroid Build Coastguard Worker		// Interface nil
204*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S interface{} }{
205*1fa6dee9SAndroid Build Coastguard Worker			S: nil,
206*1fa6dee9SAndroid Build Coastguard Worker		},
207*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S interface{} }{
208*1fa6dee9SAndroid Build Coastguard Worker			S: nil,
209*1fa6dee9SAndroid Build Coastguard Worker		},
210*1fa6dee9SAndroid Build Coastguard Worker	},
211*1fa6dee9SAndroid Build Coastguard Worker	{
212*1fa6dee9SAndroid Build Coastguard Worker		// Interface pointer to nil
213*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S interface{} }{
214*1fa6dee9SAndroid Build Coastguard Worker			S: (*struct{ S string })(nil),
215*1fa6dee9SAndroid Build Coastguard Worker		},
216*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S interface{} }{
217*1fa6dee9SAndroid Build Coastguard Worker			S: (*struct{ S string })(nil),
218*1fa6dee9SAndroid Build Coastguard Worker		},
219*1fa6dee9SAndroid Build Coastguard Worker	},
220*1fa6dee9SAndroid Build Coastguard Worker	{
221*1fa6dee9SAndroid Build Coastguard Worker		// Pointer nil
222*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S *struct{} }{
223*1fa6dee9SAndroid Build Coastguard Worker			S: nil,
224*1fa6dee9SAndroid Build Coastguard Worker		},
225*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S *struct{} }{
226*1fa6dee9SAndroid Build Coastguard Worker			S: nil,
227*1fa6dee9SAndroid Build Coastguard Worker		},
228*1fa6dee9SAndroid Build Coastguard Worker	},
229*1fa6dee9SAndroid Build Coastguard Worker	{
230*1fa6dee9SAndroid Build Coastguard Worker		// Anonymous struct
231*1fa6dee9SAndroid Build Coastguard Worker		in: &struct {
232*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedStruct
233*1fa6dee9SAndroid Build Coastguard Worker			Nested struct{ EmbeddedStruct }
234*1fa6dee9SAndroid Build Coastguard Worker		}{
235*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedStruct: EmbeddedStruct{
236*1fa6dee9SAndroid Build Coastguard Worker				S: "string1",
237*1fa6dee9SAndroid Build Coastguard Worker				I: Int64Ptr(55),
238*1fa6dee9SAndroid Build Coastguard Worker			},
239*1fa6dee9SAndroid Build Coastguard Worker			Nested: struct{ EmbeddedStruct }{
240*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedStruct: EmbeddedStruct{
241*1fa6dee9SAndroid Build Coastguard Worker					S: "string2",
242*1fa6dee9SAndroid Build Coastguard Worker					I: Int64Ptr(5),
243*1fa6dee9SAndroid Build Coastguard Worker				},
244*1fa6dee9SAndroid Build Coastguard Worker			},
245*1fa6dee9SAndroid Build Coastguard Worker		},
246*1fa6dee9SAndroid Build Coastguard Worker		out: &struct {
247*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedStruct
248*1fa6dee9SAndroid Build Coastguard Worker			Nested struct{ EmbeddedStruct }
249*1fa6dee9SAndroid Build Coastguard Worker		}{
250*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedStruct: EmbeddedStruct{
251*1fa6dee9SAndroid Build Coastguard Worker				S: "string1",
252*1fa6dee9SAndroid Build Coastguard Worker				I: Int64Ptr(55),
253*1fa6dee9SAndroid Build Coastguard Worker			},
254*1fa6dee9SAndroid Build Coastguard Worker			Nested: struct{ EmbeddedStruct }{
255*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedStruct: EmbeddedStruct{
256*1fa6dee9SAndroid Build Coastguard Worker					S: "string2",
257*1fa6dee9SAndroid Build Coastguard Worker					I: Int64Ptr(5),
258*1fa6dee9SAndroid Build Coastguard Worker				},
259*1fa6dee9SAndroid Build Coastguard Worker			},
260*1fa6dee9SAndroid Build Coastguard Worker		},
261*1fa6dee9SAndroid Build Coastguard Worker	},
262*1fa6dee9SAndroid Build Coastguard Worker	{
263*1fa6dee9SAndroid Build Coastguard Worker		// Anonymous interface
264*1fa6dee9SAndroid Build Coastguard Worker		in: &struct {
265*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedInterface
266*1fa6dee9SAndroid Build Coastguard Worker			Nested struct{ EmbeddedInterface }
267*1fa6dee9SAndroid Build Coastguard Worker		}{
268*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedInterface: &struct{ S string }{
269*1fa6dee9SAndroid Build Coastguard Worker				S: "string1",
270*1fa6dee9SAndroid Build Coastguard Worker			},
271*1fa6dee9SAndroid Build Coastguard Worker			Nested: struct{ EmbeddedInterface }{
272*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedInterface: &struct{ S string }{
273*1fa6dee9SAndroid Build Coastguard Worker					S: "string2",
274*1fa6dee9SAndroid Build Coastguard Worker				},
275*1fa6dee9SAndroid Build Coastguard Worker			},
276*1fa6dee9SAndroid Build Coastguard Worker		},
277*1fa6dee9SAndroid Build Coastguard Worker		out: &struct {
278*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedInterface
279*1fa6dee9SAndroid Build Coastguard Worker			Nested struct{ EmbeddedInterface }
280*1fa6dee9SAndroid Build Coastguard Worker		}{
281*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedInterface: &struct{ S string }{
282*1fa6dee9SAndroid Build Coastguard Worker				S: "string1",
283*1fa6dee9SAndroid Build Coastguard Worker			},
284*1fa6dee9SAndroid Build Coastguard Worker			Nested: struct{ EmbeddedInterface }{
285*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedInterface: &struct{ S string }{
286*1fa6dee9SAndroid Build Coastguard Worker					S: "string2",
287*1fa6dee9SAndroid Build Coastguard Worker				},
288*1fa6dee9SAndroid Build Coastguard Worker			},
289*1fa6dee9SAndroid Build Coastguard Worker		},
290*1fa6dee9SAndroid Build Coastguard Worker	},
291*1fa6dee9SAndroid Build Coastguard Worker}
292*1fa6dee9SAndroid Build Coastguard Worker
293*1fa6dee9SAndroid Build Coastguard Workertype EmbeddedStruct struct {
294*1fa6dee9SAndroid Build Coastguard Worker	S string
295*1fa6dee9SAndroid Build Coastguard Worker	I *int64
296*1fa6dee9SAndroid Build Coastguard Worker}
297*1fa6dee9SAndroid Build Coastguard Workertype EmbeddedInterface interface{}
298*1fa6dee9SAndroid Build Coastguard Worker
299*1fa6dee9SAndroid Build Coastguard Workerfunc isPointerToEmptyStruct(v any) bool {
300*1fa6dee9SAndroid Build Coastguard Worker	t := reflect.TypeOf(v)
301*1fa6dee9SAndroid Build Coastguard Worker	if t.Kind() != reflect.Ptr {
302*1fa6dee9SAndroid Build Coastguard Worker		return false
303*1fa6dee9SAndroid Build Coastguard Worker	}
304*1fa6dee9SAndroid Build Coastguard Worker	t = t.Elem()
305*1fa6dee9SAndroid Build Coastguard Worker	if t.Kind() != reflect.Struct {
306*1fa6dee9SAndroid Build Coastguard Worker		return false
307*1fa6dee9SAndroid Build Coastguard Worker	}
308*1fa6dee9SAndroid Build Coastguard Worker	if t.NumField() > 0 {
309*1fa6dee9SAndroid Build Coastguard Worker		return false
310*1fa6dee9SAndroid Build Coastguard Worker	}
311*1fa6dee9SAndroid Build Coastguard Worker	return true
312*1fa6dee9SAndroid Build Coastguard Worker}
313*1fa6dee9SAndroid Build Coastguard Worker
314*1fa6dee9SAndroid Build Coastguard Workerfunc TestCloneProperties(t *testing.T) {
315*1fa6dee9SAndroid Build Coastguard Worker	for _, testCase := range clonePropertiesTestCases {
316*1fa6dee9SAndroid Build Coastguard Worker		testString := fmt.Sprintf("%s", testCase.in)
317*1fa6dee9SAndroid Build Coastguard Worker
318*1fa6dee9SAndroid Build Coastguard Worker		got := CloneProperties(reflect.ValueOf(testCase.in)).Interface()
319*1fa6dee9SAndroid Build Coastguard Worker
320*1fa6dee9SAndroid Build Coastguard Worker		if !reflect.DeepEqual(testCase.out, got) {
321*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("test case %s", testString)
322*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("incorrect output")
323*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("  expected: %#v", testCase.out)
324*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("       got: %#v", got)
325*1fa6dee9SAndroid Build Coastguard Worker		}
326*1fa6dee9SAndroid Build Coastguard Worker		if testCase.out == got && !isPointerToEmptyStruct(testCase.out) {
327*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("test case %s", testString)
328*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("items should be cloned, not the original")
329*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("  expected: %s", testCase.out)
330*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("       got: %s", got)
331*1fa6dee9SAndroid Build Coastguard Worker		}
332*1fa6dee9SAndroid Build Coastguard Worker	}
333*1fa6dee9SAndroid Build Coastguard Worker}
334*1fa6dee9SAndroid Build Coastguard Worker
335*1fa6dee9SAndroid Build Coastguard Workervar cloneEmptyPropertiesTestCases = []struct {
336*1fa6dee9SAndroid Build Coastguard Worker	in  interface{}
337*1fa6dee9SAndroid Build Coastguard Worker	out interface{}
338*1fa6dee9SAndroid Build Coastguard Worker	err error
339*1fa6dee9SAndroid Build Coastguard Worker}{
340*1fa6dee9SAndroid Build Coastguard Worker	// Valid inputs
341*1fa6dee9SAndroid Build Coastguard Worker
342*1fa6dee9SAndroid Build Coastguard Worker	{
343*1fa6dee9SAndroid Build Coastguard Worker		// Clone bool
344*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ B1, B2 bool }{
345*1fa6dee9SAndroid Build Coastguard Worker			B1: true,
346*1fa6dee9SAndroid Build Coastguard Worker			B2: false,
347*1fa6dee9SAndroid Build Coastguard Worker		},
348*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ B1, B2 bool }{},
349*1fa6dee9SAndroid Build Coastguard Worker	},
350*1fa6dee9SAndroid Build Coastguard Worker	{
351*1fa6dee9SAndroid Build Coastguard Worker		// Clone strings
352*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S string }{
353*1fa6dee9SAndroid Build Coastguard Worker			S: "string1",
354*1fa6dee9SAndroid Build Coastguard Worker		},
355*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S string }{},
356*1fa6dee9SAndroid Build Coastguard Worker	},
357*1fa6dee9SAndroid Build Coastguard Worker	{
358*1fa6dee9SAndroid Build Coastguard Worker		// Clone slice
359*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S []string }{
360*1fa6dee9SAndroid Build Coastguard Worker			S: []string{"string1"},
361*1fa6dee9SAndroid Build Coastguard Worker		},
362*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S []string }{},
363*1fa6dee9SAndroid Build Coastguard Worker	},
364*1fa6dee9SAndroid Build Coastguard Worker	{
365*1fa6dee9SAndroid Build Coastguard Worker		// Clone empty slice
366*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S []string }{
367*1fa6dee9SAndroid Build Coastguard Worker			S: []string{},
368*1fa6dee9SAndroid Build Coastguard Worker		},
369*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S []string }{},
370*1fa6dee9SAndroid Build Coastguard Worker	},
371*1fa6dee9SAndroid Build Coastguard Worker	{
372*1fa6dee9SAndroid Build Coastguard Worker		// Clone nil slice
373*1fa6dee9SAndroid Build Coastguard Worker		in:  &struct{ S []string }{},
374*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S []string }{},
375*1fa6dee9SAndroid Build Coastguard Worker	},
376*1fa6dee9SAndroid Build Coastguard Worker	{
377*1fa6dee9SAndroid Build Coastguard Worker		// Clone slice of structs
378*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S []struct{ T string } }{
379*1fa6dee9SAndroid Build Coastguard Worker			S: []struct{ T string }{
380*1fa6dee9SAndroid Build Coastguard Worker				{"string1"}, {"string2"},
381*1fa6dee9SAndroid Build Coastguard Worker			},
382*1fa6dee9SAndroid Build Coastguard Worker		},
383*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S []struct{ T string } }{
384*1fa6dee9SAndroid Build Coastguard Worker			S: []struct{ T string }(nil),
385*1fa6dee9SAndroid Build Coastguard Worker		},
386*1fa6dee9SAndroid Build Coastguard Worker	},
387*1fa6dee9SAndroid Build Coastguard Worker	{
388*1fa6dee9SAndroid Build Coastguard Worker		// Clone pointer to bool
389*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ B1, B2 *bool }{
390*1fa6dee9SAndroid Build Coastguard Worker			B1: BoolPtr(true),
391*1fa6dee9SAndroid Build Coastguard Worker			B2: BoolPtr(false),
392*1fa6dee9SAndroid Build Coastguard Worker		},
393*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ B1, B2 *bool }{},
394*1fa6dee9SAndroid Build Coastguard Worker	},
395*1fa6dee9SAndroid Build Coastguard Worker	{
396*1fa6dee9SAndroid Build Coastguard Worker		// Clone pointer to int64
397*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ B1, B2 *int64 }{
398*1fa6dee9SAndroid Build Coastguard Worker			B1: Int64Ptr(5),
399*1fa6dee9SAndroid Build Coastguard Worker			B2: Int64Ptr(4),
400*1fa6dee9SAndroid Build Coastguard Worker		},
401*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ B1, B2 *int64 }{},
402*1fa6dee9SAndroid Build Coastguard Worker	},
403*1fa6dee9SAndroid Build Coastguard Worker	{
404*1fa6dee9SAndroid Build Coastguard Worker		// Clone pointer to string
405*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S *string }{
406*1fa6dee9SAndroid Build Coastguard Worker			S: StringPtr("string1"),
407*1fa6dee9SAndroid Build Coastguard Worker		},
408*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S *string }{},
409*1fa6dee9SAndroid Build Coastguard Worker	},
410*1fa6dee9SAndroid Build Coastguard Worker	{
411*1fa6dee9SAndroid Build Coastguard Worker		// Clone struct
412*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S struct{ S string } }{
413*1fa6dee9SAndroid Build Coastguard Worker			S: struct{ S string }{
414*1fa6dee9SAndroid Build Coastguard Worker				S: "string1",
415*1fa6dee9SAndroid Build Coastguard Worker			},
416*1fa6dee9SAndroid Build Coastguard Worker		},
417*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S struct{ S string } }{
418*1fa6dee9SAndroid Build Coastguard Worker			S: struct{ S string }{},
419*1fa6dee9SAndroid Build Coastguard Worker		},
420*1fa6dee9SAndroid Build Coastguard Worker	},
421*1fa6dee9SAndroid Build Coastguard Worker	{
422*1fa6dee9SAndroid Build Coastguard Worker		// Clone struct pointer
423*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S *struct{ S string } }{
424*1fa6dee9SAndroid Build Coastguard Worker			S: &struct{ S string }{
425*1fa6dee9SAndroid Build Coastguard Worker				S: "string1",
426*1fa6dee9SAndroid Build Coastguard Worker			},
427*1fa6dee9SAndroid Build Coastguard Worker		},
428*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S *struct{ S string } }{
429*1fa6dee9SAndroid Build Coastguard Worker			S: &struct{ S string }{},
430*1fa6dee9SAndroid Build Coastguard Worker		},
431*1fa6dee9SAndroid Build Coastguard Worker	},
432*1fa6dee9SAndroid Build Coastguard Worker	{
433*1fa6dee9SAndroid Build Coastguard Worker		// Clone interface
434*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S interface{} }{
435*1fa6dee9SAndroid Build Coastguard Worker			S: &struct{ S string }{
436*1fa6dee9SAndroid Build Coastguard Worker				S: "string1",
437*1fa6dee9SAndroid Build Coastguard Worker			},
438*1fa6dee9SAndroid Build Coastguard Worker		},
439*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S interface{} }{
440*1fa6dee9SAndroid Build Coastguard Worker			S: &struct{ S string }{},
441*1fa6dee9SAndroid Build Coastguard Worker		},
442*1fa6dee9SAndroid Build Coastguard Worker	},
443*1fa6dee9SAndroid Build Coastguard Worker	{
444*1fa6dee9SAndroid Build Coastguard Worker		// Clone nested interface
445*1fa6dee9SAndroid Build Coastguard Worker		in: &struct {
446*1fa6dee9SAndroid Build Coastguard Worker			Nested struct{ S interface{} }
447*1fa6dee9SAndroid Build Coastguard Worker		}{
448*1fa6dee9SAndroid Build Coastguard Worker			Nested: struct{ S interface{} }{
449*1fa6dee9SAndroid Build Coastguard Worker				S: &struct{ S string }{
450*1fa6dee9SAndroid Build Coastguard Worker					S: "string1",
451*1fa6dee9SAndroid Build Coastguard Worker				},
452*1fa6dee9SAndroid Build Coastguard Worker			},
453*1fa6dee9SAndroid Build Coastguard Worker		},
454*1fa6dee9SAndroid Build Coastguard Worker		out: &struct {
455*1fa6dee9SAndroid Build Coastguard Worker			Nested struct{ S interface{} }
456*1fa6dee9SAndroid Build Coastguard Worker		}{
457*1fa6dee9SAndroid Build Coastguard Worker			Nested: struct{ S interface{} }{
458*1fa6dee9SAndroid Build Coastguard Worker				S: &struct{ S string }{},
459*1fa6dee9SAndroid Build Coastguard Worker			},
460*1fa6dee9SAndroid Build Coastguard Worker		},
461*1fa6dee9SAndroid Build Coastguard Worker	},
462*1fa6dee9SAndroid Build Coastguard Worker	{
463*1fa6dee9SAndroid Build Coastguard Worker		// Empty struct
464*1fa6dee9SAndroid Build Coastguard Worker		in:  &struct{}{},
465*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{}{},
466*1fa6dee9SAndroid Build Coastguard Worker	},
467*1fa6dee9SAndroid Build Coastguard Worker	{
468*1fa6dee9SAndroid Build Coastguard Worker		// Interface nil
469*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S interface{} }{
470*1fa6dee9SAndroid Build Coastguard Worker			S: nil,
471*1fa6dee9SAndroid Build Coastguard Worker		},
472*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S interface{} }{},
473*1fa6dee9SAndroid Build Coastguard Worker	},
474*1fa6dee9SAndroid Build Coastguard Worker	{
475*1fa6dee9SAndroid Build Coastguard Worker		// Interface pointer to nil
476*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S interface{} }{
477*1fa6dee9SAndroid Build Coastguard Worker			S: (*struct{ S string })(nil),
478*1fa6dee9SAndroid Build Coastguard Worker		},
479*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S interface{} }{
480*1fa6dee9SAndroid Build Coastguard Worker			S: (*struct{ S string })(nil),
481*1fa6dee9SAndroid Build Coastguard Worker		},
482*1fa6dee9SAndroid Build Coastguard Worker	},
483*1fa6dee9SAndroid Build Coastguard Worker	{
484*1fa6dee9SAndroid Build Coastguard Worker		// Pointer nil
485*1fa6dee9SAndroid Build Coastguard Worker		in: &struct{ S *struct{} }{
486*1fa6dee9SAndroid Build Coastguard Worker			S: nil,
487*1fa6dee9SAndroid Build Coastguard Worker		},
488*1fa6dee9SAndroid Build Coastguard Worker		out: &struct{ S *struct{} }{},
489*1fa6dee9SAndroid Build Coastguard Worker	},
490*1fa6dee9SAndroid Build Coastguard Worker	{
491*1fa6dee9SAndroid Build Coastguard Worker		// Anonymous struct
492*1fa6dee9SAndroid Build Coastguard Worker		in: &struct {
493*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedStruct
494*1fa6dee9SAndroid Build Coastguard Worker			Nested struct{ EmbeddedStruct }
495*1fa6dee9SAndroid Build Coastguard Worker		}{
496*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedStruct: EmbeddedStruct{
497*1fa6dee9SAndroid Build Coastguard Worker				S: "string1",
498*1fa6dee9SAndroid Build Coastguard Worker			},
499*1fa6dee9SAndroid Build Coastguard Worker			Nested: struct{ EmbeddedStruct }{
500*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedStruct: EmbeddedStruct{
501*1fa6dee9SAndroid Build Coastguard Worker					S: "string2",
502*1fa6dee9SAndroid Build Coastguard Worker				},
503*1fa6dee9SAndroid Build Coastguard Worker			},
504*1fa6dee9SAndroid Build Coastguard Worker		},
505*1fa6dee9SAndroid Build Coastguard Worker		out: &struct {
506*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedStruct
507*1fa6dee9SAndroid Build Coastguard Worker			Nested struct{ EmbeddedStruct }
508*1fa6dee9SAndroid Build Coastguard Worker		}{
509*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedStruct: EmbeddedStruct{},
510*1fa6dee9SAndroid Build Coastguard Worker			Nested: struct{ EmbeddedStruct }{
511*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedStruct: EmbeddedStruct{},
512*1fa6dee9SAndroid Build Coastguard Worker			},
513*1fa6dee9SAndroid Build Coastguard Worker		},
514*1fa6dee9SAndroid Build Coastguard Worker	},
515*1fa6dee9SAndroid Build Coastguard Worker	{
516*1fa6dee9SAndroid Build Coastguard Worker		// Anonymous interface
517*1fa6dee9SAndroid Build Coastguard Worker		in: &struct {
518*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedInterface
519*1fa6dee9SAndroid Build Coastguard Worker			Nested struct{ EmbeddedInterface }
520*1fa6dee9SAndroid Build Coastguard Worker		}{
521*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedInterface: &struct{ S string }{
522*1fa6dee9SAndroid Build Coastguard Worker				S: "string1",
523*1fa6dee9SAndroid Build Coastguard Worker			},
524*1fa6dee9SAndroid Build Coastguard Worker			Nested: struct{ EmbeddedInterface }{
525*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedInterface: &struct{ S string }{
526*1fa6dee9SAndroid Build Coastguard Worker					S: "string2",
527*1fa6dee9SAndroid Build Coastguard Worker				},
528*1fa6dee9SAndroid Build Coastguard Worker			},
529*1fa6dee9SAndroid Build Coastguard Worker		},
530*1fa6dee9SAndroid Build Coastguard Worker		out: &struct {
531*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedInterface
532*1fa6dee9SAndroid Build Coastguard Worker			Nested struct{ EmbeddedInterface }
533*1fa6dee9SAndroid Build Coastguard Worker		}{
534*1fa6dee9SAndroid Build Coastguard Worker			EmbeddedInterface: &struct{ S string }{},
535*1fa6dee9SAndroid Build Coastguard Worker			Nested: struct{ EmbeddedInterface }{
536*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedInterface: &struct{ S string }{},
537*1fa6dee9SAndroid Build Coastguard Worker			},
538*1fa6dee9SAndroid Build Coastguard Worker		},
539*1fa6dee9SAndroid Build Coastguard Worker	},
540*1fa6dee9SAndroid Build Coastguard Worker}
541*1fa6dee9SAndroid Build Coastguard Worker
542*1fa6dee9SAndroid Build Coastguard Workerfunc TestCloneEmptyProperties(t *testing.T) {
543*1fa6dee9SAndroid Build Coastguard Worker	for _, testCase := range cloneEmptyPropertiesTestCases {
544*1fa6dee9SAndroid Build Coastguard Worker		testString := fmt.Sprintf("%#v", testCase.in)
545*1fa6dee9SAndroid Build Coastguard Worker
546*1fa6dee9SAndroid Build Coastguard Worker		got := CloneEmptyProperties(reflect.ValueOf(testCase.in)).Interface()
547*1fa6dee9SAndroid Build Coastguard Worker
548*1fa6dee9SAndroid Build Coastguard Worker		if !reflect.DeepEqual(testCase.out, got) {
549*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("test case %s", testString)
550*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("incorrect output")
551*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("  expected: %#v", testCase.out)
552*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("       got: %#v", got)
553*1fa6dee9SAndroid Build Coastguard Worker		}
554*1fa6dee9SAndroid Build Coastguard Worker	}
555*1fa6dee9SAndroid Build Coastguard Worker}
556*1fa6dee9SAndroid Build Coastguard Worker
557*1fa6dee9SAndroid Build Coastguard Workerfunc TestZeroProperties(t *testing.T) {
558*1fa6dee9SAndroid Build Coastguard Worker	for _, testCase := range cloneEmptyPropertiesTestCases {
559*1fa6dee9SAndroid Build Coastguard Worker		testString := fmt.Sprintf("%#v", testCase.in)
560*1fa6dee9SAndroid Build Coastguard Worker
561*1fa6dee9SAndroid Build Coastguard Worker		got := CloneProperties(reflect.ValueOf(testCase.in)).Interface()
562*1fa6dee9SAndroid Build Coastguard Worker		ZeroProperties(reflect.ValueOf(got))
563*1fa6dee9SAndroid Build Coastguard Worker
564*1fa6dee9SAndroid Build Coastguard Worker		if !reflect.DeepEqual(testCase.out, got) {
565*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("test case %s", testString)
566*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("incorrect output")
567*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("  expected: %#v", testCase.out)
568*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("       got: %#v", got)
569*1fa6dee9SAndroid Build Coastguard Worker		}
570*1fa6dee9SAndroid Build Coastguard Worker	}
571*1fa6dee9SAndroid Build Coastguard Worker}
572