From 11297844d2d2469a7d07703e679833fb373170ab Mon Sep 17 00:00:00 2001 From: Brandon Palm Date: Wed, 20 Dec 2023 15:00:35 -0600 Subject: [PATCH] Adjust XML output --- pkg/claimhelper/claimhelper.go | 83 ++++++++++++++++++++--------- pkg/claimhelper/claimhelper_test.go | 15 +++--- pkg/flags/flags_test.go | 17 ++++++ 3 files changed, 82 insertions(+), 33 deletions(-) create mode 100644 pkg/flags/flags_test.go diff --git a/pkg/claimhelper/claimhelper.go b/pkg/claimhelper/claimhelper.go index 0d9054256..e63ec79f3 100644 --- a/pkg/claimhelper/claimhelper.go +++ b/pkg/claimhelper/claimhelper.go @@ -21,7 +21,9 @@ import ( "encoding/xml" "fmt" "path/filepath" + "sort" "strconv" + "strings" "os" "time" @@ -41,7 +43,7 @@ const ( CNFFeatureValidationJunitXMLFileName = "validation_junit.xml" CNFFeatureValidationReportKey = "cnf-feature-validation" // dateTimeFormatDirective is the directive used to format date/time according to ISO 8601. - DateTimeFormatDirective = "2006-01-02T15:04:05+00:00" + DateTimeFormatDirective = "2006-01-02 15:04:05 -0700 MST" // States for test cases TestStateFailed = "failed" @@ -60,33 +62,33 @@ type FailureMessage struct { } type TestCase struct { - Text string `xml:",chardata"` - Name string `xml:"name,attr"` - Classname string `xml:"classname,attr"` - Status string `xml:"status,attr"` - Time string `xml:"time,attr"` - SystemErr string `xml:"system-err,omitempty"` - Skipped SkippedMessage `xml:"skipped,omitempty"` - Failure FailureMessage `xml:"failure,omitempty"` + Text string `xml:",chardata"` + Name string `xml:"name,attr,omitempty"` + Classname string `xml:"classname,attr,omitempty"` + Status string `xml:"status,attr,omitempty"` + Time string `xml:"time,attr,omitempty"` + SystemErr string `xml:"system-err,omitempty"` + Skipped *SkippedMessage `xml:"skipped"` + Failure *FailureMessage `xml:"failure"` } type Testsuite struct { Text string `xml:",chardata"` - Name string `xml:"name,attr"` - Package string `xml:"package,attr"` - Tests string `xml:"tests,attr"` - Disabled string `xml:"disabled,attr"` + Name string `xml:"name,attr,omitempty"` + Package string `xml:"package,attr,omitempty"` + Tests string `xml:"tests,attr,omitempty"` + Disabled string `xml:"disabled,attr,omitempty"` Skipped string `xml:"skipped,attr,omitempty"` Errors string `xml:"errors,attr,omitempty"` Failures string `xml:"failures,attr,omitempty"` - Time string `xml:"time,attr"` - Timestamp string `xml:"timestamp,attr"` + Time string `xml:"time,attr,omitempty"` + Timestamp string `xml:"timestamp,attr,omitempty"` Properties struct { Text string `xml:",chardata"` Property []struct { Text string `xml:",chardata"` - Name string `xml:"name,attr"` - Value string `xml:"value,attr"` + Name string `xml:"name,attr,omitempty"` + Value string `xml:"value,attr,omitempty"` } `xml:"property"` } `xml:"properties"` Testcase []TestCase `xml:"testcase"` @@ -95,11 +97,11 @@ type Testsuite struct { type TestSuitesXML struct { XMLName xml.Name `xml:"testsuites"` Text string `xml:",chardata"` - Tests string `xml:"tests,attr"` - Disabled string `xml:"disabled,attr"` + Tests string `xml:"tests,attr,omitempty"` + Disabled string `xml:"disabled,attr,omitempty"` Errors string `xml:"errors,attr,omitempty"` Failures string `xml:"failures,attr,omitempty"` - Time string `xml:"time,attr"` + Time string `xml:"time,attr,omitempty"` Testsuite Testsuite `xml:"testsuite"` } @@ -153,6 +155,17 @@ func populateXMLFromClaim(c claim.Claim, startTime, endTime time.Time) TestSuite const ( TestSuiteName = "CNF Certification Test Suite" ) + + // Collector all of the Test IDs + allTestIDs := []string{} + for _, result := range c.Results { + typedResult := result.(claim.Result) + allTestIDs = append(allTestIDs, typedResult.TestID.Id) + } + + // Sort the test IDs + sort.Strings(allTestIDs) + xmlOutput := TestSuitesXML{} // xmlOutput.Tests = strconv.Itoa(len(c.Results)) @@ -178,7 +191,7 @@ func populateXMLFromClaim(c claim.Claim, startTime, endTime time.Time) TestSuite xmlOutput.Failures = strconv.Itoa(failedTests) xmlOutput.Disabled = strconv.Itoa(skippedTests) xmlOutput.Errors = strconv.Itoa(0) - xmlOutput.Time = strconv.FormatFloat(endTime.Sub(startTime).Seconds(), 'f', 3, 64) + xmlOutput.Time = strconv.FormatFloat(endTime.Sub(startTime).Seconds(), 'f', 5, 64) // xmlOutput.Testsuite.Name = TestSuiteName @@ -188,30 +201,50 @@ func populateXMLFromClaim(c claim.Claim, startTime, endTime time.Time) TestSuite xmlOutput.Testsuite.Skipped = strconv.Itoa(skippedTests) xmlOutput.Testsuite.Errors = strconv.Itoa(0) - xmlOutput.Testsuite.Time = strconv.FormatFloat(endTime.Sub(startTime).Seconds(), 'f', 3, 64) + xmlOutput.Testsuite.Time = strconv.FormatFloat(endTime.Sub(startTime).Seconds(), 'f', 5, 64) xmlOutput.Testsuite.Timestamp = time.Now().UTC().Format(DateTimeFormatDirective) // // - for testID, result := range c.Results { + // Loop through all of the sorted test IDs + for _, testID := range allTestIDs { // Type the result - typedResult := result.(claim.Result) + typedResult := c.Results[testID].(claim.Result) testCase := TestCase{} testCase.Name = testID testCase.Classname = TestSuiteName testCase.Status = typedResult.State - testCase.Time = strconv.FormatFloat(float64(typedResult.Duration), 'f', 3, 64) + + // Clean the time strings to remove the " m=" suffix + start, err := time.Parse(DateTimeFormatDirective, strings.Split(typedResult.StartTime, " m=")[0]) + if err != nil { + log.Error("Failed to parse start time: %v", err) + } + end, err := time.Parse(DateTimeFormatDirective, strings.Split(typedResult.EndTime, " m=")[0]) + if err != nil { + log.Error("Failed to parse end time: %v", err) + } + + // Calculate the duration of the test case + difference := end.Sub(start) + testCase.Time = strconv.FormatFloat(difference.Seconds(), 'f', 10, 64) // Populate the skipped message if the test case was skipped if testCase.Status == TestStateSkipped { + testCase.Skipped = &SkippedMessage{} testCase.Skipped.Text = typedResult.SkipReason + } else { + testCase.Skipped = nil } // Populate the failure message if the test case failed if testCase.Status == TestStateFailed { + testCase.Failure = &FailureMessage{} testCase.Failure.Text = typedResult.CheckDetails + } else { + testCase.Failure = nil } // Append the test case to the test suite diff --git a/pkg/claimhelper/claimhelper_test.go b/pkg/claimhelper/claimhelper_test.go index bfd98b7cf..3500e00b9 100644 --- a/pkg/claimhelper/claimhelper_test.go +++ b/pkg/claimhelper/claimhelper_test.go @@ -46,6 +46,8 @@ func TestPopulateXMLFromClaim(t *testing.T) { }, State: "failed", SkipReason: failureMessage, + StartTime: "2023-12-20 14:51:33 -0600 MST", + EndTime: "2023-12-20 14:51:34 -0600 MST", CheckDetails: "", CapturedTestOutput: "test output", CategoryClassification: &claim.CategoryClassification{ @@ -72,7 +74,7 @@ func TestPopulateXMLFromClaim(t *testing.T) { Disabled: strconv.Itoa(0), Tests: strconv.Itoa(1), Errors: strconv.Itoa(0), - Time: strconv.Itoa(60), + Time: strconv.Itoa(1), Testsuite: Testsuite{ Name: "test-suite1", @@ -84,8 +86,8 @@ func TestPopulateXMLFromClaim(t *testing.T) { Testcase: []TestCase{ { Name: "test-case1", - Time: strconv.Itoa(60), - Failure: FailureMessage{ + Time: strconv.Itoa(1), + Failure: &FailureMessage{ Message: "my custom failure message", }, }, @@ -97,9 +99,9 @@ func TestPopulateXMLFromClaim(t *testing.T) { for _, tc := range testCases { // Build some 1 minute duration start and end time - startTime, err := time.Parse(DateTimeFormatDirective, "2006-01-02T15:04:05+00:00") + startTime, err := time.Parse(DateTimeFormatDirective, "2023-12-20 14:51:33 -0600 MST") assert.Nil(t, err) - endTime, err := time.Parse(DateTimeFormatDirective, "2006-01-02T15:05:05+00:00") + endTime, err := time.Parse(DateTimeFormatDirective, "2023-12-20 14:51:34 -0600 MST") assert.Nil(t, err) xmlResult := populateXMLFromClaim(generateClaim(map[string]claim.Result{"test-case1": tc.testResult}), startTime, endTime) @@ -108,9 +110,6 @@ func TestPopulateXMLFromClaim(t *testing.T) { assert.Equal(t, tc.expectedXMLResult.Failures, xmlResult.Failures) assert.Equal(t, tc.expectedXMLResult.Tests, xmlResult.Tests) assert.Equal(t, tc.expectedXMLResult.Errors, xmlResult.Errors) - assert.Equal(t, tc.expectedXMLResult.Testsuite.Skipped, xmlResult.Testsuite.Skipped) - - // convert "60.000" string to 60 int expectedTimeFloat, err := strconv.ParseFloat(tc.expectedXMLResult.Time, 32) assert.Nil(t, err) actualTimeFloat, err := strconv.ParseFloat(xmlResult.Time, 32) diff --git a/pkg/flags/flags_test.go b/pkg/flags/flags_test.go new file mode 100644 index 000000000..804e4f9bd --- /dev/null +++ b/pkg/flags/flags_test.go @@ -0,0 +1,17 @@ +// Copyright (C) 2020-2023 Red Hat, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +package flags