Currently KVM lacks a simple, userspace agnostic, performance benchmark for
dirty logging. Such a benchmark will be beneficial for ensuring that dirty
logging performance does not regress, and to give a common baseline for
validating performance improvements. The dirty log perf test introduced in
this series builds on aspects of the existing demand paging perf test and
provides time-based performance metrics for enabling and disabling dirty
logging, getting the dirty log, and dirtying memory.
While the test currently only has a build target for x86, I expect it will
work on, or be easily modified to support other architectures.
Ben Gardon (5):
KVM: selftests: Factor code out of demand_paging_test
KVM: selftests: Remove address rounding in guest code
KVM: selftests: Simplify demand_paging_test with timespec_diff_now
KVM: selftests: Add wrfract to common guest code
KVM: selftests: Introduce the dirty log perf test
tools/testing/selftests/kvm/.gitignore | 1 +
tools/testing/selftests/kvm/Makefile | 1 +
.../selftests/kvm/demand_paging_test.c | 230 ++---------
.../selftests/kvm/dirty_log_perf_test.c | 382 ++++++++++++++++++
.../selftests/kvm/include/perf_test_util.h | 192 +++++++++
.../testing/selftests/kvm/include/test_util.h | 2 +
tools/testing/selftests/kvm/lib/test_util.c | 22 +-
7 files changed, 635 insertions(+), 195 deletions(-)
create mode 100644 tools/testing/selftests/kvm/dirty_log_perf_test.c
create mode 100644 tools/testing/selftests/kvm/include/perf_test_util.h
--
2.29.0.rc2.309.g374f81d7ae-goog
Implementation of support for parameterized testing in KUnit.
This approach requires the creation of a test case using the
KUNIT_CASE_PARAM macro that accepts a generator function as input.
This generator function should return the next parameter given the
previous parameter in parameterized tests. It also provides
a macro to generate common-case generators.
Signed-off-by: Arpitha Raghunandan <98.arpi(a)gmail.com>
Co-developed-by: Marco Elver <elver(a)google.com>
Signed-off-by: Marco Elver <elver(a)google.com>
---
Changes v3->v4:
- Rename kunit variables
- Rename generator function helper macro
- Add documentation for generator approach
- Display test case name in case of failure along with param index
Changes v2->v3:
- Modifictaion of generator macro and method
Changes v1->v2:
- Use of a generator method to access test case parameters
include/kunit/test.h | 34 ++++++++++++++++++++++++++++++++++
lib/kunit/test.c | 21 ++++++++++++++++++++-
2 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/include/kunit/test.h b/include/kunit/test.h
index 9197da792336..ec2307ee9bb0 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -107,6 +107,13 @@ struct kunit;
*
* @run_case: the function representing the actual test case.
* @name: the name of the test case.
+ * @generate_params: the generator function for parameterized tests.
+ *
+ * The generator function is used to lazily generate a series of
+ * arbitrarily typed values that fit into a void*. The argument @prev
+ * is the previously returned value, which should be used to derive the
+ * next value; @prev is set to NULL on the initial generator call.
+ * When no more values are available, the generator must return NULL.
*
* A test case is a function with the signature,
* ``void (*)(struct kunit *)``
@@ -141,6 +148,7 @@ struct kunit;
struct kunit_case {
void (*run_case)(struct kunit *test);
const char *name;
+ void* (*generate_params)(void *prev);
/* private: internal use only. */
bool success;
@@ -162,6 +170,9 @@ static inline char *kunit_status_to_string(bool status)
* &struct kunit_case for an example on how to use it.
*/
#define KUNIT_CASE(test_name) { .run_case = test_name, .name = #test_name }
+#define KUNIT_CASE_PARAM(test_name, gen_params) \
+ { .run_case = test_name, .name = #test_name, \
+ .generate_params = gen_params }
/**
* struct kunit_suite - describes a related collection of &struct kunit_case
@@ -208,6 +219,15 @@ struct kunit {
const char *name; /* Read only after initialization! */
char *log; /* Points at case log after initialization */
struct kunit_try_catch try_catch;
+ /* param_value points to test case parameters in parameterized tests */
+ void *param_value;
+ /*
+ * param_index stores the index of the parameter in
+ * parameterized tests. param_index + 1 is printed
+ * to indicate the parameter that causes the test
+ * to fail in case of test failure.
+ */
+ int param_index;
/*
* success starts as true, and may only be set to false during a
* test case; thus, it is safe to update this across multiple
@@ -1742,4 +1762,18 @@ do { \
fmt, \
##__VA_ARGS__)
+/**
+ * KUNIT_ARRAY_PARAM() - Helper method for test parameter generators
+ * required in parameterized tests.
+ * @name: prefix of the name for the test parameter generator function.
+ * It will be suffixed by "_gen_params".
+ * @array: a user-supplied pointer to an array of test parameters.
+ */
+#define KUNIT_ARRAY_PARAM(name, array) \
+ static void *name##_gen_params(void *prev) \
+ { \
+ typeof((array)[0]) * __next = prev ? ((typeof(__next)) prev) + 1 : (array); \
+ return __next - (array) < ARRAY_SIZE((array)) ? __next : NULL; \
+ }
+
#endif /* _KUNIT_TEST_H */
diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index 750704abe89a..8ad908b61494 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -127,6 +127,12 @@ unsigned int kunit_test_case_num(struct kunit_suite *suite,
}
EXPORT_SYMBOL_GPL(kunit_test_case_num);
+static void kunit_print_failed_param(struct kunit *test)
+{
+ kunit_err(test, "\n\tTest failed at:\n\ttest case: %s\n\tparameter: %d\n",
+ test->name, test->param_index + 1);
+}
+
static void kunit_print_string_stream(struct kunit *test,
struct string_stream *stream)
{
@@ -168,6 +174,8 @@ static void kunit_fail(struct kunit *test, struct kunit_assert *assert)
assert->format(assert, stream);
kunit_print_string_stream(test, stream);
+ if (test->param_value)
+ kunit_print_failed_param(test);
WARN_ON(string_stream_destroy(stream));
}
@@ -239,7 +247,18 @@ static void kunit_run_case_internal(struct kunit *test,
}
}
- test_case->run_case(test);
+ if (!test_case->generate_params) {
+ test_case->run_case(test);
+ } else {
+ test->param_value = test_case->generate_params(NULL);
+ test->param_index = 0;
+
+ while (test->param_value) {
+ test_case->run_case(test);
+ test->param_value = test_case->generate_params(test->param_value);
+ test->param_index++;
+ }
+ }
}
static void kunit_case_internal_cleanup(struct kunit *test)
--
2.25.1
This patch set adds AF_XDP selftests based on veth to selftests/xsk/.
# Topology:
# ---------
# -----------
# _ | Process | _
# / ----------- \
# / | \
# / | \
# ----------- | -----------
# | Thread1 | | | Thread2 |
# ----------- | -----------
# | | |
# ----------- | -----------
# | xskX | | | xskY |
# ----------- | -----------
# | | |
# ----------- | ----------
# | vethX | --------- | vethY |
# ----------- peer ----------
# | | |
# namespaceX | namespaceY
These selftests test AF_XDP SKB and Native/DRV modes using veth Virtual
Ethernet interfaces.
The test program contains two threads, each thread is single socket with
a unique UMEM. It validates in-order packet delivery and packet content
by sending packets to each other.
Prerequisites setup by script TEST_PREREQUISITES.sh:
Set up veth interfaces as per the topology shown ^^:
* setup two veth interfaces and one namespace
** veth<xxxx> in root namespace
** veth<yyyy> in af_xdp<xxxx> namespace
** namespace af_xdp<xxxx>
* create a spec file veth.spec that includes this run-time configuration
that is read by test scripts - filenames prefixed with TEST_XSK
*** xxxx and yyyy are randomly generated 4 digit numbers used to avoid
conflict with any existing interface.
The following tests are provided:
1. AF_XDP SKB mode
Generic mode XDP is driver independent, used when the driver does
not have support for XDP. Works on any netdevice using sockets and
generic XDP path. XDP hook from netif_receive_skb().
a. nopoll - soft-irq processing
b. poll - using poll() syscall
c. Socket Teardown
Create a Tx and a Rx socket, Tx from one socket, Rx on another.
Destroy both sockets, then repeat multiple times. Only nopoll mode
is used
d. Bi-directional Sockets
Configure sockets as bi-directional tx/rx sockets, sets up fill
and completion rings on each socket, tx/rx in both directions.
Only nopoll mode is used
2. AF_XDP DRV/Native mode
Works on any netdevice with XDP_REDIRECT support, driver dependent.
Processes packets before SKB allocation. Provides better performance
than SKB. Driver hook available just after DMA of buffer descriptor.
a. nopoll
b. poll
c. Socket Teardown
d. Bi-directional Sockets
* Only copy mode is supported because veth does not currently support
zero-copy mode
Total tests: 8.
Flow:
* Single process spawns two threads: Tx and Rx
* Each of these two threads attach to a veth interface within their
assigned namespaces
* Each thread creates one AF_XDP socket connected to a unique umem
for each veth interface
* Tx thread transmits 10k packets from veth<xxxx> to veth<yyyy>
* Rx thread verifies if all 10k packets were received and delivered
in-order, and have the right content
Structure of the patch set:
Patch 1: This patch adds XSK Selftests framework under
tools/testing/selftests/xsk, and README
Patch 2: Adds tests: SKB poll and nopoll mode, mac-ip-udp debug,
and README updates
Patch 3: Adds tests: DRV poll and nopoll mode, and README updates
Patch 4: Adds tests: SKB and DRV Socket Teardown, and README updates
Patch 5: Adds tests: SKB and DRV Bi-directional Sockets, and README
updates
Thanks: Weqaar
Weqaar Janjua (5):
selftests/xsk: xsk selftests framework
selftests/xsk: xsk selftests - SKB POLL, NOPOLL
selftests/xsk: xsk selftests - DRV POLL, NOPOLL
selftests/xsk: xsk selftests - Socket Teardown - SKB, DRV
selftests/xsk: xsk selftests - Bi-directional Sockets - SKB, DRV
MAINTAINERS | 1 +
tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/xsk/Makefile | 34 +
tools/testing/selftests/xsk/README | 125 +++
.../selftests/xsk/TEST_PREREQUISITES.sh | 53 +
tools/testing/selftests/xsk/TEST_XSK.sh | 15 +
.../xsk/TEST_XSK_DRV_BIDIRECTIONAL.sh | 22 +
.../selftests/xsk/TEST_XSK_DRV_NOPOLL.sh | 18 +
.../selftests/xsk/TEST_XSK_DRV_POLL.sh | 18 +
.../selftests/xsk/TEST_XSK_DRV_TEARDOWN.sh | 18 +
.../xsk/TEST_XSK_SKB_BIDIRECTIONAL.sh | 19 +
.../selftests/xsk/TEST_XSK_SKB_NOPOLL.sh | 18 +
.../selftests/xsk/TEST_XSK_SKB_POLL.sh | 18 +
.../selftests/xsk/TEST_XSK_SKB_TEARDOWN.sh | 18 +
tools/testing/selftests/xsk/config | 12 +
tools/testing/selftests/xsk/prereqs.sh | 119 ++
tools/testing/selftests/xsk/xdpprogs/Makefile | 64 ++
.../selftests/xsk/xdpprogs/Makefile.target | 68 ++
.../selftests/xsk/xdpprogs/xdpxceiver.c | 1000 +++++++++++++++++
.../selftests/xsk/xdpprogs/xdpxceiver.h | 159 +++
tools/testing/selftests/xsk/xskenv.sh | 33 +
21 files changed, 1833 insertions(+)
create mode 100644 tools/testing/selftests/xsk/Makefile
create mode 100644 tools/testing/selftests/xsk/README
create mode 100755 tools/testing/selftests/xsk/TEST_PREREQUISITES.sh
create mode 100755 tools/testing/selftests/xsk/TEST_XSK.sh
create mode 100755 tools/testing/selftests/xsk/TEST_XSK_DRV_BIDIRECTIONAL.sh
create mode 100755 tools/testing/selftests/xsk/TEST_XSK_DRV_NOPOLL.sh
create mode 100755 tools/testing/selftests/xsk/TEST_XSK_DRV_POLL.sh
create mode 100755 tools/testing/selftests/xsk/TEST_XSK_DRV_TEARDOWN.sh
create mode 100755 tools/testing/selftests/xsk/TEST_XSK_SKB_BIDIRECTIONAL.sh
create mode 100755 tools/testing/selftests/xsk/TEST_XSK_SKB_NOPOLL.sh
create mode 100755 tools/testing/selftests/xsk/TEST_XSK_SKB_POLL.sh
create mode 100755 tools/testing/selftests/xsk/TEST_XSK_SKB_TEARDOWN.sh
create mode 100644 tools/testing/selftests/xsk/config
create mode 100755 tools/testing/selftests/xsk/prereqs.sh
create mode 100644 tools/testing/selftests/xsk/xdpprogs/Makefile
create mode 100644 tools/testing/selftests/xsk/xdpprogs/Makefile.target
create mode 100644 tools/testing/selftests/xsk/xdpprogs/xdpxceiver.c
create mode 100644 tools/testing/selftests/xsk/xdpprogs/xdpxceiver.h
create mode 100755 tools/testing/selftests/xsk/xskenv.sh
--
2.20.1
# Background
KUnit currently lacks any first-class support for mocking.
For an overview and discussion on the pros and cons, see
https://martinfowler.com/articles/mocksArentStubs.html
This patch set introduces the basic machinery needed for mocking:
setting and validating expectations, setting default actions, etc.
Using that basic infrastructure, we add macros for "class mocking", as
it's probably the easiest type of mocking to start with.
## Class mocking
By "class mocking", we're referring mocking out function pointers stored
in structs like:
struct sender {
int (*send)(struct sender *sender, int data);
};
or in ops structs
struct sender {
struct send_ops *ops; // contains `send`
};
After the necessary DEFINE_* macros, we can then write code like
struct MOCK(sender) mock_sender = CONSTRUCT_MOCK(sender, test);
/* Fake an error for a specific input. */
handle = KUNIT_EXPECT_CALL(send(<omitted>, kunit_int_eq(42)));
handle->action = kunit_int_return(test, -EINVAL);
/* Pass the mocked object to some code under test. */
KUNIT_EXPECT_EQ(test, -EINVAL, send_message(...));
I.e. the goal is to make it easier to test
1) with less dependencies (we don't need to setup a real `sender`)
2) unusual/error conditions more easily.
In the future, we hope to build upon this to support mocking in more
contexts, e.g. standalone funcs, etc.
# TODOs
## Naming
This introduces a number of new macros for dealing with mocks,
e.g:
DEFINE_STRUCT_CLASS_MOCK(METHOD(foo), CLASS(example),
RETURNS(int),
PARAMS(struct example *, int));
...
KUNIT_EXPECT_CALL(foo(mock_get_ctrl(mock_example), ...);
For consistency, we could prefix everything with KUNIT, e.g.
`KUNIT_DEFINE_STRUCT_CLASS_MOCK` and `kunit_mock_get_ctrl`, but it feels
like the names might be long enough that they would hinder readability.
## Usage
For now the only use of class mocking is in kunit-example-test.c
As part of changing this from an RFC to a real patch set, we're hoping
to include at least one example.
Pointers to bits of code where this would be useful that aren't too
hairy would be appreciated.
E.g. could easily add a test for tools/perf/ui/progress.h, e.g. that
ui_progress__init() calls ui_progress_ops.init(), but that likely isn't
useful to anyone.
---
v2:
* Pass `struct kunit *` to mock init's to allow allocating ops structs.
* Update kunit-example-test.cc to do so as a more realistic example.
v1: https://lore.kernel.org/linux-kselftest/20200918183114.2571146-1-dlatypov@g…
---
Brendan Higgins (9):
kunit: test: add kunit_stream a std::stream like logger
kunit: test: add concept of post conditions
checkpatch: add support for struct MOCK(foo) syntax
kunit: mock: add parameter list manipulation macros
kunit: mock: add internal mock infrastructure
kunit: mock: add basic matchers and actions
kunit: mock: add class mocking support
kunit: mock: add struct param matcher
kunit: mock: implement nice, strict and naggy mock distinctions
Daniel Latypov (2):
Revert "kunit: move string-stream.h to lib/kunit"
kunit: expose kunit_set_failure() for use by mocking
Marcelo Schmitt (1):
kunit: mock: add macro machinery to pick correct format args
include/kunit/assert.h | 3 +-
include/kunit/kunit-stream.h | 94 +++
include/kunit/mock.h | 902 +++++++++++++++++++++++++
include/kunit/params.h | 305 +++++++++
{lib => include}/kunit/string-stream.h | 2 +
include/kunit/test.h | 9 +
lib/kunit/Makefile | 9 +-
lib/kunit/assert.c | 2 -
lib/kunit/common-mocks.c | 409 +++++++++++
lib/kunit/kunit-example-test.c | 98 +++
lib/kunit/kunit-stream.c | 110 +++
lib/kunit/mock-macro-test.c | 241 +++++++
lib/kunit/mock-test.c | 531 +++++++++++++++
lib/kunit/mock.c | 370 ++++++++++
lib/kunit/string-stream-test.c | 3 +-
lib/kunit/string-stream.c | 5 +-
lib/kunit/test.c | 15 +-
scripts/checkpatch.pl | 4 +
18 files changed, 3099 insertions(+), 13 deletions(-)
create mode 100644 include/kunit/kunit-stream.h
create mode 100644 include/kunit/mock.h
create mode 100644 include/kunit/params.h
rename {lib => include}/kunit/string-stream.h (95%)
create mode 100644 lib/kunit/common-mocks.c
create mode 100644 lib/kunit/kunit-stream.c
create mode 100644 lib/kunit/mock-macro-test.c
create mode 100644 lib/kunit/mock-test.c
create mode 100644 lib/kunit/mock.c
base-commit: 10b82d5176488acee2820e5a2cf0f2ec5c3488b6
--
2.28.0.1011.ga647a8990f-goog
Nowadays, there are increasing requirements to benchmark the performance
of dma_map and dma_unmap particually while the device is attached to an
IOMMU.
This patchset provides the benchmark infrastruture for streaming DMA
mapping. The architecture of the code is pretty much similar with GUP
benchmark:
* mm/gup_benchmark.c provides kernel interface;
* tools/testing/selftests/vm/gup_benchmark.c provides user program to
call the interface provided by mm/gup_benchmark.c.
In our case, kernel/dma/map_benchmark.c is like mm/gup_benchmark.c;
tools/testing/selftests/dma/dma_map_benchmark.c is like tools/testing/
selftests/vm/gup_benchmark.c
A major difference with GUP benchmark is DMA_MAP benchmark needs to run
on a device. Considering one board with below devices and IOMMUs
device A ------- IOMMU 1
device B ------- IOMMU 2
device C ------- non-IOMMU
Different devices might attach to different IOMMU or non-IOMMU. To make
benchmark run, we can either
* create a virtual device and hack the kernel code to attach the virtual
device to IOMMU1, IOMMU2 or non-IOMMU.
* use the existing driver_override mechinism, unbind device A,B, or c from
their original driver and bind them to "dma_map_benchmark" platform_driver
or pci_driver for benchmarking.
In this patchset, I prefer to use the driver_override and avoid the various
hack in kernel. We can dynamically switch devices behind different IOMMUs
to get the performance of dma map on IOMMU or non-IOMMU.
Barry Song (2):
dma-mapping: add benchmark support for streaming DMA APIs
selftests/dma: add test application for DMA_MAP_BENCHMARK
MAINTAINERS | 6 +
kernel/dma/Kconfig | 8 +
kernel/dma/Makefile | 1 +
kernel/dma/map_benchmark.c | 202 ++++++++++++++++++
tools/testing/selftests/dma/Makefile | 6 +
tools/testing/selftests/dma/config | 1 +
.../testing/selftests/dma/dma_map_benchmark.c | 72 +++++++
7 files changed, 296 insertions(+)
create mode 100644 kernel/dma/map_benchmark.c
create mode 100644 tools/testing/selftests/dma/Makefile
create mode 100644 tools/testing/selftests/dma/config
create mode 100644 tools/testing/selftests/dma/dma_map_benchmark.c
--
2.25.1
For simplcity, strip all trailing whitespace from parsed output.
I imagine no one is printing out meaningful trailing whitespace via
KUNIT_FAIL() or similar, and that if they are, they really shouldn't.
`isolate_kunit_output()` yielded liens with trailing \n, which results
in artifacty output like this:
$ ./tools/testing/kunit/kunit.py run
[16:16:46] [FAILED] example_simple_test
[16:16:46] # example_simple_test: EXPECTATION FAILED at lib/kunit/kunit-example-test.c:29
[16:16:46] Expected 1 + 1 == 3, but
[16:16:46] 1 + 1 == 2
[16:16:46] 3 == 3
[16:16:46] not ok 1 - example_simple_test
[16:16:46]
After this change:
[16:16:46] # example_simple_test: EXPECTATION FAILED at lib/kunit/kunit-example-test.c:29
[16:16:46] Expected 1 + 1 == 3, but
[16:16:46] 1 + 1 == 2
[16:16:46] 3 == 3
[16:16:46] not ok 1 - example_simple_test
[16:16:46]
We should *not* be expecting lines to end with \n in kunit_tool_test.py
for this reason.
Do the same for `raw_output()` as well which suffers from the same
issue.
This is a followup to [1], but rebased onto kunit-fixes to pick up the
other raw_output() fix and fixes for kunit_tool_test.py.
[1] https://lore.kernel.org/linux-kselftest/20201020233219.4146059-1-dlatypov@g…
Signed-off-by: Daniel Latypov <dlatypov(a)google.com>
---
tools/testing/kunit/kunit_parser.py | 3 ++-
tools/testing/kunit/kunit_tool_test.py | 4 ++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/testing/kunit/kunit_parser.py b/tools/testing/kunit/kunit_parser.py
index 84a1af2581f5..edd6fbd1cf18 100644
--- a/tools/testing/kunit/kunit_parser.py
+++ b/tools/testing/kunit/kunit_parser.py
@@ -54,6 +54,7 @@ kunit_end_re = re.compile('(List of all partitions:|'
def isolate_kunit_output(kernel_output):
started = False
for line in kernel_output:
+ line = line.rstrip() # line always has a trailing \n
if kunit_start_re.search(line):
prefix_len = len(line.split('TAP version')[0])
started = True
@@ -65,7 +66,7 @@ def isolate_kunit_output(kernel_output):
def raw_output(kernel_output):
for line in kernel_output:
- print(line)
+ print(line.rstrip())
DIVIDER = '=' * 60
diff --git a/tools/testing/kunit/kunit_tool_test.py b/tools/testing/kunit/kunit_tool_test.py
index 0b60855fb819..497ab51bc170 100755
--- a/tools/testing/kunit/kunit_tool_test.py
+++ b/tools/testing/kunit/kunit_tool_test.py
@@ -102,7 +102,7 @@ class KUnitParserTest(unittest.TestCase):
'test_data/test_output_isolated_correctly.log')
file = open(log_path)
result = kunit_parser.isolate_kunit_output(file.readlines())
- self.assertContains('TAP version 14\n', result)
+ self.assertContains('TAP version 14', result)
self.assertContains(' # Subtest: example', result)
self.assertContains(' 1..2', result)
self.assertContains(' ok 1 - example_simple_test', result)
@@ -115,7 +115,7 @@ class KUnitParserTest(unittest.TestCase):
'test_data/test_pound_sign.log')
with open(log_path) as file:
result = kunit_parser.isolate_kunit_output(file.readlines())
- self.assertContains('TAP version 14\n', result)
+ self.assertContains('TAP version 14', result)
self.assertContains(' # Subtest: kunit-resource-test', result)
self.assertContains(' 1..5', result)
self.assertContains(' ok 1 - kunit_resource_test_init_resources', result)
base-commit: cab67acc8a18d7c6f1850313e3da1a030abe8fc4
--
2.29.1.341.ge80a0c044ae-goog