cuelang.org/go@v0.13.0/cuego/cuego_test.go (about) 1 // Copyright 2019 CUE Authors 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 15 package cuego 16 17 import ( 18 "reflect" 19 "testing" 20 ) 21 22 type Sum struct { 23 A int `cue:"C-B" json:",omitempty"` 24 B int `cue:"C-A" json:",omitempty"` 25 C int `cue:"A+B & >=5" json:",omitempty"` 26 } 27 28 func checkErr(t *testing.T, got error, want string) { 29 t.Helper() 30 if (got == nil) != (want == "") { 31 t.Errorf("error: got %v; want %v", got, want) 32 } 33 } 34 func TestValidate(t *testing.T) { 35 fail := "some error" 36 testCases := []struct { 37 name string 38 value interface{} 39 constraints string 40 err string 41 }{{ 42 name: "Sum", 43 value: Sum{A: 1, B: 4, C: 5}, 44 }, { 45 name: "*Sum", 46 value: &Sum{A: 1, B: 4, C: 5}, 47 }, { 48 name: "*Sum: incorrect sum", 49 value: &Sum{A: 1, B: 4, C: 6}, 50 err: fail, 51 }, { 52 name: "*Sum: field C is too low", 53 value: &Sum{A: 1, B: 3, C: 4}, 54 err: fail, 55 }, { 56 name: "*Sum: nil value", 57 value: (*Sum)(nil), 58 // }, { 59 // // TODO: figure out whether this constraint should constrain it 60 // // to a struct or not. 61 // name: "*Sum: nil disallowed by constraint", 62 // value: (*Sum)(nil), 63 // constraints: "!=null", 64 // err: fail, 65 }, { 66 // Not a typical constraint, but it is possible. 67 name: "string list", 68 value: []string{"a", "b", "c"}, 69 constraints: `[_, "b", ...]`, 70 }} 71 72 for _, tc := range testCases { 73 t.Run(tc.name, func(t *testing.T) { 74 c := &Context{} 75 if tc.constraints != "" { 76 err := c.Constrain(tc.value, tc.constraints) 77 if err != nil { 78 t.Fatal(err) 79 } 80 } 81 err := c.Validate(tc.value) 82 checkErr(t, err, tc.err) 83 }) 84 } 85 } 86 87 func TestUpdate(t *testing.T) { 88 type sump struct { 89 A *int `cue:"C-B"` 90 B *int `cue:"C-A"` 91 C *int `cue:"A+B"` 92 } 93 one := 1 94 two := 2 95 fail := "some error" 96 _ = fail 97 _ = one 98 testCases := []struct { 99 name string 100 value interface{} 101 result interface{} 102 constraints string 103 err string 104 }{{ 105 name: "*Sum", 106 value: &Sum{A: 1, B: 4, C: 5}, 107 result: &Sum{A: 1, B: 4, C: 5}, 108 }, { 109 name: "*Sum", 110 value: &Sum{A: 1, B: 4}, 111 result: &Sum{A: 1, B: 4, C: 5}, 112 }, { 113 name: "*sump", 114 value: &sump{A: &one, B: &one}, 115 result: &sump{A: &one, B: &one, C: &two}, 116 }, { 117 name: "*Sum: backwards", 118 value: &Sum{B: 4, C: 8}, 119 result: &Sum{A: 4, B: 4, C: 8}, 120 }, { 121 name: "*Sum: sum too low", 122 value: &Sum{A: 1, B: 3}, 123 result: &Sum{A: 1, B: 3}, // Value should not be updated 124 err: fail, 125 }, { 126 name: "*Sum: sum underspecified", 127 value: &Sum{A: 1}, 128 result: &Sum{A: 1}, // Value should not be updated 129 err: fail, 130 }, { 131 name: "Sum: cannot modify", 132 value: Sum{A: 3, B: 4, C: 7}, 133 result: Sum{A: 3, B: 4, C: 7}, 134 err: fail, 135 }, { 136 name: "*Sum: cannot update nil value", 137 value: (*Sum)(nil), 138 result: (*Sum)(nil), 139 err: fail, 140 }, { 141 name: "cannot modify slice", 142 value: []string{"a", "b", "c"}, 143 result: []string{"a", "b", "c"}, 144 err: fail, 145 }} 146 for _, tc := range testCases { 147 t.Run(tc.name, func(t *testing.T) { 148 c := &Context{} 149 if tc.constraints != "" { 150 err := c.Constrain(tc.value, tc.constraints) 151 if err != nil { 152 t.Fatal(err) 153 } 154 } 155 err := c.Complete(tc.value) 156 checkErr(t, err, tc.err) 157 if !reflect.DeepEqual(tc.value, tc.result) { 158 t.Errorf("value:\n got: %#v;\nwant: %#v", tc.value, tc.result) 159 } 160 }) 161 } 162 }