Skip to content

Commit

Permalink
Merge pull request torvalds#117 from sched-ext/refactor_tests
Browse files Browse the repository at this point in the history
scx: Implement scx selftests framework
  • Loading branch information
htejun authored Jan 10, 2024
2 parents 7909b33 + c64a804 commit 228db9d
Show file tree
Hide file tree
Showing 17 changed files with 666 additions and 206 deletions.
7 changes: 4 additions & 3 deletions tools/testing/selftests/scx/.gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
dsp_fallbackdsq_fail
dsp_localdsq_fail
ddsp_bogus_dsq_fail
ddsp_vtimelocal_fail
enq_last_no_enq_fails
enqueue_select_cpu_fails
enq_select_cpu_fails
init_enable_count
minimal
runner
select_cpu_dfl
select_cpu_dfl_nodispatch
select_cpu_dispatch
Expand Down
40 changes: 32 additions & 8 deletions tools/testing/selftests/scx/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ ifneq ($(LLVM),)
CFLAGS += -Wno-unused-command-line-argument
endif

LDFLAGS = -lelf -lz -lpthread
LDFLAGS = -lelf -lz -lpthread -lzstd

IS_LITTLE_ENDIAN = $(shell $(CC) -dM -E - </dev/null | \
grep 'define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__')
Expand Down Expand Up @@ -148,12 +148,6 @@ $(INCLUDE_DIR)/%.bpf.skel.h: $(SCXOBJ_DIR)/%.bpf.o $(INCLUDE_DIR)/vmlinux.h $(BP
# C schedulers #
################
c-sched-targets := \
dsp_fallbackdsq_fail \
dsp_localdsq_fail \
enq_last_no_enq_fails \
enqueue_select_cpu_fails \
init_enable_count \
minimal \
select_cpu_dfl \
select_cpu_dfl_nodispatch \
select_cpu_dispatch \
Expand All @@ -172,9 +166,39 @@ override define CLEAN
rm -rf $(OUTPUT_DIR)
rm -f *.o *.bpf.o *.bpf.skel.h *.bpf.subskel.h
rm -f $(TEST_GEN_PROGS)
rm -f runner
endef

all: $(TEST_GEN_PROGS)
auto-test-targets := \
enq_last_no_enq_fails \
enq_select_cpu_fails \
ddsp_bogus_dsq_fail \
ddsp_vtimelocal_fail \
init_enable_count \
minimal \
test_example

testcase-targets := $(addsuffix .o,$(addprefix $(SCXOBJ_DIR)/,$(auto-test-targets)))

$(SCXOBJ_DIR)/runner.o: runner.c | $(SCXOBJ_DIR)
$(CC) $(CFLAGS) -c $< -o $@

# Create all of the test targets object files, whose testcase objects will be
# registered into the runner in ELF constructors.
#
# Note that we must do double expansion here in order to support conditionally
# compiling BPF object files only if one is present, as the wildcard Make
# function doesn't support using implicit rules otherwise.
.SECONDEXPANSION:
$(testcase-targets): $(SCXOBJ_DIR)/%.o: %.c $(SCXOBJ_DIR)/runner.o $$(if $$(wildcard $$*.bpf.c), $(INCLUDE_DIR)/%.bpf.skel.h) | $(SCXOBJ_DIR)
$(eval test=$(patsubst %.o,%.c,$(notdir $@)))
$(CC) $(CFLAGS) -c $< -o $@ $(SCXOBJ_DIR)/runner.o

runner: $(SCXOBJ_DIR)/runner.o $(BPFOBJ) $(testcase-targets)
@echo "$(testcase-targets)"
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^

all: runner

.PHONY: all clean help

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

char _license[] SEC("license") = "GPL";

s32 BPF_STRUCT_OPS(dsp_fallbackdsq_fail_select_cpu, struct task_struct *p,
s32 BPF_STRUCT_OPS(ddsp_bogus_dsq_fail_select_cpu, struct task_struct *p,
s32 prev_cpu, u64 wake_flags)
{
s32 cpu = scx_bpf_pick_idle_cpu(p->cpus_ptr, 0);
Expand All @@ -26,17 +26,17 @@ s32 BPF_STRUCT_OPS(dsp_fallbackdsq_fail_select_cpu, struct task_struct *p,
return prev_cpu;
}

s32 BPF_STRUCT_OPS(dsp_fallbackdsq_fail_init)
s32 BPF_STRUCT_OPS(ddsp_bogus_dsq_fail_init)
{
scx_bpf_switch_all();

return 0;
}

SEC(".struct_ops.link")
struct sched_ext_ops dsp_fallbackdsq_fail_ops = {
.select_cpu = dsp_fallbackdsq_fail_select_cpu,
.init = dsp_fallbackdsq_fail_init,
.name = "dsp_fallbackdsq_fail",
struct sched_ext_ops ddsp_bogus_dsq_fail_ops = {
.select_cpu = ddsp_bogus_dsq_fail_select_cpu,
.init = ddsp_bogus_dsq_fail_init,
.name = "ddsp_bogus_dsq_fail",
.timeout_ms = 1000U,
};
55 changes: 55 additions & 0 deletions tools/testing/selftests/scx/ddsp_bogus_dsq_fail.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2024 Meta Platforms, Inc. and affiliates.
* Copyright (c) 2024 David Vernet <dvernet@meta.com>
* Copyright (c) 2024 Tejun Heo <tj@kernel.org>
*/
#include <bpf/bpf.h>
#include <scx/common.h>
#include <sys/wait.h>
#include <unistd.h>
#include "ddsp_bogus_dsq_fail.bpf.skel.h"
#include "scx_test.h"

static enum scx_test_status setup(void **ctx)
{
struct ddsp_bogus_dsq_fail *skel;

skel = ddsp_bogus_dsq_fail__open_and_load();
SCX_FAIL_IF(!skel, "Failed to open and load skel");
*ctx = skel;

return SCX_TEST_PASS;
}

static enum scx_test_status run(void *ctx)
{
struct ddsp_bogus_dsq_fail *skel = ctx;
struct bpf_link *link;

link = bpf_map__attach_struct_ops(skel->maps.ddsp_bogus_dsq_fail_ops);
SCX_FAIL_IF(!link, "Failed to attach struct_ops");

sleep(1);
bpf_link__destroy(link);

return SCX_TEST_PASS;
}

static void cleanup(void *ctx)
{
struct ddsp_bogus_dsq_fail *skel = ctx;

ddsp_bogus_dsq_fail__destroy(skel);
}

struct scx_test ddsp_bogus_dsq_fail = {
.name = "ddsp_bogus_dsq_fail",
.description = "Verify we gracefully fail, and fall back to using a "
"built-in DSQ, if we do a direct dispatch to an invalid"
" DSQ in ops.select_cpu()",
.setup = setup,
.run = run,
.cleanup = cleanup,
};
REGISTER_SCX_TEST(&ddsp_bogus_dsq_fail)
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

char _license[] SEC("license") = "GPL";

s32 BPF_STRUCT_OPS(dsp_localdsq_fail_select_cpu, struct task_struct *p,
s32 BPF_STRUCT_OPS(ddsp_vtimelocal_fail_select_cpu, struct task_struct *p,
s32 prev_cpu, u64 wake_flags)
{
s32 cpu = scx_bpf_pick_idle_cpu(p->cpus_ptr, 0);
Expand All @@ -23,17 +23,17 @@ s32 BPF_STRUCT_OPS(dsp_localdsq_fail_select_cpu, struct task_struct *p,
return prev_cpu;
}

s32 BPF_STRUCT_OPS(dsp_localdsq_fail_init)
s32 BPF_STRUCT_OPS(ddsp_vtimelocal_fail_init)
{
scx_bpf_switch_all();

return 0;
}

SEC(".struct_ops.link")
struct sched_ext_ops dsp_localdsq_fail_ops = {
.select_cpu = dsp_localdsq_fail_select_cpu,
.init = dsp_localdsq_fail_init,
.name = "dsp_localdsq_fail",
struct sched_ext_ops ddsp_vtimelocal_fail_ops = {
.select_cpu = ddsp_vtimelocal_fail_select_cpu,
.init = ddsp_vtimelocal_fail_init,
.name = "ddsp_vtimelocal_fail",
.timeout_ms = 1000U,
};
54 changes: 54 additions & 0 deletions tools/testing/selftests/scx/ddsp_vtimelocal_fail.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2024 Meta Platforms, Inc. and affiliates.
* Copyright (c) 2024 David Vernet <dvernet@meta.com>
* Copyright (c) 2024 Tejun Heo <tj@kernel.org>
*/
#include <bpf/bpf.h>
#include <scx/common.h>
#include <unistd.h>
#include "ddsp_vtimelocal_fail.bpf.skel.h"
#include "scx_test.h"

static enum scx_test_status setup(void **ctx)
{
struct ddsp_vtimelocal_fail *skel;

skel = ddsp_vtimelocal_fail__open_and_load();
SCX_FAIL_IF(!skel, "Failed to open and load skel");
*ctx = skel;

return SCX_TEST_PASS;
}

static enum scx_test_status run(void *ctx)
{
struct ddsp_vtimelocal_fail *skel = ctx;
struct bpf_link *link;

link = bpf_map__attach_struct_ops(skel->maps.ddsp_vtimelocal_fail_ops);
SCX_FAIL_IF(!link, "Failed to attach struct_ops");

sleep(1);
bpf_link__destroy(link);

return SCX_TEST_PASS;
}

static void cleanup(void *ctx)
{
struct ddsp_vtimelocal_fail *skel = ctx;

ddsp_vtimelocal_fail__destroy(skel);
}

struct scx_test ddsp_vtimelocal_fail = {
.name = "ddsp_vtimelocal_fail",
.description = "Verify we gracefully fail, and fall back to using a "
"built-in DSQ, if we do a direct vtime dispatch to a "
"built-in DSQ from DSQ in ops.select_cpu()",
.setup = setup,
.run = run,
.cleanup = cleanup,
};
REGISTER_SCX_TEST(&ddsp_vtimelocal_fail)
36 changes: 0 additions & 36 deletions tools/testing/selftests/scx/dsp_fallbackdsq_fail.c

This file was deleted.

36 changes: 0 additions & 36 deletions tools/testing/selftests/scx/dsp_localdsq_fail.c

This file was deleted.

50 changes: 38 additions & 12 deletions tools/testing/selftests/scx/enq_last_no_enq_fails.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,57 @@
* Copyright (c) 2023 David Vernet <dvernet@meta.com>
* Copyright (c) 2023 Tejun Heo <tj@kernel.org>
*/
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <libgen.h>
#include <bpf/bpf.h>
#include <scx/common.h>
#include <sys/wait.h>
#include <unistd.h>
#include "enq_last_no_enq_fails.bpf.skel.h"
#include "scx_test.h"

int main(int argc, char **argv)
static enum scx_test_status setup(void **ctx)
{
struct enq_last_no_enq_fails *skel;
struct bpf_link *link;

libbpf_set_strict_mode(LIBBPF_STRICT_ALL);

skel = enq_last_no_enq_fails__open_and_load();
SCX_BUG_ON(!skel, "Failed to open and load skel");
if (!skel) {
SCX_ERR("Failed to open and load skel");
return SCX_TEST_FAIL;
}
*ctx = skel;

return SCX_TEST_PASS;
}

static enum scx_test_status run(void *ctx)
{
struct enq_last_no_enq_fails *skel = ctx;
struct bpf_link *link;

link = bpf_map__attach_struct_ops(skel->maps.enq_last_no_enq_fails_ops);
SCX_BUG_ON(link, "Succeeded in attaching struct_ops");
if (link) {
SCX_ERR("Incorrectly succeeded in to attaching scheduler");
return SCX_TEST_FAIL;
}

bpf_link__destroy(link);
enq_last_no_enq_fails__destroy(skel);

return 0;
return SCX_TEST_PASS;
}

static void cleanup(void *ctx)
{
struct enq_last_no_enq_fails *skel = ctx;

enq_last_no_enq_fails__destroy(skel);
}

struct scx_test enq_last_no_enq_fails = {
.name = "enq_last_no_enq_fails",
.description = "Verify we fail to load a scheduler if we specify "
"the SCX_OPS_ENQ_LAST flag without defining "
"ops.enqueue()",
.setup = setup,
.run = run,
.cleanup = cleanup,
};
REGISTER_SCX_TEST(&enq_last_no_enq_fails)
Loading

0 comments on commit 228db9d

Please sign in to comment.