github.com/adevinta/lava@v0.7.2/internal/config/config_test.go (about) 1 // Copyright 2023 Adevinta 2 3 package config 4 5 import ( 6 "errors" 7 "io" 8 "log/slog" 9 "regexp" 10 "testing" 11 12 agentconfig "github.com/adevinta/vulcan-agent/config" 13 types "github.com/adevinta/vulcan-types" 14 "github.com/google/go-cmp/cmp" 15 ) 16 17 func TestParse(t *testing.T) { 18 tests := []struct { 19 name string 20 file string 21 envs map[string]string 22 want Config 23 wantErr error 24 wantErrRegexp *regexp.Regexp 25 }{ 26 { 27 name: "valid", 28 file: "testdata/valid.yaml", 29 want: Config{ 30 LavaVersion: "v1.0.0", 31 ChecktypeURLs: []string{ 32 "checktypes.json", 33 }, 34 Targets: []Target{ 35 { 36 Identifier: "example.com", 37 AssetType: types.DomainName, 38 }, 39 }, 40 }, 41 }, 42 { 43 name: "valid env", 44 file: "testdata/valid_env.yaml", 45 want: Config{ 46 LavaVersion: "v1.0.0", 47 ChecktypeURLs: []string{ 48 "checktypes.json", 49 }, 50 Targets: []Target{ 51 { 52 Identifier: "example.com", 53 AssetType: types.DomainName, 54 }, 55 }, 56 }, 57 envs: map[string]string{ 58 "TARGET": "example.com", 59 "CHECK_types_URL1": "checktypes.json", 60 }, 61 }, 62 { 63 name: "invalid env", 64 file: "testdata/invalid_env.yaml", 65 want: Config{ 66 LavaVersion: "v1.0.0", 67 ChecktypeURLs: []string{ 68 "checktypes.json", 69 }, 70 Targets: []Target{ 71 { 72 Identifier: "${1NVALID}", 73 AssetType: types.DomainName, 74 }, 75 }, 76 }, 77 }, 78 { 79 name: "empty", 80 file: "testdata/empty.yaml", 81 want: Config{}, 82 wantErr: io.EOF, 83 }, 84 { 85 name: "invalid lava version", 86 file: "testdata/invalid_lava_version.yaml", 87 want: Config{}, 88 wantErr: ErrInvalidLavaVersion, 89 }, 90 { 91 name: "no checktypes URLs", 92 file: "testdata/no_checktypes_urls.yaml", 93 want: Config{}, 94 wantErr: ErrNoChecktypeURLs, 95 }, 96 { 97 name: "no targets", 98 file: "testdata/no_targets.yaml", 99 want: Config{}, 100 wantErr: ErrNoTargets, 101 }, 102 { 103 name: "no target identifier", 104 file: "testdata/no_target_identifier.yaml", 105 want: Config{}, 106 wantErr: ErrNoTargetIdentifier, 107 }, 108 { 109 name: "no target asset type", 110 file: "testdata/no_target_asset_type.yaml", 111 want: Config{}, 112 wantErr: ErrNoTargetAssetType, 113 }, 114 { 115 name: "critical severity", 116 file: "testdata/critical_severity.yaml", 117 want: Config{ 118 LavaVersion: "v1.0.0", 119 ChecktypeURLs: []string{ 120 "checktypes.json", 121 }, 122 ReportConfig: ReportConfig{ 123 Severity: SeverityCritical, 124 }, 125 Targets: []Target{ 126 { 127 Identifier: "example.com", 128 AssetType: types.DomainName, 129 }, 130 }, 131 }, 132 }, 133 { 134 name: "invalid severity", 135 file: "testdata/invalid_severity.yaml", 136 want: Config{}, 137 wantErr: ErrInvalidSeverity, 138 }, 139 { 140 name: "never pull policy", 141 file: "testdata/never_pull_policy.yaml", 142 want: Config{ 143 LavaVersion: "v1.0.0", 144 ChecktypeURLs: []string{ 145 "checktypes.json", 146 }, 147 AgentConfig: AgentConfig{ 148 PullPolicy: agentconfig.PullPolicyNever, 149 }, 150 Targets: []Target{ 151 { 152 Identifier: "example.com", 153 AssetType: types.DomainName, 154 }, 155 }, 156 }, 157 }, 158 { 159 name: "invalid pull policy", 160 file: "testdata/invalid_pull_policy.yaml", 161 want: Config{}, 162 wantErrRegexp: regexp.MustCompile(`value .* is not a valid PullPolicy value`), 163 }, 164 { 165 name: "invalid target asset type", 166 file: "testdata/invalid_target_asset_type.yaml", 167 want: Config{}, 168 wantErr: ErrInvalidAssetType, 169 }, 170 { 171 name: "JSON output format", 172 file: "testdata/json_output_format.yaml", 173 want: Config{ 174 LavaVersion: "v1.0.0", 175 ChecktypeURLs: []string{ 176 "checktypes.json", 177 }, 178 Targets: []Target{ 179 { 180 Identifier: "example.com", 181 AssetType: types.DomainName, 182 }, 183 }, 184 ReportConfig: ReportConfig{ 185 Format: OutputFormatJSON, 186 }, 187 }, 188 }, 189 { 190 name: "invalid output format", 191 file: "testdata/invalid_output_format.yaml", 192 want: Config{}, 193 wantErr: ErrInvalidOutputFormat, 194 }, 195 { 196 name: "debug log level", 197 file: "testdata/debug_log_level.yaml", 198 want: Config{ 199 LavaVersion: "v1.0.0", 200 ChecktypeURLs: []string{ 201 "checktypes.json", 202 }, 203 Targets: []Target{ 204 { 205 Identifier: "example.com", 206 AssetType: types.DomainName, 207 }, 208 }, 209 LogLevel: slog.LevelDebug, 210 }, 211 }, 212 { 213 name: "invalid log level", 214 file: "testdata/invalid_log_level.yaml", 215 want: Config{}, 216 wantErrRegexp: regexp.MustCompile(`level string ".*": unknown name`), 217 }, 218 } 219 220 for _, tt := range tests { 221 t.Run(tt.name, func(t *testing.T) { 222 for k, v := range tt.envs { 223 t.Setenv(k, v) 224 } 225 got, err := ParseFile(tt.file) 226 227 switch { 228 case tt.wantErr != nil: 229 if !errors.Is(err, tt.wantErr) { 230 t.Errorf("unexpected error: got: %v, want: %v", err, tt.wantErr) 231 } 232 case tt.wantErrRegexp != nil: 233 if err == nil { 234 t.Errorf("unexpected nil error: want: %v", tt.wantErrRegexp) 235 } else if !tt.wantErrRegexp.MatchString(err.Error()) { 236 t.Errorf("unexpected error: got: %v, want: %v", err, tt.wantErrRegexp) 237 } 238 default: 239 if err != nil { 240 t.Errorf("unexpected error: %v", err) 241 } 242 } 243 244 if diff := cmp.Diff(tt.want, got); diff != "" { 245 t.Errorf("configs mismatch (-want +got):\n%v", diff) 246 } 247 }) 248 } 249 } 250 251 func TestConfig_IsCompatible(t *testing.T) { 252 tests := []struct { 253 name string 254 cfg Config 255 v string 256 want bool 257 }{ 258 { 259 name: "same version", 260 cfg: Config{LavaVersion: "v1.0.0"}, 261 v: "v1.0.0", 262 want: true, 263 }, 264 { 265 name: "lower version", 266 cfg: Config{LavaVersion: "v1.1.0"}, 267 v: "1.0.0", 268 want: false, 269 }, 270 { 271 name: "higher version", 272 cfg: Config{LavaVersion: "v1.0.0"}, 273 v: "v1.1.0", 274 want: true, 275 }, 276 { 277 name: "pre-release", 278 cfg: Config{LavaVersion: "v0.0.0"}, 279 v: "v0.0.0-20231216173526-1150d51c5272", 280 want: false, 281 }, 282 { 283 name: "invalid version", 284 cfg: Config{LavaVersion: "v1.0.0"}, 285 v: "invalid", 286 want: false, 287 }, 288 } 289 290 for _, tt := range tests { 291 t.Run(tt.name, func(t *testing.T) { 292 got := tt.cfg.IsCompatible(tt.v) 293 if got != tt.want { 294 t.Errorf("unexpected result: %v, minimum required version: %v, v: %v", got, tt.cfg.LavaVersion, tt.v) 295 } 296 }) 297 } 298 } 299 300 func TestSeverity_MarshalText(t *testing.T) { 301 tests := []struct { 302 name string 303 severity Severity 304 want string 305 wantErr error 306 }{ 307 { 308 name: "critical", 309 severity: SeverityCritical, 310 want: "critical", 311 wantErr: nil, 312 }, 313 { 314 name: "high", 315 severity: SeverityHigh, 316 want: "high", 317 wantErr: nil, 318 }, 319 { 320 name: "medium", 321 severity: SeverityMedium, 322 want: "medium", 323 wantErr: nil, 324 }, 325 { 326 name: "low", 327 severity: SeverityLow, 328 want: "low", 329 wantErr: nil, 330 }, 331 { 332 name: "info", 333 severity: SeverityInfo, 334 want: "info", 335 wantErr: nil, 336 }, 337 { 338 name: "invalid", 339 severity: 7, 340 want: "", 341 wantErr: ErrInvalidSeverity, 342 }, 343 } 344 345 for _, tt := range tests { 346 t.Run(tt.name, func(t *testing.T) { 347 got, err := tt.severity.MarshalText() 348 if !errors.Is(err, tt.wantErr) { 349 t.Errorf("unexpected error: want: %v, got: %v", tt.wantErr, err) 350 } 351 if string(got) != tt.want { 352 t.Errorf("unexpected severity string: want: %v, got: %v", tt.want, got) 353 } 354 }) 355 } 356 }