Skip to content

Commit 40f222b

Browse files
authored
Merge pull request kubernetes#128834 from pohly/scheduler-perf-pass-workaround
scheduler_perf: fix and enhance reporting
2 parents 776fb24 + 25a4758 commit 40f222b

File tree

2 files changed

+48
-16
lines changed

2 files changed

+48
-16
lines changed

hack/make-rules/test.sh

+3-1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ fi
8181
# Set to 'y' to keep the verbose stdout from tests when KUBE_JUNIT_REPORT_DIR is
8282
# set.
8383
KUBE_KEEP_VERBOSE_TEST_OUTPUT=${KUBE_KEEP_VERBOSE_TEST_OUTPUT:-n}
84+
# Set to 'false' to disable reduction of the JUnit file to only the top level tests.
85+
KUBE_PRUNE_JUNIT_TESTS=${KUBE_PRUNE_JUNIT_TESTS:-true}
8486

8587
kube::test::usage() {
8688
kube::log::usage_from_stdin <<EOF
@@ -234,7 +236,7 @@ runTests() {
234236
&& rc=$? || rc=$?
235237

236238
if [[ -n "${junit_filename_prefix}" ]]; then
237-
prune-junit-xml "${junit_filename_prefix}.xml"
239+
prune-junit-xml -prune-tests="${KUBE_PRUNE_JUNIT_TESTS}" "${junit_filename_prefix}.xml"
238240
fi
239241

240242
if [[ ${KUBE_COVER} =~ ^[yY]$ ]]; then

test/integration/scheduler_perf/scheduler_perf.go

+45-15
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"os"
3030
"path"
3131
"regexp"
32+
"slices"
3233
"strings"
3334
"sync"
3435
"testing"
@@ -207,9 +208,9 @@ var (
207208
}
208209
)
209210

210-
var UseTestingLog *bool
211-
var PerfSchedulingLabelFilter *string
212-
var TestSchedulingLabelFilter *string
211+
var UseTestingLog bool
212+
var PerfSchedulingLabelFilter string
213+
var TestSchedulingLabelFilter string
213214

214215
// InitTests should be called in a TestMain in each config subdirectory.
215216
func InitTests() error {
@@ -235,9 +236,9 @@ func InitTests() error {
235236
"A set of key=value pairs that describe feature gates for alpha/experimental features. "+
236237
"Options are:\n"+strings.Join(LoggingFeatureGate.KnownFeatures(), "\n"))
237238

238-
UseTestingLog = flag.Bool("use-testing-log", false, "Write log entries with testing.TB.Log. This is more suitable for unit testing and debugging, but less realistic in real benchmarks.")
239-
PerfSchedulingLabelFilter = flag.String("perf-scheduling-label-filter", "performance", "comma-separated list of labels which a testcase must have (no prefix or +) or must not have (-), used by BenchmarkPerfScheduling")
240-
TestSchedulingLabelFilter = flag.String("test-scheduling-label-filter", "integration-test,-performance", "comma-separated list of labels which a testcase must have (no prefix or +) or must not have (-), used by TestScheduling")
239+
flag.BoolVar(&UseTestingLog, "use-testing-log", false, "Write log entries with testing.TB.Log. This is more suitable for unit testing and debugging, but less realistic in real benchmarks.")
240+
flag.StringVar(&PerfSchedulingLabelFilter, "perf-scheduling-label-filter", "performance", "comma-separated list of labels which a testcase must have (no prefix or +) or must not have (-), used by BenchmarkPerfScheduling")
241+
flag.StringVar(&TestSchedulingLabelFilter, "test-scheduling-label-filter", "integration-test,-performance", "comma-separated list of labels which a testcase must have (no prefix or +) or must not have (-), used by TestScheduling")
241242

242243
// This would fail if we hadn't removed the logging flags above.
243244
logsapi.AddGoFlags(LoggingConfig, flag.CommandLine)
@@ -988,7 +989,7 @@ func (scm stopCollectingMetricsOp) patchParams(_ *workload) (realOp, error) {
988989

989990
func initTestOutput(tb testing.TB) io.Writer {
990991
var output io.Writer
991-
if *UseTestingLog {
992+
if UseTestingLog {
992993
output = framework.NewTBWriter(tb)
993994
} else {
994995
tmpDir := tb.TempDir()
@@ -1020,9 +1021,9 @@ func initTestOutput(tb testing.TB) io.Writer {
10201021
var specialFilenameChars = regexp.MustCompile(`[^a-zA-Z0-9-_]`)
10211022

10221023
func setupTestCase(t testing.TB, tc *testCase, featureGates map[featuregate.Feature]bool, output io.Writer, outOfTreePluginRegistry frameworkruntime.Registry) (informers.SharedInformerFactory, ktesting.TContext) {
1023-
tCtx := ktesting.Init(t, initoption.PerTestOutput(*UseTestingLog))
1024+
tCtx := ktesting.Init(t, initoption.PerTestOutput(UseTestingLog))
10241025
artifacts, doArtifacts := os.LookupEnv("ARTIFACTS")
1025-
if !*UseTestingLog && doArtifacts {
1026+
if !UseTestingLog && doArtifacts {
10261027
// Reconfigure logging so that it goes to a separate file per
10271028
// test instead of stderr. If the test passes, the file gets
10281029
// deleted. The overall output can be very large (> 200 MB for
@@ -1115,6 +1116,32 @@ func featureGatesMerge(src map[featuregate.Feature]bool, overrides map[featurega
11151116
return result
11161117
}
11171118

1119+
// fixJSONOutput works around Go not emitting a "pass" action for
1120+
// sub-benchmarks
1121+
// (https://github.com/golang/go/issues/66825#issuecomment-2343229005), which
1122+
// causes gotestsum to report a successful benchmark run as failed
1123+
// (https://github.com/gotestyourself/gotestsum/issues/413#issuecomment-2343206787).
1124+
//
1125+
// It does this by printing the missing "PASS" output line that test2json
1126+
// then converts into the "pass" action.
1127+
func fixJSONOutput(b *testing.B) {
1128+
if !slices.Contains(os.Args, "-test.v=test2json") {
1129+
// Not printing JSON.
1130+
return
1131+
}
1132+
1133+
start := time.Now()
1134+
b.Cleanup(func() {
1135+
if b.Failed() {
1136+
// Really has failed, do nothing.
1137+
return
1138+
}
1139+
// SYN gets injected when using -test.v=test2json, see
1140+
// https://cs.opensource.google/go/go/+/refs/tags/go1.23.3:src/testing/testing.go;drc=87ec2c959c73e62bfae230ef7efca11ec2a90804;l=527
1141+
fmt.Fprintf(os.Stderr, "%c--- PASS: %s (%.2fs)\n", 22 /* SYN */, b.Name(), time.Since(start).Seconds())
1142+
})
1143+
}
1144+
11181145
// RunBenchmarkPerfScheduling runs the scheduler performance benchmark tests.
11191146
//
11201147
// You can pass your own scheduler plugins via outOfTreePluginRegistry.
@@ -1128,11 +1155,12 @@ func RunBenchmarkPerfScheduling(b *testing.B, configFile string, topicName strin
11281155
if err = validateTestCases(testCases); err != nil {
11291156
b.Fatal(err)
11301157
}
1158+
fixJSONOutput(b)
11311159

11321160
if testing.Short() {
1133-
*PerfSchedulingLabelFilter += ",+short"
1161+
PerfSchedulingLabelFilter += ",+short"
11341162
}
1135-
testcaseLabelSelectors := strings.Split(*PerfSchedulingLabelFilter, ",")
1163+
testcaseLabelSelectors := strings.Split(PerfSchedulingLabelFilter, ",")
11361164

11371165
output := initTestOutput(b)
11381166

@@ -1147,11 +1175,13 @@ func RunBenchmarkPerfScheduling(b *testing.B, configFile string, topicName strin
11471175
dataItems := DataItems{Version: "v1"}
11481176
for _, tc := range testCases {
11491177
b.Run(tc.Name, func(b *testing.B) {
1178+
fixJSONOutput(b)
11501179
for _, w := range tc.Workloads {
11511180
b.Run(w.Name, func(b *testing.B) {
11521181
if !enabled(testcaseLabelSelectors, append(tc.Labels, w.Labels...)...) {
1153-
b.Skipf("disabled by label filter %v", PerfSchedulingLabelFilter)
1182+
b.Skipf("disabled by label filter %q", PerfSchedulingLabelFilter)
11541183
}
1184+
fixJSONOutput(b)
11551185

11561186
featureGates := featureGatesMerge(tc.FeatureGates, w.FeatureGates)
11571187
informerFactory, tCtx := setupTestCase(b, tc, featureGates, output, outOfTreePluginRegistry)
@@ -1244,16 +1274,16 @@ func RunIntegrationPerfScheduling(t *testing.T, configFile string) {
12441274
}
12451275

12461276
if testing.Short() {
1247-
*TestSchedulingLabelFilter += ",+short"
1277+
TestSchedulingLabelFilter += ",+short"
12481278
}
1249-
testcaseLabelSelectors := strings.Split(*TestSchedulingLabelFilter, ",")
1279+
testcaseLabelSelectors := strings.Split(TestSchedulingLabelFilter, ",")
12501280

12511281
for _, tc := range testCases {
12521282
t.Run(tc.Name, func(t *testing.T) {
12531283
for _, w := range tc.Workloads {
12541284
t.Run(w.Name, func(t *testing.T) {
12551285
if !enabled(testcaseLabelSelectors, append(tc.Labels, w.Labels...)...) {
1256-
t.Skipf("disabled by label filter %q", *TestSchedulingLabelFilter)
1286+
t.Skipf("disabled by label filter %q", TestSchedulingLabelFilter)
12571287
}
12581288
featureGates := featureGatesMerge(tc.FeatureGates, w.FeatureGates)
12591289
informerFactory, tCtx := setupTestCase(t, tc, featureGates, nil, nil)

0 commit comments

Comments
 (0)