github.com/yoheimuta/protolint@v0.49.8-0.20240515023657-4ecaebb7575d/internal/linter/report/reporters/ciReporter_test.go (about) 1 package reporters_test 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 "path/filepath" 8 "testing" 9 10 "github.com/yoheimuta/go-protoparser/v4/parser/meta" 11 "github.com/yoheimuta/protolint/internal/linter/report/reporters" 12 "github.com/yoheimuta/protolint/linter/report" 13 "github.com/yoheimuta/protolint/linter/rule" 14 ) 15 16 type testFiles struct { 17 files []string 18 } 19 20 type testStruct struct { 21 name string 22 inputFailures []report.Failure 23 wantOutput string 24 expectedError error 25 files testFiles 26 } 27 28 type testCases struct { 29 oneWarningOneError testStruct 30 onlyErrors testStruct 31 oneOfEach testStruct 32 } 33 34 func makeTestData() testCases { 35 return testCases{ 36 37 oneWarningOneError: testStruct{ 38 name: "oneWarningOneError", 39 wantOutput: "", 40 expectedError: nil, 41 files: testFiles{}, 42 inputFailures: []report.Failure{ 43 report.FailureWithSeverityf( 44 meta.Position{ 45 Filename: "example.proto", 46 Offset: 100, 47 Line: 5, 48 Column: 10, 49 }, 50 "ENUM_NAMES_UPPER_CAMEL_CASE", 51 string(rule.SeverityWarning), 52 `EnumField name "fIRST_VALUE" must be CAPITALS_WITH_UNDERSCORES`, 53 ), 54 report.FailureWithSeverityf( 55 meta.Position{ 56 Filename: "example.proto", 57 Offset: 200, 58 Line: 10, 59 Column: 20, 60 }, 61 "ENUM_NAMES_UPPER_CAMEL_CASE", 62 string(rule.SeverityError), 63 `EnumField name "SECOND.VALUE" must be CAPITALS_WITH_UNDERSCORES`, 64 ), 65 }, 66 }, 67 68 onlyErrors: testStruct{ 69 name: "onlyErrors", 70 wantOutput: "", 71 expectedError: nil, 72 files: testFiles{}, 73 inputFailures: []report.Failure{ 74 report.FailureWithSeverityf( 75 meta.Position{ 76 Filename: "example.proto", 77 Offset: 100, 78 Line: 5, 79 Column: 10, 80 }, 81 "ENUM_NAMES_UPPER_CAMEL_CASE", 82 string(rule.SeverityError), 83 `EnumField name "fIRST_VALUE" must be CAPITALS_WITH_UNDERSCORES`, 84 ), 85 report.FailureWithSeverityf( 86 meta.Position{ 87 Filename: "example.proto", 88 Offset: 200, 89 Line: 10, 90 Column: 20, 91 }, 92 "ENUM_NAMES_UPPER_CAMEL_CASE", 93 string(rule.SeverityError), 94 `EnumField name "SECOND.VALUE" must be CAPITALS_WITH_UNDERSCORES`, 95 ), 96 report.FailureWithSeverityf( 97 meta.Position{ 98 Filename: "example.proto", 99 Offset: 300, 100 Line: 20, 101 Column: 40, 102 }, 103 "ENUM_NAMES_UPPER_CAMEL_CASE", 104 string(rule.SeverityError), 105 `EnumField name "third.VALUE" must be CAPITALS_WITH_UNDERSCORES`, 106 ), 107 }, 108 }, 109 110 oneOfEach: testStruct{ 111 name: "oneOfEach", 112 wantOutput: "", 113 expectedError: nil, 114 files: testFiles{}, 115 inputFailures: []report.Failure{ 116 report.FailureWithSeverityf( 117 meta.Position{ 118 Filename: "example.proto", 119 Offset: 100, 120 Line: 5, 121 Column: 10, 122 }, 123 "ENUM_NAMES_UPPER_CAMEL_CASE", 124 string(rule.SeverityNote), 125 `EnumField name "fIRST_VALUE" must be CAPITALS_WITH_UNDERSCORES`, 126 ), 127 report.FailureWithSeverityf( 128 meta.Position{ 129 Filename: "example.proto", 130 Offset: 200, 131 Line: 10, 132 Column: 20, 133 }, 134 "ENUM_NAMES_UPPER_CAMEL_CASE", 135 string(rule.SeverityWarning), 136 `EnumField name "SECOND.VALUE" must be CAPITALS_WITH_UNDERSCORES`, 137 ), 138 report.FailureWithSeverityf( 139 meta.Position{ 140 Filename: "example.proto", 141 Offset: 300, 142 Line: 20, 143 Column: 40, 144 }, 145 "ENUM_NAMES_UPPER_CAMEL_CASE", 146 string(rule.SeverityError), 147 `EnumField name "third.VALUE" must be CAPITALS_WITH_UNDERSCORES`, 148 ), 149 }, 150 }, 151 } 152 } 153 154 func TestProblemMatcherReporter_Report(t *testing.T) { 155 initTestCases := makeTestData() 156 initTestCases.oneOfEach.want(`Protolint ENUM_NAMES_UPPER_CAMEL_CASE (info): example.proto[5,10]: EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 157 Protolint ENUM_NAMES_UPPER_CAMEL_CASE (warning): example.proto[10,20]: EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 158 Protolint ENUM_NAMES_UPPER_CAMEL_CASE (error): example.proto[20,40]: EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 159 `) 160 initTestCases.oneWarningOneError.want(`Protolint ENUM_NAMES_UPPER_CAMEL_CASE (warning): example.proto[5,10]: EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 161 Protolint ENUM_NAMES_UPPER_CAMEL_CASE (error): example.proto[10,20]: EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 162 `) 163 initTestCases.onlyErrors.want(`Protolint ENUM_NAMES_UPPER_CAMEL_CASE (error): example.proto[5,10]: EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 164 Protolint ENUM_NAMES_UPPER_CAMEL_CASE (error): example.proto[10,20]: EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 165 Protolint ENUM_NAMES_UPPER_CAMEL_CASE (error): example.proto[20,40]: EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 166 `) 167 168 tests := initTestCases.tests() 169 170 reporter := reporters.NewCiReporterWithGenericFormat() 171 run_tests(t, tests, reporter) 172 } 173 174 func TestAzureDevOpsMatcherReporter_Report(t *testing.T) { 175 initTestCases := makeTestData() 176 initTestCases.oneOfEach.want(`##vso[task.logissue type=warning;sourcepath=example.proto;linenumber=10;columnnumber=20;code=ENUM_NAMES_UPPER_CAMEL_CASE;]EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 177 ##vso[task.logissue type=error;sourcepath=example.proto;linenumber=20;columnnumber=40;code=ENUM_NAMES_UPPER_CAMEL_CASE;]EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 178 `) 179 initTestCases.oneWarningOneError.want(`##vso[task.logissue type=warning;sourcepath=example.proto;linenumber=5;columnnumber=10;code=ENUM_NAMES_UPPER_CAMEL_CASE;]EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 180 ##vso[task.logissue type=error;sourcepath=example.proto;linenumber=10;columnnumber=20;code=ENUM_NAMES_UPPER_CAMEL_CASE;]EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 181 `) 182 initTestCases.onlyErrors.want(`##vso[task.logissue type=error;sourcepath=example.proto;linenumber=5;columnnumber=10;code=ENUM_NAMES_UPPER_CAMEL_CASE;]EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 183 ##vso[task.logissue type=error;sourcepath=example.proto;linenumber=10;columnnumber=20;code=ENUM_NAMES_UPPER_CAMEL_CASE;]EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 184 ##vso[task.logissue type=error;sourcepath=example.proto;linenumber=20;columnnumber=40;code=ENUM_NAMES_UPPER_CAMEL_CASE;]EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 185 `) 186 187 tests := initTestCases.tests() 188 189 reporter := reporters.NewCiReporterForAzureDevOps() 190 run_tests(t, tests, reporter) 191 } 192 func TestGithubActionMatcherReporter_Report(t *testing.T) { 193 initTestCases := makeTestData() 194 initTestCases.oneOfEach.want(`::notice file=example.proto,line=5,col=10,title=ENUM_NAMES_UPPER_CAMEL_CASE::EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 195 ::warning file=example.proto,line=10,col=20,title=ENUM_NAMES_UPPER_CAMEL_CASE::EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 196 ::error file=example.proto,line=20,col=40,title=ENUM_NAMES_UPPER_CAMEL_CASE::EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 197 `) 198 initTestCases.oneWarningOneError.want(`::warning file=example.proto,line=5,col=10,title=ENUM_NAMES_UPPER_CAMEL_CASE::EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 199 ::error file=example.proto,line=10,col=20,title=ENUM_NAMES_UPPER_CAMEL_CASE::EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 200 `) 201 initTestCases.onlyErrors.want(`::error file=example.proto,line=5,col=10,title=ENUM_NAMES_UPPER_CAMEL_CASE::EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 202 ::error file=example.proto,line=10,col=20,title=ENUM_NAMES_UPPER_CAMEL_CASE::EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 203 ::error file=example.proto,line=20,col=40,title=ENUM_NAMES_UPPER_CAMEL_CASE::EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 204 `) 205 206 tests := initTestCases.tests() 207 208 reporter := reporters.NewCiReporterForGithubActions() 209 run_tests(t, tests, reporter) 210 } 211 func TestGitlabCiCdMatcherReporter_Report(t *testing.T) { 212 initTestCases := makeTestData() 213 initTestCases.oneOfEach.want(`INFO: ENUM_NAMES_UPPER_CAMEL_CASE example.proto(5,10) : EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 214 WARNING: ENUM_NAMES_UPPER_CAMEL_CASE example.proto(10,20) : EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 215 ERROR: ENUM_NAMES_UPPER_CAMEL_CASE example.proto(20,40) : EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 216 `) 217 initTestCases.oneWarningOneError.want(`WARNING: ENUM_NAMES_UPPER_CAMEL_CASE example.proto(5,10) : EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 218 ERROR: ENUM_NAMES_UPPER_CAMEL_CASE example.proto(10,20) : EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 219 `) 220 initTestCases.onlyErrors.want(`ERROR: ENUM_NAMES_UPPER_CAMEL_CASE example.proto(5,10) : EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 221 ERROR: ENUM_NAMES_UPPER_CAMEL_CASE example.proto(10,20) : EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 222 ERROR: ENUM_NAMES_UPPER_CAMEL_CASE example.proto(20,40) : EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 223 `) 224 225 tests := initTestCases.tests() 226 reporter := reporters.NewCiReporterForGitlab() 227 run_tests(t, tests, reporter) 228 } 229 230 func TestEnvMatcherReporterFromTemplateString_Report(t *testing.T) { 231 t.Setenv("PROTOLINT_CIREPORTER_TEMPLATE_STRING", "{{ .Severity }}@{{ .File }}[{{ .Line }},{{ .Column }}] triggered rule {{ .Rule }} with message {{ .Message }}") 232 initTestCases := makeTestData() 233 initTestCases.oneOfEach.want(`info@example.proto[5,10] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 234 warning@example.proto[10,20] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 235 error@example.proto[20,40] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 236 `) 237 initTestCases.oneWarningOneError.want(`warning@example.proto[5,10] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 238 error@example.proto[10,20] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 239 `) 240 initTestCases.onlyErrors.want(`error@example.proto[5,10] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 241 error@example.proto[10,20] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 242 error@example.proto[20,40] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 243 `) 244 245 tests := initTestCases.tests() 246 reporter := reporters.NewCiReporterFromEnv() 247 run_tests(t, tests, reporter) 248 } 249 250 func TestEnvMatcherReporterFromTemplateFile_Report(t *testing.T) { 251 initTestCases := makeTestData() 252 initTestCases.oneOfEach.files.appendFile(t, "0oneOfEach.template", "[fromfile:0oneOfEach.template] {{ .Severity }}@{{ .File }}[{{ .Line }},{{ .Column }}] triggered rule {{ .Rule }} with message {{ .Message }}") 253 initTestCases.oneOfEach.want(`[fromfile:0oneOfEach.template] info@example.proto[5,10] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 254 [fromfile:0oneOfEach.template] warning@example.proto[10,20] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 255 [fromfile:0oneOfEach.template] error@example.proto[20,40] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 256 `) 257 initTestCases.oneWarningOneError.files.appendFile(t, "0oneWarningOneError.template", "[fromfile:0oneWarningOneError.template] {{ .Severity }}@{{ .File }}[{{ .Line }},{{ .Column }}] triggered rule {{ .Rule }} with message {{ .Message }}") 258 initTestCases.oneWarningOneError.want(`[fromfile:0oneWarningOneError.template] warning@example.proto[5,10] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 259 [fromfile:0oneWarningOneError.template] error@example.proto[10,20] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 260 `) 261 initTestCases.onlyErrors.files.appendFile(t, "0onlyErrors.template", "[fromfile:0onlyErrors.template] {{ .Severity }}@{{ .File }}[{{ .Line }},{{ .Column }}] triggered rule {{ .Rule }} with message {{ .Message }}") 262 initTestCases.onlyErrors.want(`[fromfile:0onlyErrors.template] error@example.proto[5,10] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 263 [fromfile:0onlyErrors.template] error@example.proto[10,20] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 264 [fromfile:0onlyErrors.template] error@example.proto[20,40] triggered rule ENUM_NAMES_UPPER_CAMEL_CASE with message EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 265 `) 266 267 tests := initTestCases.tests() 268 reporter := reporters.NewCiReporterFromEnv() 269 run_tests(t, tests, reporter) 270 } 271 272 func TestEnvMatcherReporterFromNonExistingTemplateFile_Report(t *testing.T) { 273 t.Setenv("PROTOLINT_CIREPORTER_TEMPLATE_FILE", filepath.Join(t.TempDir(), "does.not.exist")) 274 initTestCases := makeTestData() 275 initTestCases.oneOfEach.want(`Protolint ENUM_NAMES_UPPER_CAMEL_CASE (info): example.proto[5,10]: EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 276 Protolint ENUM_NAMES_UPPER_CAMEL_CASE (warning): example.proto[10,20]: EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 277 Protolint ENUM_NAMES_UPPER_CAMEL_CASE (error): example.proto[20,40]: EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 278 `) 279 initTestCases.oneWarningOneError.want(`Protolint ENUM_NAMES_UPPER_CAMEL_CASE (warning): example.proto[5,10]: EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 280 Protolint ENUM_NAMES_UPPER_CAMEL_CASE (error): example.proto[10,20]: EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 281 `) 282 initTestCases.onlyErrors.want(`Protolint ENUM_NAMES_UPPER_CAMEL_CASE (error): example.proto[5,10]: EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 283 Protolint ENUM_NAMES_UPPER_CAMEL_CASE (error): example.proto[10,20]: EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 284 Protolint ENUM_NAMES_UPPER_CAMEL_CASE (error): example.proto[20,40]: EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 285 `) 286 287 tests := initTestCases.tests() 288 reporter := reporters.NewCiReporterFromEnv() 289 run_tests(t, tests, reporter) 290 } 291 292 func TestEnvMatcherReporterFromUnallowedTemplateFile_Report(t *testing.T) { 293 tplFile := filepath.Join(t.TempDir(), "does.exist") 294 t.Setenv("PROTOLINT_CIREPORTER_TEMPLATE_FILE", tplFile) 295 t.Cleanup(func() { 296 if _, err := os.Stat(tplFile); os.IsNotExist(err) { 297 t.Logf("File %s already deleted", tplFile) 298 } 299 300 err := os.Remove(tplFile) 301 if err != nil { 302 t.Errorf("ERROR while cleaning up file %s: %v", tplFile, err) 303 } 304 }) 305 file, err := os.Create(tplFile) 306 if err != nil { 307 t.Errorf("Failed to create temp file: %v", err) 308 } 309 _, err = file.Write([]byte("[fromfile:does.exist] {{ .Severity }}@{{ .File }}[{{ .Line }},{{ .Column }}] triggered rule {{ .Rule }} with message {{ .Message }}")) 310 if err != nil { 311 t.Errorf("Failed to write temp file: %v", err) 312 } 313 err = file.Close() 314 if err != nil { 315 t.Errorf("Failed to create temp file (error while closing): %v", err) 316 } 317 err = os.Chmod(tplFile, 0200) 318 if err != nil { 319 t.Errorf("Failed to remove read permissions: %v", err) 320 } 321 322 initTestCases := makeTestData() 323 initTestCases.oneOfEach.want(`Protolint ENUM_NAMES_UPPER_CAMEL_CASE (info): example.proto[5,10]: EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 324 Protolint ENUM_NAMES_UPPER_CAMEL_CASE (warning): example.proto[10,20]: EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 325 Protolint ENUM_NAMES_UPPER_CAMEL_CASE (error): example.proto[20,40]: EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 326 `) 327 initTestCases.oneWarningOneError.want(`Protolint ENUM_NAMES_UPPER_CAMEL_CASE (warning): example.proto[5,10]: EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 328 Protolint ENUM_NAMES_UPPER_CAMEL_CASE (error): example.proto[10,20]: EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 329 `) 330 initTestCases.onlyErrors.want(`Protolint ENUM_NAMES_UPPER_CAMEL_CASE (error): example.proto[5,10]: EnumField name \"fIRST_VALUE\" must be CAPITALS_WITH_UNDERSCORES 331 Protolint ENUM_NAMES_UPPER_CAMEL_CASE (error): example.proto[10,20]: EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES 332 Protolint ENUM_NAMES_UPPER_CAMEL_CASE (error): example.proto[20,40]: EnumField name \"third.VALUE\" must be CAPITALS_WITH_UNDERSCORES 333 `) 334 335 tests := initTestCases.tests() 336 reporter := reporters.NewCiReporterFromEnv() 337 run_tests(t, tests, reporter) 338 } 339 340 func TestEnvMatcherReporterFromErroneousTemplateFile_ReportTestEnvMatcherReporterFromErroneousTemplateString_Report(t *testing.T) { 341 initTestCases := makeTestData() 342 initTestCases.oneOfEach.files.appendFile(t, "1oneOfEach.template", "[fromfile:1oneOfEach.template] {{ .Severit }}@{{ .Fil }}[{{ .Lne }},{{ .Colum }}] triggered rule {{ .ule }} with message {{ .Msg }}") 343 initTestCases.oneOfEach.expectError(`template: Failure:1:34: executing "Failure" at <.Severit>: can't evaluate field Severit in type reporters.ciReportedFailure`) 344 345 initTestCases.oneWarningOneError.files.appendFile(t, "1oneWarningOneError.template", "[fromfile:1oneWarningOneError.template] {{ .Severit }}@{{ .Fil }}[{{ .Lne }},{{ .Colum }}] triggered rule {{ .ule }} with message {{ .Msg }}") 346 initTestCases.oneWarningOneError.expectError(`template: Failure:1:43: executing "Failure" at <.Severit>: can't evaluate field Severit in type reporters.ciReportedFailure`) 347 348 initTestCases.onlyErrors.files.appendFile(t, "1onlyErrors.template", "[fromfile:1onlyErrors.template] {{ .Severit }}@{{ .Fil }}[{{ .Lne }},{{ .Colum }}] triggered rule {{ .ule }} with message {{ .Msg }}") 349 initTestCases.onlyErrors.expectError(`template: Failure:1:35: executing "Failure" at <.Severit>: can't evaluate field Severit in type reporters.ciReportedFailure`) 350 351 tests := initTestCases.tests() 352 reporter := reporters.NewCiReporterFromEnv() 353 run_tests(t, tests, reporter) 354 } 355 356 func TestEnvMatcherReporterFromErroneousTemplateString_Report(t *testing.T) { 357 t.Setenv("PROTOLINT_CIREPORTER_TEMPLATE_STRING", "{{ .Severit }}@{{ .Fil }}[{{ .Lne }},{{ .Colum }}] triggered rule {{ .ule }} with message {{ .Msg }}") 358 initTestCases := makeTestData() 359 initTestCases.oneOfEach.expectError(`template: Failure:1:3: executing "Failure" at <.Severit>: can't evaluate field Severit in type reporters.ciReportedFailure`) 360 initTestCases.oneWarningOneError.expectError(`template: Failure:1:3: executing "Failure" at <.Severit>: can't evaluate field Severit in type reporters.ciReportedFailure`) 361 initTestCases.onlyErrors.expectError(`template: Failure:1:3: executing "Failure" at <.Severit>: can't evaluate field Severit in type reporters.ciReportedFailure`) 362 363 tests := initTestCases.tests() 364 reporter := reporters.NewCiReporterFromEnv() 365 run_tests(t, tests, reporter) 366 } 367 368 func run_tests(t *testing.T, tests []testStruct, r reporters.CiReporter) { 369 if len(tests) == 0 { 370 t.SkipNow() 371 } 372 for _, test := range tests { 373 test := test 374 t.Cleanup(func() { test.cleanUp(t) }) 375 t.Run(test.name, func(t *testing.T) { 376 if len(test.files.files) > 0 { 377 t.Setenv("PROTOLINT_CIREPORTER_TEMPLATE_FILE", test.files.files[0]) 378 } 379 380 buf := &bytes.Buffer{} 381 err := r.Report(buf, test.inputFailures) 382 test.cleanUp(t) 383 if err != nil { 384 isExpectedError := false 385 if test.expectedError != nil { 386 isExpectedError = err.Error() == test.expectedError.Error() 387 } 388 389 if !isExpectedError { 390 t.Errorf("got err %v, but want %v", err, test.expectedError) 391 return 392 } else { 393 t.Logf("Wanted %v, got %v", test.expectedError, err) 394 } 395 } 396 if buf.String() != test.wantOutput { 397 t.Errorf(` got 398 %s 399 , but want 400 %s`, buf.String(), test.wantOutput) 401 } 402 }) 403 } 404 } 405 406 func (ts testStruct) cleanUp(t *testing.T) { 407 ts.files.cleanUp(t) 408 } 409 410 func (tf testFiles) cleanUp(t *testing.T) { 411 for _, file := range tf.files { 412 413 if _, err := os.Stat(file); os.IsNotExist(err) { 414 t.Logf("File %s already deleted", file) 415 continue 416 } 417 418 err := os.Remove(file) 419 if err != nil { 420 t.Errorf("ERROR while cleaning up file %s: %v", file, err) 421 } 422 } 423 } 424 425 func (tf *testFiles) appendFile(t *testing.T, fileName string, fileContent string) { 426 filePath := filepath.Join(t.TempDir(), fileName) 427 file, err := os.Create(filePath) 428 if err != nil { 429 t.Errorf("Failed to create file %s: %v", filePath, err) 430 return 431 } 432 433 defer func(td *testing.T) { 434 err = file.Close() 435 if err != nil { 436 td.Errorf("Failed to content to file %s: %v", filePath, err) 437 return 438 } 439 }(t) 440 441 _, err = file.WriteString(fileContent) 442 if err != nil { 443 t.Errorf("Failed to content to file %s: %v", filePath, err) 444 return 445 } 446 447 tf.files = append(tf.files, filePath) 448 } 449 450 func (ts *testStruct) want(input string) { 451 ts.wantOutput = input 452 } 453 454 func (ts *testStruct) expectError(err string) { 455 ts.expectedError = fmt.Errorf(err) 456 ts.want("") 457 } 458 459 func (td testCases) tests() []testStruct { 460 var allCases []testStruct 461 462 allCases = append(allCases, td.oneOfEach) 463 allCases = append(allCases, td.oneWarningOneError) 464 allCases = append(allCases, td.onlyErrors) 465 466 return allCases 467 }