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  }