1// Copyright 2020 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package proptools
16
17import (
18	"reflect"
19	"testing"
20)
21
22func TestPropertyNameForField(t *testing.T) {
23	tests := []struct {
24		name  string
25		input string
26		want  string
27	}{
28		{
29			name:  "short",
30			input: "S",
31			want:  "s",
32		},
33		{
34			name:  "long",
35			input: "String",
36			want:  "string",
37		},
38		{
39			name:  "uppercase",
40			input: "STRING",
41			want:  "STRING",
42		},
43		{
44			name:  "mixed",
45			input: "StRiNg",
46			want:  "stRiNg",
47		},
48		{
49			name:  "underscore",
50			input: "Under_score",
51			want:  "under_score",
52		},
53		{
54			name:  "uppercase underscore",
55			input: "UNDER_SCORE",
56			want:  "UNDER_SCORE",
57		},
58		{
59			name:  "x86",
60			input: "X86",
61			want:  "x86",
62		},
63		{
64			name:  "x86_64",
65			input: "X86_64",
66			want:  "x86_64",
67		},
68	}
69	for _, tt := range tests {
70		t.Run(tt.name, func(t *testing.T) {
71			if got := PropertyNameForField(tt.input); got != tt.want {
72				t.Errorf("PropertyNameForField(%v) = %v, want %v", tt.input, got, tt.want)
73			}
74		})
75	}
76}
77
78func TestFieldNameForProperty(t *testing.T) {
79	tests := []struct {
80		name  string
81		input string
82		want  string
83	}{
84		{
85			name:  "short lowercase",
86			input: "s",
87			want:  "S",
88		},
89		{
90			name:  "short uppercase",
91			input: "S",
92			want:  "S",
93		},
94		{
95			name:  "long lowercase",
96			input: "string",
97			want:  "String",
98		},
99		{
100			name:  "long uppercase",
101			input: "STRING",
102			want:  "STRING",
103		},
104		{
105			name:  "mixed",
106			input: "StRiNg",
107			want:  "StRiNg",
108		},
109	}
110	for _, tt := range tests {
111		t.Run(tt.name, func(t *testing.T) {
112			if got := FieldNameForProperty(tt.input); got != tt.want {
113				t.Errorf("FieldNameForProperty(%v) = %v, want %v", tt.input, got, tt.want)
114			}
115		})
116	}
117}
118
119func TestClearField(t *testing.T) {
120	props := struct {
121		i  int
122		s  string
123		ps *string
124		ss []string
125		c  struct {
126			n int
127		}
128	}{}
129
130	props.i = 42
131	Clear(&props.i)
132	if props.i != 0 {
133		t.Error("int field is not cleared to zero.")
134	}
135
136	props.s = "foo"
137	Clear(&props.s)
138	if props.s != "" {
139		t.Error("string field is not cleared to zero.")
140	}
141
142	props.ps = StringPtr("foo")
143	Clear(&props.ps)
144	if props.ps != nil {
145		t.Error("string pointer field is not cleared to zero.")
146	}
147
148	props.ss = []string{"foo"}
149	Clear(&props.ss)
150	if props.ss != nil {
151		t.Error("string array field is not cleared to zero.")
152	}
153
154	props.c.n = 42
155	Clear(&props.c)
156	if props.c.n != 0 {
157		t.Error("struct field is not cleared to zero.")
158	}
159}
160
161func TestIsConfigurable(t *testing.T) {
162	testCases := []struct {
163		name     string
164		value    interface{}
165		expected bool
166	}{
167		{
168			name:     "Configurable string",
169			value:    Configurable[string]{},
170			expected: true,
171		},
172		{
173			name:     "Configurable string list",
174			value:    Configurable[[]string]{},
175			expected: true,
176		},
177		{
178			name:     "Configurable bool",
179			value:    Configurable[bool]{},
180			expected: true,
181		},
182		{
183			name: "Other struct with a bool as the first field",
184			value: struct {
185				x bool
186			}{},
187			expected: false,
188		},
189	}
190	for _, tc := range testCases {
191		t.Run(tc.name, func(t *testing.T) {
192			value := reflect.ValueOf(tc.value)
193			if isConfigurable(value.Type()) != tc.expected {
194				t.Errorf("Expected isConfigurable to return %t", tc.expected)
195			}
196		})
197	}
198}
199