Skip to content

Commit

Permalink
Add relacy tests into stdexec source tree
Browse files Browse the repository at this point in the history
  • Loading branch information
ccotter committed Sep 14, 2024
1 parent 7b202a1 commit 37ef4c4
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 0 deletions.
59 changes: 59 additions & 0 deletions test/rrd/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# User-customizable variables:
CXX ?= c++
CXX_STD ?= c++20
CXXFLAGS ?= -I relacy -I relacy/relacy/fakestd -O1 -std=$(CXX_STD) -I ../../include -I ../../test -g
DEPFLAGS ?= -MD -MF $(@).d -MP -MT $(@)
build_dir = build

.SECONDARY:

test_programs = split async_scope

test_exe_files = $(foreach name,$(test_programs),$(build_dir)/$(name))

exe_files = $(test_exe_files)
o_files = $(exe_files:=.cpp.o)

ansi_term_csi = [
ansi_term_bold = $(ansi_term_csi)1m
ansi_term_green = $(ansi_term_csi)32m
ansi_term_red = $(ansi_term_csi)31m
ansi_term_reset = $(ansi_term_csi)m

COMPILE.cpp = $(CXX) $(DEPFLAGS) $(CXXFLAGS) -c
LINK.cpp = $(CXX) $(CXXFLAGS)

.PHONY: all
all: tests

.PHONY: tests
tests: $(test_exe_files)

$(build_dir)/%.check-result: $(build_dir)/% always-run
@ \
printf '%s%s ...%s\n' $(ansi_term_bold) $(*) $(ansi_term_reset) >&2; \
$(<); \
status="$${?}"; \
printf %d "$${status}" >$(@); \
if [ "$${status}" -eq 0 ]; then \
printf '%s%s %s%s\n' $(ansi_term_green) $(*) OK $(ansi_term_reset); \
else \
printf '%s%s %s%s\n' $(ansi_term_red) $(*) FAIL $(ansi_term_reset); \
fi >&2; \
exit "$${status}"

$(build_dir)/%: $(build_dir)/%.cpp.o
$(LINK.cpp) $(^) -o $(@)

$(build_dir)/%.cpp.o: %.cpp
@mkdir -p $(dir $(@))
$(COMPILE.cpp) -o $(@) $(<)

.PHONY: clean
clean:
rm -fr -- $(build_dir)/

.PHONY: always-run
always-run:

-include $(o_files:=.d)
42 changes: 42 additions & 0 deletions test/rrd/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
## Relacy tests

[Relacy (RRD)](https://www.1024cores.net/home/relacy-race-detector/rrd-introduction)
is a data race detector. It replaces the OS scheduler with an scheduler that
explores many different thread interleavings, and logs detected races or assertion
failures. Relacy can also simulate relaxed hardware by simulating old values of a
variable as allowed by the C++11 memory model.

Relacy requires a specialized build. In particular, it is a header only library that
replaces the standard library and pthread APIs at compile time. Since it places some
standard library includes, writing new tests may require working around certain
limitations in terms of what the replacement headers and accompanying runtime can
support. For example, Relacy's atomic replacements cannot support `++x`, so the
stdexec library could needs to use `x.fetch_add(1)` to be compatible with Relacy.

## Instructions

Run the following commands from within this directory (`./tests/rrd`).

```
# TODO: Merge patches into upstream Relacy @ dvyukov's version
git clone -b stdexec https://github.com/ccotter/relacy
CXX=g++-11 make -j 4
./build/split
```

## Recommended use

The Relacy tests can be manually built and executed. New tests can be written for
new algorithms, or new use cases in the stdexec library.

At this time, integrating the tests into CI is not yet recommended. If we can figure
out a more stable build on all environments/compilers, we should revisit this.

## Supported platforms

The stdexec Relacy tests have been verified to build and run on
* Linux based GCC+11 with libstdc++ (`x86_64`)
* Mac with Apple Clang 15 with libc++ (`x86_64`)

G++12 and newer are known to have issues that could be addressed with patches
to Relacy.
51 changes: 51 additions & 0 deletions test/rrd/async_scope.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include "../../relacy/relacy_std.hpp"
#include "../../relacy/relacy_cli.hpp"

#include <stdexec/execution.hpp>
#include <exec/async_scope.hpp>
#include <exec/static_thread_pool.hpp>
#include <test_common/schedulers.hpp>
#include <test_common/type_helpers.hpp>

#include <chrono>
#include <random>
#include <iostream>

using rl::nvar;
using rl::nvolatile;
using rl::mutex;

namespace ex = stdexec;
using exec::async_scope;

struct async_scope_bug : rl::test_suite<async_scope_bug, 1>
{
static size_t const dynamic_thread_count = 2;

void thread(unsigned)
{
exec::static_thread_pool ctx{1};

ex::scheduler auto sch = ctx.get_scheduler();

exec::async_scope scope;
std::atomic_bool produced{false};
ex::sender auto begin = ex::schedule(sch);
{
ex::sender auto ftr = scope.spawn_future(begin | stdexec::then([&]() { produced.store(true); }));
(void) ftr;
}
stdexec::sync_wait(scope.on_empty() | stdexec::then([&]() {
RL_ASSERT(produced.load());
}));
}
};

int main()
{
rl::test_params p;
p.iteration_count = 50000;
p.execution_depth_limit = 10000;
rl::simulate<async_scope_bug>(p);
return 0;
}
45 changes: 45 additions & 0 deletions test/rrd/split.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "../../relacy/relacy_std.hpp"
#include "../../relacy/relacy_cli.hpp"

#include <stdexec/execution.hpp>
#include <exec/async_scope.hpp>
#include <exec/static_thread_pool.hpp>
#include <test_common/schedulers.hpp>

#include <chrono>
#include <random>
#include <iostream>

using rl::nvar;
using rl::nvolatile;
using rl::mutex;

namespace ex = stdexec;
using exec::async_scope;

struct split_bug : rl::test_suite<split_bug, 1>
{
static size_t const dynamic_thread_count = 2;

void thread(unsigned)
{
exec::static_thread_pool pool{1};
auto split = ex::schedule(pool.get_scheduler()) //
| ex::then([] {
return 42;
})
| ex::split();

auto [val] = ex::sync_wait(split).value();
RL_ASSERT(val == 42);
}
};

int main()
{
rl::test_params p;
p.iteration_count = 50000;
p.execution_depth_limit = 10000;
rl::simulate<split_bug>(p);
return 0;
}

0 comments on commit 37ef4c4

Please sign in to comment.