github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/internal/task/expression_test.go (about) 1 package task 2 3 import ( 4 "sort" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 "github.com/stretchr/testify/require" 9 10 "github.com/anchore/syft/syft/cataloging/pkgcataloging" 11 ) 12 13 func Test_newExpressionsFromSelectionRequest(t *testing.T) { 14 ts := []Task{ 15 dummyTask("1", "t1"), 16 dummyTask("2", "t2"), 17 dummyTask("3", "t3"), 18 dummyTask("4", "t4"), 19 dummyTask("5"), 20 dummyTask("6"), 21 } 22 23 nc := newExpressionContext(ts) 24 25 var tests = []struct { 26 name string 27 basis []string 28 expressions []string 29 expected Expressions 30 expectedErrors []error 31 }{ 32 { 33 name: "empty input", 34 basis: []string{}, 35 expressions: []string{}, 36 expected: nil, 37 }, 38 { 39 name: "valid single set operation", 40 basis: []string{"1"}, 41 expressions: []string{}, 42 expected: []Expression{ 43 {Operation: SetOperation, Operand: "1"}, 44 }, 45 }, 46 { 47 name: "add operation", 48 basis: []string{}, 49 expressions: []string{"+4"}, 50 expected: []Expression{ 51 {Operation: AddOperation, Operand: "4"}, 52 }, 53 }, 54 { 55 name: "remove operation", 56 basis: []string{}, 57 expressions: []string{"-3"}, 58 expected: []Expression{ 59 {Operation: RemoveOperation, Operand: "3"}, 60 }, 61 }, 62 { 63 name: "select operation", 64 basis: []string{}, 65 expressions: []string{"t2"}, 66 expected: []Expression{ 67 {Operation: SubSelectOperation, Operand: "t2"}, 68 }, 69 }, 70 { 71 name: "mixed operations order", 72 basis: []string{"1"}, 73 expressions: []string{"+4", "-3", "t2"}, 74 expected: []Expression{ 75 // note they are sorted by operation 76 {Operation: SetOperation, Operand: "1"}, 77 {Operation: SubSelectOperation, Operand: "t2"}, 78 {Operation: RemoveOperation, Operand: "3"}, 79 {Operation: AddOperation, Operand: "4"}, 80 }, 81 }, 82 { 83 name: "invalid token", 84 basis: []string{"!1"}, 85 expressions: []string{}, 86 expected: nil, 87 expectedErrors: []error{ErrInvalidToken}, 88 }, 89 { 90 name: "use + operator in basis", 91 basis: []string{"+1"}, 92 expressions: []string{}, 93 expected: nil, 94 expectedErrors: []error{ErrInvalidToken}, 95 }, 96 { 97 name: "use - operator in basis", 98 basis: []string{"-1"}, 99 expressions: []string{}, 100 expected: nil, 101 expectedErrors: []error{ErrInvalidToken}, 102 }, 103 { 104 name: "invalid name", 105 basis: []string{}, 106 expressions: []string{"+t1"}, 107 expected: nil, 108 expectedErrors: []error{ErrTagsNotAllowed}, 109 }, 110 { 111 name: "invalid tag", 112 basis: []string{}, 113 expressions: []string{"1"}, 114 expected: nil, 115 expectedErrors: []error{ErrNamesNotAllowed}, 116 }, 117 { 118 name: "invalid use of all", 119 basis: []string{}, 120 expressions: []string{"all"}, 121 expected: nil, 122 expectedErrors: []error{ErrAllNotAllowed}, 123 }, 124 { 125 name: "allow all operand", 126 basis: []string{"all"}, 127 expressions: []string{}, 128 expected: []Expression{ 129 // note they are sorted by operation 130 {Operation: SetOperation, Operand: "all"}, 131 }, 132 }, 133 } 134 135 for _, tt := range tests { 136 t.Run(tt.name, func(t *testing.T) { 137 138 req := pkgcataloging.NewSelectionRequest().WithDefaults(tt.basis...).WithExpression(tt.expressions...) 139 140 result := newExpressionsFromSelectionRequest(nc, req) 141 if tt.expectedErrors != nil { 142 errs := result.Errors() 143 require.Len(t, errs, len(tt.expectedErrors)) 144 for i, err := range tt.expectedErrors { 145 var target ErrInvalidExpression 146 require.ErrorAs(t, errs[i], &target) 147 assert.Equal(t, err, target.Err) 148 } 149 } else { 150 assert.Empty(t, result.Errors()) 151 assert.Equal(t, tt.expected, result) 152 } 153 }) 154 } 155 } 156 157 func Test_expressionNodes_sort(t *testing.T) { 158 tests := []struct { 159 name string 160 subject Expressions 161 want Expressions 162 }{ 163 { 164 name: "sort operations but keep token order", 165 subject: []Expression{ 166 { 167 Operation: AddOperation, 168 Operand: "8", 169 }, 170 { 171 Operation: AddOperation, 172 Operand: "7", 173 }, 174 { 175 Operation: RemoveOperation, 176 Operand: "6", 177 }, 178 { 179 Operation: RemoveOperation, 180 Operand: "5", 181 }, 182 { 183 Operation: SetOperation, 184 Operand: "2", 185 }, 186 { 187 Operation: SetOperation, 188 Operand: "1", 189 }, 190 { 191 Operation: SubSelectOperation, 192 Operand: "4", 193 }, 194 { 195 Operation: SubSelectOperation, 196 Operand: "3", 197 }, 198 }, 199 want: []Expression{ 200 { 201 Operation: SetOperation, 202 Operand: "2", 203 }, 204 { 205 Operation: SetOperation, 206 Operand: "1", 207 }, 208 { 209 Operation: SubSelectOperation, 210 Operand: "4", 211 }, 212 { 213 Operation: SubSelectOperation, 214 Operand: "3", 215 }, 216 { 217 Operation: RemoveOperation, 218 Operand: "6", 219 }, 220 { 221 Operation: RemoveOperation, 222 Operand: "5", 223 }, 224 { 225 Operation: AddOperation, 226 Operand: "8", 227 }, 228 { 229 Operation: AddOperation, 230 Operand: "7", 231 }, 232 }, 233 }, 234 } 235 for _, tt := range tests { 236 t.Run(tt.name, func(t *testing.T) { 237 s := tt.subject.Clone() 238 sort.Sort(s) 239 assert.Equal(t, tt.want, s) 240 }) 241 } 242 }