Files
Alex ShtinandGitHub 8e8f1b0f7c Remove license header from every file (#7689)
## What changed?
<!-- Describe what has changed in this PR -->
Remove license header from every file. Because it is really hard to
follow in this PR here is the summary:
1. License header is removed from all `.go` and `.proto` files
:fireworks::fireworks:🎆.
2. `LICENSE` file in the root directory has only Temporal and Uber
copyrights.
3. 5 other `LICENSE` files added to the packages which have copyrights
different from Temporal and Uber: Datadog, Xargin, "Mat Ryer, Tyler
Bunnell and contributors".
4. `license_file` flag is removed from all code generation tools.
5. `copyright_file` flag is removed from `go:generate mockgen`
directive.
6. All copyright related targets are removed from `Makefile`.
7. Updated Temporal copyright year to 2025 everywhere.

## Why?
<!-- Tell your future self why have you made these changes -->
I double checked with legal department that it is not needed to have
license header in every file. One file per repo is enough. I put all
copyrights to the root `LICENSE` file and removed header from all other
files. Also updated tools and `Makefile`.
2025-05-01 18:50:21 -07:00

192 lines
4.6 KiB
Go

package testrunner
import (
"encoding/xml"
"errors"
"fmt"
"iter"
"log"
"os"
"strings"
"github.com/jstemmer/go-junit-report/v2/junit"
)
type junitReport struct {
path string
junit.Testsuites
}
func (j *junitReport) read() error {
f, err := os.Open(j.path)
if err != nil {
return fmt.Errorf("failed to open junit report file: %w", err)
}
defer f.Close()
decoder := xml.NewDecoder(f)
if err = decoder.Decode(&j.Testsuites); err != nil {
return fmt.Errorf("failed to read junit report file: %w", err)
}
return nil
}
func generateForTimedoutTests(timedoutTests []string) *junitReport {
var testcases []junit.Testcase
for _, name := range timedoutTests {
testcases = append(testcases, junit.Testcase{
Name: name + " (timeout)",
Failure: &junit.Result{Message: "Timeout"},
})
}
return &junitReport{
Testsuites: junit.Testsuites{
Suites: []junit.Testsuite{
{
Name: "suite",
Testcases: testcases,
},
},
},
}
}
func (j *junitReport) write() error {
f, err := os.Create(j.path)
if err != nil {
return fmt.Errorf("failed to open junit report file: %w", err)
}
defer f.Close()
encoder := xml.NewEncoder(f)
encoder.Indent("", " ")
if err = encoder.Encode(j.Testsuites); err != nil {
return fmt.Errorf("failed to write junit report file: %w", err)
}
log.Printf("wrote junit report to %s", j.path)
return nil
}
func (j *junitReport) collectTestCases() map[string]struct{} {
cases := make(map[string]struct{})
for _, suite := range j.Testsuites.Suites {
for _, tc := range suite.Testcases {
cases[tc.Name] = struct{}{}
}
}
return cases
}
func (j *junitReport) collectTestCaseFailures() []string {
root := node{children: make(map[string]node)}
for _, suite := range j.Testsuites.Suites {
if suite.Failures == 0 {
continue
}
for _, tc := range suite.Testcases {
if tc.Failure == nil {
continue
}
n := root
for _, part := range strings.Split(tc.Name, "/") {
child, ok := n.children[part]
if !ok {
child = node{children: make(map[string]node)}
n.children[part] = child
}
n = child
}
}
}
leafFailures := make([]string, 0)
// Walk the tree and find all leaf failures. The way Go test failures are reported in junit is that there's a
// test case per suite and per test in that suite. Filter out any nodes that have children to find the most
// specific failures to rerun.
for path, n := range root.walk() {
if len(n.children) > 0 {
continue
}
leafFailures = append(leafFailures, path)
}
return leafFailures
}
func mergeReports(reports []*junitReport) (*junitReport, error) {
if len(reports) == 0 {
return nil, errors.New("no reports to merge")
}
if len(reports) == 1 {
return reports[0], nil
}
var combined junit.Testsuites
combined.XMLName = reports[0].Testsuites.XMLName
combined.Name = reports[0].Testsuites.Name
combined.Suites = reports[0].Testsuites.Suites
for i, report := range reports {
combined.Tests += report.Testsuites.Tests
combined.Errors += report.Testsuites.Errors
combined.Failures += report.Testsuites.Failures
combined.Skipped += report.Testsuites.Skipped
combined.Disabled += report.Testsuites.Disabled
combined.Time += report.Testsuites.Time
// If the report is for a retry ...
if i > 0 {
// Run sanity check to make sure we rerun what we expect.
casesTested := report.collectTestCases()
casesMissing := make([]string, 0)
previousReport := reports[i-1]
for _, f := range previousReport.collectTestCaseFailures() {
if _, ok := casesTested[f]; !ok {
casesMissing = append(casesMissing, f)
}
}
if len(casesMissing) > 0 {
return nil,
fmt.Errorf("expected a rerun of all failures from the previous attempt, missing: %v", casesMissing)
}
// Append the test cases from the retry.
for _, suite := range report.Testsuites.Suites {
cpy := suite
cpy.Name += fmt.Sprintf(" (retry %d)", i)
cpy.Testcases = make([]junit.Testcase, 0, len(suite.Testcases))
for _, test := range suite.Testcases {
tcpy := test
tcpy.Name += fmt.Sprintf(" (retry %d)", i)
cpy.Testcases = append(cpy.Testcases, tcpy)
}
combined.Suites = append(combined.Suites, cpy)
}
}
}
return &junitReport{Testsuites: combined}, nil
}
type node struct {
children map[string]node
}
func (n node) visitor(path ...string) func(yield func(string, node) bool) {
return func(yield func(string, node) bool) {
for name, child := range n.children {
path := append(path, name)
if !yield(strings.Join(path, "/"), child) {
return
}
child.visitor(path...)(yield)
}
}
}
func (n node) walk() iter.Seq2[string, node] {
return n.visitor()
}