Skip to content

Commit 37ef4c4

Browse files
committed
Add relacy tests into stdexec source tree
1 parent 7b202a1 commit 37ef4c4

File tree

4 files changed

+197
-0
lines changed

4 files changed

+197
-0
lines changed

test/rrd/Makefile

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# User-customizable variables:
2+
CXX ?= c++
3+
CXX_STD ?= c++20
4+
CXXFLAGS ?= -I relacy -I relacy/relacy/fakestd -O1 -std=$(CXX_STD) -I ../../include -I ../../test -g
5+
DEPFLAGS ?= -MD -MF $(@).d -MP -MT $(@)
6+
build_dir = build
7+
8+
.SECONDARY:
9+
10+
test_programs = split async_scope
11+
12+
test_exe_files = $(foreach name,$(test_programs),$(build_dir)/$(name))
13+
14+
exe_files = $(test_exe_files)
15+
o_files = $(exe_files:=.cpp.o)
16+
17+
ansi_term_csi = [
18+
ansi_term_bold = $(ansi_term_csi)1m
19+
ansi_term_green = $(ansi_term_csi)32m
20+
ansi_term_red = $(ansi_term_csi)31m
21+
ansi_term_reset = $(ansi_term_csi)m
22+
23+
COMPILE.cpp = $(CXX) $(DEPFLAGS) $(CXXFLAGS) -c
24+
LINK.cpp = $(CXX) $(CXXFLAGS)
25+
26+
.PHONY: all
27+
all: tests
28+
29+
.PHONY: tests
30+
tests: $(test_exe_files)
31+
32+
$(build_dir)/%.check-result: $(build_dir)/% always-run
33+
@ \
34+
printf '%s%s ...%s\n' $(ansi_term_bold) $(*) $(ansi_term_reset) >&2; \
35+
$(<); \
36+
status="$${?}"; \
37+
printf %d "$${status}" >$(@); \
38+
if [ "$${status}" -eq 0 ]; then \
39+
printf '%s%s %s%s\n' $(ansi_term_green) $(*) OK $(ansi_term_reset); \
40+
else \
41+
printf '%s%s %s%s\n' $(ansi_term_red) $(*) FAIL $(ansi_term_reset); \
42+
fi >&2; \
43+
exit "$${status}"
44+
45+
$(build_dir)/%: $(build_dir)/%.cpp.o
46+
$(LINK.cpp) $(^) -o $(@)
47+
48+
$(build_dir)/%.cpp.o: %.cpp
49+
@mkdir -p $(dir $(@))
50+
$(COMPILE.cpp) -o $(@) $(<)
51+
52+
.PHONY: clean
53+
clean:
54+
rm -fr -- $(build_dir)/
55+
56+
.PHONY: always-run
57+
always-run:
58+
59+
-include $(o_files:=.d)

test/rrd/README.md

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
## Relacy tests
2+
3+
[Relacy (RRD)](https://www.1024cores.net/home/relacy-race-detector/rrd-introduction)
4+
is a data race detector. It replaces the OS scheduler with an scheduler that
5+
explores many different thread interleavings, and logs detected races or assertion
6+
failures. Relacy can also simulate relaxed hardware by simulating old values of a
7+
variable as allowed by the C++11 memory model.
8+
9+
Relacy requires a specialized build. In particular, it is a header only library that
10+
replaces the standard library and pthread APIs at compile time. Since it places some
11+
standard library includes, writing new tests may require working around certain
12+
limitations in terms of what the replacement headers and accompanying runtime can
13+
support. For example, Relacy's atomic replacements cannot support `++x`, so the
14+
stdexec library could needs to use `x.fetch_add(1)` to be compatible with Relacy.
15+
16+
## Instructions
17+
18+
Run the following commands from within this directory (`./tests/rrd`).
19+
20+
```
21+
# TODO: Merge patches into upstream Relacy @ dvyukov's version
22+
git clone -b stdexec https://github.com/ccotter/relacy
23+
CXX=g++-11 make -j 4
24+
./build/split
25+
```
26+
27+
## Recommended use
28+
29+
The Relacy tests can be manually built and executed. New tests can be written for
30+
new algorithms, or new use cases in the stdexec library.
31+
32+
At this time, integrating the tests into CI is not yet recommended. If we can figure
33+
out a more stable build on all environments/compilers, we should revisit this.
34+
35+
## Supported platforms
36+
37+
The stdexec Relacy tests have been verified to build and run on
38+
* Linux based GCC+11 with libstdc++ (`x86_64`)
39+
* Mac with Apple Clang 15 with libc++ (`x86_64`)
40+
41+
G++12 and newer are known to have issues that could be addressed with patches
42+
to Relacy.

test/rrd/async_scope.cpp

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include "../../relacy/relacy_std.hpp"
2+
#include "../../relacy/relacy_cli.hpp"
3+
4+
#include <stdexec/execution.hpp>
5+
#include <exec/async_scope.hpp>
6+
#include <exec/static_thread_pool.hpp>
7+
#include <test_common/schedulers.hpp>
8+
#include <test_common/type_helpers.hpp>
9+
10+
#include <chrono>
11+
#include <random>
12+
#include <iostream>
13+
14+
using rl::nvar;
15+
using rl::nvolatile;
16+
using rl::mutex;
17+
18+
namespace ex = stdexec;
19+
using exec::async_scope;
20+
21+
struct async_scope_bug : rl::test_suite<async_scope_bug, 1>
22+
{
23+
static size_t const dynamic_thread_count = 2;
24+
25+
void thread(unsigned)
26+
{
27+
exec::static_thread_pool ctx{1};
28+
29+
ex::scheduler auto sch = ctx.get_scheduler();
30+
31+
exec::async_scope scope;
32+
std::atomic_bool produced{false};
33+
ex::sender auto begin = ex::schedule(sch);
34+
{
35+
ex::sender auto ftr = scope.spawn_future(begin | stdexec::then([&]() { produced.store(true); }));
36+
(void) ftr;
37+
}
38+
stdexec::sync_wait(scope.on_empty() | stdexec::then([&]() {
39+
RL_ASSERT(produced.load());
40+
}));
41+
}
42+
};
43+
44+
int main()
45+
{
46+
rl::test_params p;
47+
p.iteration_count = 50000;
48+
p.execution_depth_limit = 10000;
49+
rl::simulate<async_scope_bug>(p);
50+
return 0;
51+
}

test/rrd/split.cpp

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include "../../relacy/relacy_std.hpp"
2+
#include "../../relacy/relacy_cli.hpp"
3+
4+
#include <stdexec/execution.hpp>
5+
#include <exec/async_scope.hpp>
6+
#include <exec/static_thread_pool.hpp>
7+
#include <test_common/schedulers.hpp>
8+
9+
#include <chrono>
10+
#include <random>
11+
#include <iostream>
12+
13+
using rl::nvar;
14+
using rl::nvolatile;
15+
using rl::mutex;
16+
17+
namespace ex = stdexec;
18+
using exec::async_scope;
19+
20+
struct split_bug : rl::test_suite<split_bug, 1>
21+
{
22+
static size_t const dynamic_thread_count = 2;
23+
24+
void thread(unsigned)
25+
{
26+
exec::static_thread_pool pool{1};
27+
auto split = ex::schedule(pool.get_scheduler()) //
28+
| ex::then([] {
29+
return 42;
30+
})
31+
| ex::split();
32+
33+
auto [val] = ex::sync_wait(split).value();
34+
RL_ASSERT(val == 42);
35+
}
36+
};
37+
38+
int main()
39+
{
40+
rl::test_params p;
41+
p.iteration_count = 50000;
42+
p.execution_depth_limit = 10000;
43+
rl::simulate<split_bug>(p);
44+
return 0;
45+
}

0 commit comments

Comments
 (0)