experiment/resultstore/convert.go
func convertSuiteMeta(suiteMeta gcs.SuitesMeta) resultstore.Suite {
	out := resultstore.Suite{
		Name: path.Base(suiteMeta.Path),
		Files: []resultstore.File{
			{
				ContentType: "text/xml",
				ID:          resultstore.UUID(),
				URL:         suiteMeta.Path, // ensure the junit.xml file appears in artifacts list
			},
		},
	}
	for _, suite := range suiteMeta.Suites.Suites {
		child := resultstore.Suite{
			Name:     suite.Name,
			Duration: dur(suite.Time),
		}
		switch {
		case suite.Failures > 0 && suite.Tests >= suite.Failures:
			child.Failures = append(child.Failures, resultstore.Failure{
				Message: fmt.Sprintf("%d out of %d tests failed (%.1f%% passing)", suite.Failures, suite.Tests, float64(suite.Tests-suite.Failures)*100.0/float64(suite.Tests)),
			})
		case suite.Failures > 0:
			child.Failures = append(child.Failures, resultstore.Failure{
				Message: fmt.Sprintf("%d tests failed", suite.Failures),
			})
		}
		for _, result := range suite.Results {
			name, tags := stripTags(result.Name)
			class := result.ClassName
			if class == "" {
				class = strings.Join(tags, " ")
			} else {
				class += " " + strings.Join(tags, " ")
			}
			c := resultstore.Case{
				Name:     name,
				Class:    class,
				Duration: dur(result.Time),
				Result:   resultstore.Completed,
			}
			const max = 5000 // truncate messages to this length
			msg := result.Message(max)
			switch {
			case result.Failure != nil:
				// failing tests have a completed result with an error
				if msg == "" {
					msg = "unknown failure"
				}
				c.Failures = append(c.Failures, resultstore.Failure{
					Message: msg,
				})
			case result.Skipped != nil:
				c.Result = resultstore.Skipped
				if msg != "" { // skipped results do not require an error, but may.
					c.Errors = append(c.Errors, resultstore.Error{
						Message: msg,
					})
				}
			}
			child.Cases = append(child.Cases, c)
			if c.Duration > child.Duration {
				child.Duration = c.Duration
			}
		}
		if child.Duration > out.Duration {
			// Assume suites run in parallel, so choose max
			out.Duration = child.Duration
		}
		out.Suites = append(out.Suites, child)
	}
	return out
}
func convertSuiteMeta(suiteMeta gcs.SuitesMeta) resultstore.Suite {
	out := resultstore.Suite{
		Name: path.Base(suiteMeta.Path),
		Files: []resultstore.File{
			{
				ContentType: "text/xml",
				ID:          resultstore.UUID(),
				URL:         suiteMeta.Path, // ensure the junit.xml file appears in artifacts list
			},
		},
	}
	for _, suite := range suiteMeta.Suites.Suites {
		child := resultstore.Suite{
			Name:     suite.Name,
			Duration: dur(suite.Time),
		}
		switch {
		case suite.Failures > 0 && suite.Tests >= suite.Failures:
			child.Failures = append(child.Failures, resultstore.Failure{
				Message: fmt.Sprintf("%d out of %d tests failed (%.1f%% passing)", suite.Failures, suite.Tests, float64(suite.Tests-suite.Failures)*100.0/float64(suite.Tests)),
			})
		case suite.Failures > 0:
			child.Failures = append(child.Failures, resultstore.Failure{
				Message: fmt.Sprintf("%d tests failed", suite.Failures),
			})
		}
		for _, result := range suite.Results {
			name, tags := stripTags(result.Name)
			class := result.ClassName
			if class == "" {
				class = strings.Join(tags, " ")
			} else {
				class += " " + strings.Join(tags, " ")
			}
			c := resultstore.Case{
				Name:     name,
				Class:    class,
				Duration: dur(result.Time),
				Result:   resultstore.Completed,
			}
			const max = 5000 // truncate messages to this length
			msg := result.Message(max)
			switch {
			case result.Failure != nil:
				// failing tests have a completed result with an error
				if msg == "" {
					msg = "unknown failure"
				}
				c.Failures = append(c.Failures, resultstore.Failure{
					Message: msg,
				})
			case result.Skipped != nil:
				c.Result = resultstore.Skipped
				if msg != "" { // skipped results do not require an error, but may.
					c.Errors = append(c.Errors, resultstore.Error{
						Message: msg,
					})
				}
			}
			child.Cases = append(child.Cases, c)
			if c.Duration > child.Duration {
				child.Duration = c.Duration
			}
		}
		if child.Duration > out.Duration {
			// Assume suites run in parallel, so choose max
			out.Duration = child.Duration
		}
		out.Suites = append(out.Suites, child)
	}
	return out
}
// convertSuiteMeta converts a junit result in gcs to a ResultStore Suite.