1// Copyright (C) 2024 The Android Open Source Project
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 templatefns
16
17import (
18	"errors"
19	"testing"
20)
21
22var caseTests = []struct {
23	input, kebabCase, snakeCase, titleCase, upperCamelCase, lowerCamelCase string
24}{
25	{
26		input:     "",
27		kebabCase: "", snakeCase: "", titleCase: "", upperCamelCase: "", lowerCamelCase: ""},
28	{
29		input:     "f",
30		kebabCase: "f", snakeCase: "f", titleCase: "F", upperCamelCase: "F", lowerCamelCase: "f"},
31	{
32		input:     "foo",
33		kebabCase: "foo", snakeCase: "foo", titleCase: "Foo", upperCamelCase: "Foo", lowerCamelCase: "foo"},
34	{
35		input:     " foo_bar",
36		kebabCase: "foo-bar", snakeCase: "foo_bar", titleCase: "Foo Bar", upperCamelCase: "FooBar", lowerCamelCase: "fooBar"},
37	{
38		input:     " foo-bar",
39		kebabCase: "foo-bar", snakeCase: "foo_bar", titleCase: "Foo Bar", upperCamelCase: "FooBar", lowerCamelCase: "fooBar"},
40	{
41		input:     " foo bar",
42		kebabCase: "foo-bar", snakeCase: "foo_bar", titleCase: "Foo Bar", upperCamelCase: "FooBar", lowerCamelCase: "fooBar"},
43	{
44		input:     " Foo Bar",
45		kebabCase: "foo-bar", snakeCase: "foo_bar", titleCase: "Foo Bar", upperCamelCase: "FooBar", lowerCamelCase: "fooBar"},
46	{
47		input:     "HTTP_status_code",
48		kebabCase: "http-status-code", snakeCase: "http_status_code", titleCase: "HTTP Status Code", upperCamelCase: "HTTPStatusCode", lowerCamelCase: "httpStatusCode"},
49	{
50		input:     "foo   many spaces",
51		kebabCase: "foo-many-spaces", snakeCase: "foo_many_spaces", titleCase: "Foo Many Spaces", upperCamelCase: "FooManySpaces", lowerCamelCase: "fooManySpaces"},
52	{
53		input:     "foo---many-dashes",
54		kebabCase: "foo-many-dashes", snakeCase: "foo_many_dashes", titleCase: "Foo Many Dashes", upperCamelCase: "FooManyDashes", lowerCamelCase: "fooManyDashes"},
55	{
56		input:     "foo___many_underline",
57		kebabCase: "foo-many-underline", snakeCase: "foo_many_underline", titleCase: "Foo Many Underline", upperCamelCase: "FooManyUnderline", lowerCamelCase: "fooManyUnderline"},
58	{
59		input:     "UpperCamelCase",
60		kebabCase: "upper-camel-case", snakeCase: "upper_camel_case", titleCase: "Upper Camel Case", upperCamelCase: "UpperCamelCase", lowerCamelCase: "upperCamelCase"},
61	{
62		input:     "ACRONYMInUpperCamelCase",
63		kebabCase: "acronym-in-upper-camel-case", snakeCase: "acronym_in_upper_camel_case", titleCase: "ACRONYM In Upper Camel Case", upperCamelCase: "ACRONYMInUpperCamelCase", lowerCamelCase: "acronymInUpperCamelCase"},
64	{
65		input:     "FooGRPCHandler",
66		kebabCase: "foo-grpc-handler", snakeCase: "foo_grpc_handler", titleCase: "Foo GRPC Handler", upperCamelCase: "FooGRPCHandler", lowerCamelCase: "fooGRPCHandler"},
67	{
68		input:     "GRPC1234Handler",
69		kebabCase: "grpc1234-handler", snakeCase: "grpc1234_handler", titleCase: "GRPC1234 Handler", upperCamelCase: "GRPC1234Handler", lowerCamelCase: "grpc1234Handler"},
70	{
71		input:     "tricky4567number",
72		kebabCase: "tricky4567-number", snakeCase: "tricky4567_number", titleCase: "Tricky4567 Number", upperCamelCase: "Tricky4567Number", lowerCamelCase: "tricky4567Number"},
73	{
74		input:     "tricky 4567number",
75		kebabCase: "tricky-4567-number", snakeCase: "tricky_4567_number", titleCase: "Tricky 4567 Number", upperCamelCase: "Tricky4567Number", lowerCamelCase: "tricky4567Number"},
76	{
77		input:     "tricky 4567Number",
78		kebabCase: "tricky-4567-number", snakeCase: "tricky_4567_number", titleCase: "Tricky 4567 Number", upperCamelCase: "Tricky4567Number", lowerCamelCase: "tricky4567Number"},
79	{
80		input:     "tricky 4567 Number",
81		kebabCase: "tricky-4567-number", snakeCase: "tricky_4567_number", titleCase: "Tricky 4567 Number", upperCamelCase: "Tricky4567Number", lowerCamelCase: "tricky4567Number"},
82	{
83		input:     "lowerCamelCase",
84		kebabCase: "lower-camel-case", snakeCase: "lower_camel_case", titleCase: "Lower Camel Case", upperCamelCase: "LowerCamelCase", lowerCamelCase: "lowerCamelCase"},
85	{
86		input:     "endInCapitalT",
87		kebabCase: "end-in-capital-t", snakeCase: "end_in_capital_t", titleCase: "End In Capital T", upperCamelCase: "EndInCapitalT", lowerCamelCase: "endInCapitalT"},
88	{
89		input:     "snake_case",
90		kebabCase: "snake-case", snakeCase: "snake_case", titleCase: "Snake Case", upperCamelCase: "SnakeCase", lowerCamelCase: "snakeCase"},
91	{
92		input:     "kebab-case",
93		kebabCase: "kebab-case", snakeCase: "kebab_case", titleCase: "Kebab Case", upperCamelCase: "KebabCase", lowerCamelCase: "kebabCase"},
94	{
95		input:     "üñicödeCäse",
96		kebabCase: "üñicöde-cäse", snakeCase: "üñicöde_cäse", titleCase: "Üñicöde Cäse", upperCamelCase: "ÜñicödeCäse", lowerCamelCase: "üñicödeCäse"}}
97
98func TestKebabCase(t *testing.T) {
99	for _, tt := range caseTests {
100		t.Run(tt.input, func(t *testing.T) {
101			if got := kebabCase(tt.input); got != tt.kebabCase {
102				t.Fatalf("KebabCase(%q) = %q, want %q", tt.input, got, tt.kebabCase)
103			}
104		})
105	}
106}
107
108func TestSnakeCase(t *testing.T) {
109	for _, tt := range caseTests {
110		t.Run(tt.input, func(t *testing.T) {
111			if got := snakeCase(tt.input); got != tt.snakeCase {
112				t.Fatalf("SnakeCase(%q) = %q, want %q", tt.input, got, tt.snakeCase)
113			}
114		})
115	}
116}
117
118func TestTitleCase(t *testing.T) {
119	for _, tt := range caseTests {
120		t.Run(tt.input, func(t *testing.T) {
121			if got := titleCase(tt.input); got != tt.titleCase {
122				t.Fatalf("TitleCase(%q) = %q, want %q", tt.input, got, tt.titleCase)
123			}
124		})
125	}
126}
127
128func TestUpperCamelCase(t *testing.T) {
129	for _, tt := range caseTests {
130		t.Run(tt.input, func(t *testing.T) {
131			if got := upperCamelCase(tt.input); got != tt.upperCamelCase {
132				t.Fatalf("upperCamelCase(%q) = %q, want %q", tt.input, got, tt.upperCamelCase)
133			}
134		})
135	}
136}
137
138func TestLowerCamelCase(t *testing.T) {
139	for _, tt := range caseTests {
140		t.Run(tt.input, func(t *testing.T) {
141			if got := lowerCamelCase(tt.input); got != tt.lowerCamelCase {
142				t.Fatalf("lowerCamelCase(%q) = %q, want %q", tt.input, got, tt.lowerCamelCase)
143			}
144		})
145	}
146}
147
148func TestDict(t *testing.T) {
149	errorValue := errors.New("error_value")
150	var dictTest = []struct {
151		values []any
152		want   map[string]any
153	}{
154		{
155			values: []any{1, 2, 3},
156			want: map[string]any{
157				"1": 2,
158				"3": nil,
159			},
160		},
161		{
162			values: []any{"foo", "bar"},
163			want:   map[string]any{"foo": "bar"},
164		},
165		{
166			values: []any{errors.New("error_key"), errorValue},
167			want:   map[string]any{"error_key": errorValue},
168		},
169	}
170	for _, tt := range dictTest {
171		got := dict(tt.values...)
172		for k, v := range tt.want {
173			if got[k] != v {
174				t.Fatalf("dict(%v)[%q] = %q, want %q", tt.values, k, got[k], v)
175			}
176		}
177	}
178}
179