github.com/oam-dev/kubevela@v1.9.11/references/cuegen/tag_test.go (about) 1 /* 2 Copyright 2023 The KubeVela Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package cuegen 18 19 import ( 20 "testing" 21 22 "github.com/stretchr/testify/assert" 23 ) 24 25 func str(s string) *string { 26 return &s 27 } 28 29 func TestGeneratorParseTag(t *testing.T) { 30 tests := []struct { 31 name string 32 tag string 33 opts *tagOptions 34 }{ 35 {"empty", "", &tagOptions{}}, 36 {"only_name", `json:"name"`, &tagOptions{Name: "name", Enum: []string{}}}, 37 {"only_name_2", `json:""`, &tagOptions{Name: "", Enum: []string{}}}, 38 {"only_name_3", `json:"-"`, &tagOptions{Name: "-", Enum: []string{}}}, 39 {"json_omitempty", `json:"name,omitempty"`, &tagOptions{Name: "name", Optional: true, Enum: []string{}}}, 40 {"json_omitempty_2", `json:"name,omitempty,omitempty"`, &tagOptions{Name: "name", Optional: true, Enum: []string{}}}, 41 {"json_omitempty_3", `json:",omitempty"`, &tagOptions{Name: "", Optional: true, Enum: []string{}}}, 42 {"json_inline", `json:",inline"`, &tagOptions{Name: "", Inline: true, Enum: []string{}}}, 43 {"json_inline_2", `json:"name,inline"`, &tagOptions{Name: "name", Inline: true, Enum: []string{}}}, 44 {"json_inline_3", `json:"name,inline,inline"`, &tagOptions{Name: "name", Inline: true, Enum: []string{}}}, 45 {"json_omitempty_inline", `json:"name,omitempty,inline"`, &tagOptions{Name: "name", Optional: true, Inline: true, Enum: []string{}}}, 46 {"json_omitempty_inline_2", `json:",omitempty,inline"`, &tagOptions{Name: "", Optional: true, Inline: true, Enum: []string{}}}, 47 {"cue_default", `cue:"default:default_value"`, &tagOptions{Default: str("default_value"), Enum: []string{}}}, 48 {"cue_default_2", `cue:"default:default_value;default:default_value2"`, &tagOptions{Default: str("default_value2"), Enum: []string{}}}, 49 {"cue_default_3", `cue:"default:1.11"`, &tagOptions{Default: str("1.11"), Enum: []string{}}}, 50 {"cue_default_4", `cue:"default:va,lue"`, &tagOptions{Default: str(`va,lue`), Enum: []string{}}}, 51 {"cue_enum", `cue:"enum:enum1,enum2"`, &tagOptions{Enum: []string{"enum1", "enum2"}}}, 52 {"cue_enum_2", `cue:"enum:enum1,enum2;enum:enum3,enum4"`, &tagOptions{Enum: []string{"enum3", "enum4"}}}, 53 {"cue_enum_empty", `cue:""`, &tagOptions{Enum: []string{}}}, 54 {"cue_enum_empty_2", `cue:"enum:"`, &tagOptions{Enum: []string{}}}, 55 {"cue_escape", `cue:"default:\"default_value\""`, &tagOptions{Default: str(`"default_value"`), Enum: []string{}}}, 56 {"cue_escape_2", `cue:"default:\"default_value\\\"\""`, &tagOptions{Default: str(`"default_value\""`), Enum: []string{}}}, 57 {"cue_escape_3", `cue:"default:value\\;vv;enum:enum1,enum2"`, &tagOptions{Default: str(`value;vv`), Enum: []string{"enum1", "enum2"}}}, 58 {"cue_escape_default_semicolon", `cue:"default:va\\;lue\\"`, &tagOptions{Default: str(`va;lue\`), Enum: []string{}}}, 59 {"cue_escape_default_colon", `cue:"default:va\\:lue\\"`, &tagOptions{Default: str(`va:lue\`), Enum: []string{}}}, 60 {"cue_escape_enum_semicolon", `cue:"enum:e\\;num1,enum2"`, &tagOptions{Enum: []string{`e;num1`, "enum2"}}}, 61 {"cue_escape_enum_colon", `cue:"enum:e\\:num1,enum2"`, &tagOptions{Enum: []string{`e:num1`, "enum2"}}}, 62 {"cue_escape_enum_colon_2", `cue:"enum:enum1\\,enum2"`, &tagOptions{Enum: []string{"enum1,enum2"}}}, 63 {"cue_escape_all", `cue:"default:va\\;lue\\:;enum:e\\;num1,e\\:num2\\,enum3"`, &tagOptions{Default: str(`va;lue:`), Enum: []string{`e;num1`, `e:num2,enum3`}}}, 64 {"json_cue", `json:"name" cue:"default:default_value"`, &tagOptions{Name: "name", Default: str("default_value"), Enum: []string{}}}, 65 {"json_cue_2", `json:"name" cue:"default:default_value;enum:enum1,enum2"`, &tagOptions{Name: "name", Default: str("default_value"), Enum: []string{"enum1", "enum2"}}}, 66 {"json_cue_3", `json:",omitempty" cue:"default:default_value"`, &tagOptions{Name: "", Optional: true, Default: str("default_value"), Enum: []string{}}}, 67 {"json_cue_4", `json:",inline" cue:"default:default_value"`, &tagOptions{Name: "", Inline: true, Default: str("default_value"), Enum: []string{}}}, 68 {"json_cue_5", `json:"name,omitempty,inline" cue:"default:default_value"`, &tagOptions{Name: "name", Optional: true, Inline: true, Default: str("default_value"), Enum: []string{}}}, 69 {"json_cue_6", `json:",omitempty,inline" cue:"default:default_value;enum:enum1,enum2"`, &tagOptions{Name: "", Optional: true, Inline: true, Default: str("default_value"), Enum: []string{"enum1", "enum2"}}}, 70 } 71 72 g := &Generator{} 73 for _, tt := range tests { 74 got := g.parseTag(tt.tag) 75 assert.Equal(t, tt.opts, got, tt.name) 76 } 77 } 78 79 func TestParseBasicTag(t *testing.T) { 80 tests := []struct { 81 name string 82 tag string 83 wantName string 84 wantOpt string 85 }{ 86 {"empty", "", "", ""}, 87 {"only_name", "name", "name", ""}, 88 {"name_and_opt", "name,opt,opt2", "name", "opt,opt2"}, 89 {"name_and_opt_2", "name,opt1;opt2.opt3", "name", "opt1;opt2.opt3"}, 90 {"name_and_opt_with_space", "name, opt", "name", " opt"}, 91 {"only_opt", ",opt,opt2", "", "opt,opt2"}, 92 } 93 94 for _, tt := range tests { 95 gotName, gotOpt := parseTag(tt.tag) 96 assert.EqualValues(t, tt.wantName, gotName, tt.name) 97 assert.EqualValues(t, tt.wantOpt, gotOpt, tt.name) 98 } 99 } 100 101 func TestBasicTagOptHas(t *testing.T) { 102 tests := []struct { 103 name string 104 tag string 105 opt string 106 want bool 107 }{ 108 {"empty", "", "", false}, 109 {"empty_opt", "name", "", false}, 110 {"empty_tag", "", "opt", false}, 111 {"single_opt", "name,opt", "opt", true}, 112 {"multi_opt", "name,opt1,opt2,opt3", "opt1", true}, 113 {"multi_opt_2", "name,opt1,opt2,opt3", "opt2", true}, 114 {"multi_opt_3", "name,opt1,opt2,opt3", "opt3", true}, 115 {"only_multi_opt", ",opt1,opt2,opt3", "opt1", true}, 116 {"only_multi_opt_2", ",opt1,opt2,opt3", "opt2", true}, 117 {"only_multi_opt_3", ",opt1,opt2,opt3", "opt3", true}, 118 } 119 120 for _, tt := range tests { 121 _, opt := parseTag(tt.tag) 122 assert.Equal(t, tt.want, opt.Has(tt.opt), tt.name) 123 } 124 } 125 126 func TestParseExtTag(t *testing.T) { 127 tests := []struct { 128 name string 129 tag string 130 want map[string]string 131 }{ 132 {"empty", "", map[string]string{}}, 133 {"only_key", "key", map[string]string{"key": ""}}, 134 {"one_kv", "key:value", map[string]string{"key": "value"}}, 135 {"multi_kv", "key1:value1;key2:value2", map[string]string{"key1": "value1", "key2": "value2"}}, 136 {"bool", "key1;key2", map[string]string{"key1": "", "key2": ""}}, 137 {"bool_and_kv", "key1;key2:value2", map[string]string{"key1": "", "key2": "value2"}}, 138 {"kv_and_bool", "key1:value1;key2", map[string]string{"key1": "value1", "key2": ""}}, 139 {"multi_kv_and_bool", "key1:value1;key2:value2;key3", map[string]string{"key1": "value1", "key2": "value2", "key3": ""}}, 140 {"escape_semicolon_value", `key1:value\;1`, map[string]string{"key1": "value;1"}}, 141 {"escape_semicolon_key", `key\;1:value1`, map[string]string{"key;1": "value1"}}, 142 {"escape_semicolon_pairs", `key\;1:value\;1;key3:va\lue3\`, map[string]string{"key;1": "value;1", "key3": `va\lue3\`}}, 143 {"escape_semicolon_last", `key\1:value1\`, map[string]string{`key\1`: `value1\`}}, 144 {"escape_semicolon_last_2", `k\ey1:va\lue1\1`, map[string]string{`k\ey1`: `va\lue1\1`}}, 145 {"escape_semicolon_last_3", `key1:value1\;`, map[string]string{"key1": `value1;`}}, 146 {"escape_colon_value", `key1:value\:1`, map[string]string{"key1": "value:1"}}, 147 {"escape_colon_key", `key\:1:value1`, map[string]string{"key:1": "value1"}}, 148 {"escape_colon_pairs", `key\:1:value\:1;key3:va\lue3\`, map[string]string{"key:1": "value:1", "key3": `va\lue3\`}}, 149 {"escape_colon_last", `key\1:value1\:`, map[string]string{`key\1`: `value1:`}}, 150 {"escape_colon_last_2", `k\ey1:va\lue1\:1`, map[string]string{`k\ey1`: `va\lue1:1`}}, 151 {"escape_colon_last_3", `key1:value1\:`, map[string]string{"key1": `value1:`}}, 152 {"invalid_pair", `key1:value1:invalid;key2:value2`, map[string]string{"key2": "value2"}}, 153 } 154 155 for _, tt := range tests { 156 got := parseExtTag(tt.tag) 157 assert.EqualValues(t, tt.want, got, tt.name) 158 } 159 } 160 161 func TestExtTagGet(t *testing.T) { 162 tests := []struct { 163 name string 164 tag string 165 key string 166 want string 167 }{ 168 {"empty", "", "", ""}, 169 {"empty_key", "key", "", ""}, 170 {"empty_tag", "", "key", ""}, 171 {"one_kv", "key:value", "key", "value"}, 172 {"multi_kv", "key1:value1;key2:value2", "key1", "value1"}, 173 {"multi_kv_2", "key1:value1;key2:value2", "key2", "value2"}, 174 {"bool", "key1;key2", "key1", ""}, 175 {"bool2", "key1;key2", "key2", ""}, 176 {"escape", "key1:value1\\;vv", "key1", "value1;vv"}, 177 {"escape_2", "key1:\"value2\"", "key1", `"value2"`}, 178 } 179 180 for _, tt := range tests { 181 got := parseExtTag(tt.tag) 182 assert.EqualValues(t, tt.want, got.Get(tt.key), tt.name) 183 } 184 } 185 186 func TestExtTagGetX(t *testing.T) { 187 tests := []struct { 188 name string 189 tag string 190 key string 191 want *string 192 }{ 193 {"empty", "", "", nil}, 194 {"empty_key", "key", "", nil}, 195 {"empty_tag", "", "key", nil}, 196 {"one_kv", "key:value", "key", str("value")}, 197 {"multi_kv", "key1:value1;key2:value2", "key1", str("value1")}, 198 {"multi_kv_2", "key1:value1;key2:value2", "key2", str("value2")}, 199 {"bool", "key1;key2", "key1", str("")}, 200 {"bool2", "key1;key2", "key2", str("")}, 201 {"escape", "key1:value1\\;vv", "key1", str("value1;vv")}, 202 {"escape_2", "key1:\"value2\"", "key1", str(`"value2"`)}, 203 } 204 205 for _, tt := range tests { 206 got := parseExtTag(tt.tag) 207 assert.EqualValues(t, tt.want, got.GetX(tt.key), tt.name) 208 } 209 } 210 211 func TestUnescapeSplit(t *testing.T) { 212 tests := []struct { 213 name string 214 s string 215 sep string 216 want []string 217 }{ 218 {"empty", "", "", []string{}}, 219 {"empty_sep", "key:value", "", []string{"k", "e", "y", ":", "v", "a", "l", "u", "e"}}, 220 {"one", "key:value", ":", []string{"key", "value"}}, 221 {"escape_sep", `key\:value`, ":", []string{"key:value"}}, 222 {"escape_sep_2", `key\:value\:`, ":", []string{"key:value:"}}, 223 {"escape_last", `key\:value\`, ":", []string{`key:value\`}}, 224 {"escape_multi", `key\:value\:;key2:value2`, ":", []string{"key:value:;key2", "value2"}}, 225 {"escape_multi_2", `key\:value\:;key2:value2`, ";", []string{`key\:value\:`, "key2:value2"}}, 226 } 227 228 for _, tt := range tests { 229 got := unescapeSplit(tt.s, tt.sep) 230 assert.EqualValues(t, tt.want, got, tt.name) 231 } 232 }