github.com/DataDog/datadog-agent/pkg/security/secl@v0.55.0-devel.0.20240517055856-10c4965fea94/compiler/eval/strings_test.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the Apache License Version 2.0. 3 // This product includes software developed at Datadog (https://www.datadoghq.com/). 4 // Copyright 2016-present Datadog, Inc. 5 6 // Package eval holds eval related files 7 package eval 8 9 import ( 10 "slices" 11 "testing" 12 ) 13 14 func TestStringValues(t *testing.T) { 15 t.Run("scalar-fast-path", func(t *testing.T) { 16 var values StringValues 17 values.AppendScalarValue("test123") 18 19 if err := values.Compile(DefaultStringCmpOpts); err != nil { 20 t.Error(err) 21 } 22 23 if !slices.Contains(values.scalarCache, "test123") { 24 t.Error("expected cache key not found") 25 } 26 27 if len(values.stringMatchers) != 0 { 28 t.Error("shouldn't have a string matcher") 29 } 30 }) 31 32 t.Run("scalar-matcher", func(t *testing.T) { 33 var values StringValues 34 values.AppendScalarValue("test123") 35 36 if err := values.Compile(StringCmpOpts{CaseInsensitive: true}); err != nil { 37 t.Error(err) 38 } 39 40 if slices.Contains(values.scalarCache, "test123") { 41 t.Error("expected cache key found") 42 } 43 44 if len(values.stringMatchers) == 0 { 45 t.Error("should have a string matcher") 46 } 47 }) 48 } 49 50 func TestScalar(t *testing.T) { 51 t.Run("sensitive-case", func(t *testing.T) { 52 matcher, err := NewStringMatcher(ScalarValueType, "test123", DefaultStringCmpOpts) 53 if err != nil { 54 t.Error(err) 55 } 56 57 if !matcher.Matches("test123") { 58 t.Error("should match") 59 } 60 61 if matcher.Matches("TEST123") { 62 t.Error("shouldn't match") 63 } 64 }) 65 66 t.Run("insensitive-case", func(t *testing.T) { 67 matcher, err := NewStringMatcher(ScalarValueType, "test123", StringCmpOpts{CaseInsensitive: true}) 68 if err != nil { 69 t.Error(err) 70 } 71 72 if !matcher.Matches("test123") { 73 t.Error("should match") 74 } 75 76 if !matcher.Matches("TEST123") { 77 t.Error("should match") 78 } 79 }) 80 } 81 82 func TestPattern(t *testing.T) { 83 t.Run("sensitive-case", func(t *testing.T) { 84 matcher, err := NewStringMatcher(PatternValueType, "http://test*", DefaultStringCmpOpts) 85 if err != nil { 86 t.Error(err) 87 } 88 89 if !matcher.Matches("http://test123") { 90 t.Error("should match") 91 } 92 93 if matcher.Matches("http://TEST123") { 94 t.Error("shouldn't match") 95 } 96 }) 97 98 t.Run("insensitive-case", func(t *testing.T) { 99 matcher, err := NewStringMatcher(PatternValueType, "http://TEst*", StringCmpOpts{CaseInsensitive: true}) 100 if err != nil { 101 t.Error(err) 102 } 103 104 if !matcher.Matches("http://test123") { 105 t.Error("should match") 106 } 107 108 if !matcher.Matches("http://TEST123") { 109 t.Error("should match") 110 } 111 }) 112 113 t.Run("sensitive-case-scalar", func(t *testing.T) { 114 matcher, err := NewStringMatcher(PatternValueType, "http://test123", DefaultStringCmpOpts) 115 if err != nil { 116 t.Error(err) 117 } 118 119 if !matcher.Matches("http://test123") { 120 t.Error("should match") 121 } 122 123 if matcher.Matches("http://TEST123") { 124 t.Error("shouldn't match") 125 } 126 }) 127 128 t.Run("insensitive-case-scalar", func(t *testing.T) { 129 matcher, err := NewStringMatcher(PatternValueType, "http://test123", StringCmpOpts{CaseInsensitive: true}) 130 if err != nil { 131 t.Error(err) 132 } 133 134 if !matcher.Matches("http://test123") { 135 t.Error("should match") 136 } 137 138 if !matcher.Matches("http://TEST123") { 139 t.Error("should match") 140 } 141 }) 142 } 143 144 func TestGlob(t *testing.T) { 145 t.Run("sensitive-case", func(t *testing.T) { 146 matcher, err := NewStringMatcher(GlobValueType, "/etc/test*", DefaultStringCmpOpts) 147 if err != nil { 148 t.Error(err) 149 } 150 151 if !matcher.Matches("/etc/test123") { 152 t.Error("should match") 153 } 154 155 if matcher.Matches("/etc/TEST123") { 156 t.Error("shouldn't match") 157 } 158 }) 159 160 t.Run("insensitive-case", func(t *testing.T) { 161 matcher, err := NewStringMatcher(GlobValueType, "/etc/TEst*", StringCmpOpts{CaseInsensitive: true}) 162 if err != nil { 163 t.Error(err) 164 } 165 166 if !matcher.Matches("/etc/test123") { 167 t.Error("should match") 168 } 169 170 if !matcher.Matches("/etc/TEST123") { 171 t.Error("should match") 172 } 173 }) 174 175 t.Run("sensitive-case-scalar", func(t *testing.T) { 176 matcher, err := NewStringMatcher(GlobValueType, "/etc/test123", DefaultStringCmpOpts) 177 if err != nil { 178 t.Error(err) 179 } 180 181 if !matcher.Matches("/etc/test123") { 182 t.Error("should match") 183 } 184 185 if matcher.Matches("/etc/TEST123") { 186 t.Error("shouldn't match") 187 } 188 }) 189 190 t.Run("insensitive-case-scalar", func(t *testing.T) { 191 matcher, err := NewStringMatcher(GlobValueType, "/etc/test123", StringCmpOpts{CaseInsensitive: true}) 192 if err != nil { 193 t.Error(err) 194 } 195 196 if !matcher.Matches("/etc/test123") { 197 t.Error("should match") 198 } 199 200 if !matcher.Matches("/etc/TEST123") { 201 t.Error("should match") 202 } 203 }) 204 } 205 206 func TestRegexp(t *testing.T) { 207 t.Run("sensitive-case", func(t *testing.T) { 208 matcher, err := NewStringMatcher(RegexpValueType, "test.*", DefaultStringCmpOpts) 209 if err != nil { 210 t.Error(err) 211 } 212 213 if !matcher.Matches("test123") { 214 t.Error("should match") 215 } 216 217 if matcher.Matches("TEST123") { 218 t.Error("shouldn't match") 219 } 220 }) 221 222 t.Run("insensitive-case", func(t *testing.T) { 223 matcher, err := NewStringMatcher(RegexpValueType, "test.*", StringCmpOpts{CaseInsensitive: true}) 224 if err != nil { 225 t.Error(err) 226 } 227 228 if !matcher.Matches("test123") { 229 t.Error("should match") 230 } 231 232 if !matcher.Matches("TEST123") { 233 t.Error("should match") 234 } 235 }) 236 237 t.Run("multiple-string-options", func(t *testing.T) { 238 matcher, err := NewStringMatcher(RegexpValueType, ".*(restore|recovery|readme|instruction|how_to|ransom).*", StringCmpOpts{}) 239 if err != nil { 240 t.Error(err) 241 } 242 243 if !matcher.Matches("123readme456") { 244 t.Error("should match") 245 } 246 247 if matcher.Matches("TEST123") { 248 t.Error("should not match") 249 } 250 251 reMatcher, ok := matcher.(*RegexpStringMatcher) 252 if !ok { 253 t.Error("should be a regex matcher") 254 } 255 256 if !slices.Equal([]string{"restore", "recovery", "readme", "instruction", "how_to", "ransom"}, reMatcher.stringOptionsOpt) { 257 t.Error("should be an optimized string option re matcher") 258 } 259 }) 260 } 261 262 func BenchmarkRegexpEvaluator(b *testing.B) { 263 pattern := ".*(restore|recovery|readme|instruction|how_to|ransom).*" 264 265 var matcher RegexpStringMatcher 266 if err := matcher.Compile(pattern, false); err != nil { 267 b.Fatal(err) 268 } 269 270 b.ResetTimer() 271 for i := 0; i < b.N; i++ { 272 if !matcher.Matches("123ransom456.txt") { 273 b.Fatal("unexpected result") 274 } 275 } 276 }