github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/controllerutil/cue_value_test.go (about) 1 /* 2 Copyright (C) 2022-2023 ApeCloud Co., Ltd 3 4 This file is part of KubeBlocks project 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Affero General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Affero General Public License for more details. 15 16 You should have received a copy of the GNU Affero General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 package controllerutil 21 22 import ( 23 "strings" 24 "testing" 25 ) 26 27 func TestNewCUETplFromPath(t *testing.T) { 28 _, err := NewCUETplFromPath("cue.cue") 29 if err == nil { 30 t.Error("Expected error to fall through, got err") 31 } 32 } 33 34 func TestNewCUETplFromBytes(t *testing.T) { 35 _, err := NewCUETplFromBytes([]byte(""), nil) 36 if err != nil { 37 t.Error("Expected error to fall through, got nil") 38 } 39 } 40 41 func TestNewCUETpl(t *testing.T) { 42 NewCUETpl([]byte{}) 43 } 44 45 type testCUEInput struct { 46 Replicas int `json:"replicas"` 47 } 48 49 type testCUEInputIntOmitEmpty struct { 50 Replicas int `json:"replicas,omitempty"` 51 } 52 53 type testCUEInputBoolOmitEmpty struct { 54 Flag bool `json:"flag,omitempty"` 55 } 56 57 // This test shows that the omitempty tag should be used with much care if the field 58 // is used in cue template. 59 func TestCUE(t *testing.T) { 60 cueTplIntJSON := ` 61 input: { 62 replicas: int32 63 } 64 output: { 65 replicas: input.replicas 66 } 67 ` 68 cueTplBoolJSON := ` 69 input: { 70 flag: bool 71 } 72 output: { 73 flag: input.flag 74 } 75 ` 76 77 testCases := []struct { 78 name string 79 tpl string 80 input any 81 err string 82 }{{ 83 name: "testCUEInput", 84 tpl: cueTplIntJSON, 85 input: testCUEInput{Replicas: 0}, 86 }, { 87 name: "testCUEInputIntOmitEmptyWithNonZeroValue", 88 tpl: cueTplIntJSON, 89 input: testCUEInputIntOmitEmpty{Replicas: 1}, 90 }, { 91 name: "testCUEInputIntOmitEmpty", 92 tpl: cueTplIntJSON, 93 input: testCUEInputIntOmitEmpty{Replicas: 0}, 94 err: "marshal error", 95 }, { 96 name: "testCUEInputBoolOmitEmptyWithNonZeroValue", 97 tpl: cueTplBoolJSON, 98 input: testCUEInputBoolOmitEmpty{Flag: true}, 99 }, { 100 name: "testCUEInputBoolOmitEmpty", 101 tpl: cueTplBoolJSON, 102 input: testCUEInputBoolOmitEmpty{Flag: false}, 103 err: "marshal error", 104 }} 105 106 for _, tc := range testCases { 107 cueTpl := NewCUETpl([]byte(tc.tpl)) 108 cueValue := NewCUEBuilder(*cueTpl) 109 110 if err := cueValue.FillObj("input", tc.input); err != nil { 111 t.Error("Expected non-nil input error") 112 } 113 _, err := cueValue.Lookup("output") 114 checkErr(t, err, tc.err, tc.name) 115 } 116 } 117 118 func TestCUEFillObj(t *testing.T) { 119 cueTplIntJSON := ` 120 input: { 121 replicas: int32 122 } 123 output: { 124 replicas: input.replicas 125 } 126 ` 127 128 testCases := []struct { 129 name string 130 tpl string 131 input any 132 err string 133 }{ 134 { 135 name: "testCUEInvalidInput", 136 tpl: cueTplIntJSON, 137 input: make(chan int), 138 err: "unsupported type", 139 }, 140 { 141 name: "testCUEInput", 142 tpl: cueTplIntJSON, 143 input: testCUEInput{Replicas: 0}, 144 }, 145 } 146 147 for _, tc := range testCases { 148 cueTpl := NewCUETpl([]byte(tc.tpl)) 149 cueValue := NewCUEBuilder(*cueTpl) 150 151 err := cueValue.FillObj("input", tc.input) 152 checkErr(t, err, tc.err, tc.name) 153 } 154 } 155 156 func TestCUEFill(t *testing.T) { 157 cueTplIntJSON := ` 158 input: { 159 replicas: int32 160 } 161 output: { 162 replicas: input.replicas 163 } 164 ` 165 166 testCases := []struct { 167 name string 168 tpl string 169 input string 170 err string 171 }{ 172 { 173 name: "testCUEInvalidJSON", 174 tpl: cueTplIntJSON, 175 input: "", 176 err: "invalid JSON", 177 }, 178 { 179 name: "testCUEInput", 180 input: `{ "replicas": 0}`, 181 tpl: cueTplIntJSON, 182 }, 183 } 184 185 for _, tc := range testCases { 186 cueTpl := NewCUETpl([]byte(tc.tpl)) 187 cueValue := NewCUEBuilder(*cueTpl) 188 189 err := cueValue.Fill("input", []byte(tc.input)) 190 checkErr(t, err, tc.err, tc.name) 191 } 192 } 193 194 func checkErr(t *testing.T, err error, str, name string) bool { 195 t.Helper() 196 if err == nil { 197 if str != "" { 198 t.Errorf(`err:%s: got ""; want %q`, name, str) 199 } 200 return true 201 } 202 return checkFailed(t, err, str, name) 203 } 204 205 func checkFailed(t *testing.T, err error, str, name string) bool { 206 t.Helper() 207 if err != nil { 208 got := err.Error() 209 if str == "" { 210 t.Fatalf(`err:%s: got %q; want ""`, name, got) 211 } 212 if !strings.Contains(got, str) { 213 t.Errorf(`err:%s: got %q; want %q`, name, got, str) 214 } 215 return false 216 } 217 return true 218 }