Skip to content

Commit 2752e04

Browse files
committed
Add some tuple pbt tests
1 parent 4aec31e commit 2752e04

File tree

7 files changed

+365
-15
lines changed

7 files changed

+365
-15
lines changed

.github/workflows/unit_tests.yml

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,10 @@ jobs:
9898
- name: Install build tools
9999
run: |
100100
${{ matrix.install }}
101-
sudo apt install -y ninja-build
101+
sudo apt install -y ninja-build pipx
102+
pipx install pytest
103+
pipx inject pytest pytest-forked pytest-xdist hypothesis
104+
echo "/opt/pipx_bin" >> $GITHUB_PATH
102105
103106
- name: Restore CPM cache
104107
env:
@@ -177,7 +180,10 @@ jobs:
177180
- name: Install build tools
178181
run: |
179182
${{ matrix.install }}
180-
sudo apt install -y ninja-build
183+
sudo apt install -y ninja-build pipx
184+
pipx install pytest
185+
pipx inject pytest pytest-forked pytest-xdist hypothesis
186+
echo "/opt/pipx_bin" >> $GITHUB_PATH
181187
182188
- name: Restore CPM cache
183189
env:
@@ -292,7 +298,10 @@ jobs:
292298
- name: Install build tools
293299
run: |
294300
${{ matrix.install }}
295-
sudo apt install -y ninja-build
301+
sudo apt install -y ninja-build pipx
302+
pipx install pytest
303+
pipx inject pytest pytest-forked pytest-xdist hypothesis
304+
echo "/opt/pipx_bin" >> $GITHUB_PATH
296305
297306
- name: Restore CPM cache
298307
env:
@@ -338,7 +347,10 @@ jobs:
338347

339348
- name: Install build tools
340349
run: |
341-
sudo apt update && sudo apt install -y gcc-${{env.DEFAULT_GCC_VERSION}} g++-${{env.DEFAULT_GCC_VERSION}} ninja-build valgrind
350+
sudo apt update && sudo apt install -y gcc-${{env.DEFAULT_GCC_VERSION}} g++-${{env.DEFAULT_GCC_VERSION}} ninja-build valgrind pipx
351+
pipx install pytest
352+
pipx inject pytest pytest-forked pytest-xdist hypothesis
353+
echo "/opt/pipx_bin" >> $GITHUB_PATH
342354
343355
- name: Restore CPM cache
344356
env:
@@ -409,7 +421,10 @@ jobs:
409421

410422
- name: Install build tools
411423
run: |
412-
sudo apt update && sudo apt install -y clang-${{env.MULL_LLVM_VERSION}} ninja-build
424+
sudo apt update && sudo apt install -y clang-${{env.MULL_LLVM_VERSION}} ninja-build pipx
425+
pipx install pytest
426+
pipx inject pytest pytest-forked pytest-xdist hypothesis
427+
echo "/opt/pipx_bin" >> $GITHUB_PATH
413428
414429
- name: Install mull
415430
env:

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@
1010
.cmake-format.yaml
1111
CMakePresets.json
1212
/toolchains
13+
__pycache__
14+
.mypy_cache
15+
.pytest_cache
16+
.hypothesis

include/stdx/tuple_algorithms.hpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -319,16 +319,17 @@ template <tuplelike... Ts> constexpr auto cartesian_product_copy(Ts &&...ts) {
319319
return []<typename First, typename... Rest>(First &&first,
320320
Rest &&...rest) {
321321
auto const c = cartesian_product_copy(std::forward<Rest>(rest)...);
322-
return std::forward<First>(first).apply(
323-
[&]<typename... Elems>(Elems &&...elems) {
324-
auto const prepend = [&]<typename E>(E &&e) {
325-
return c.apply([&](auto... subs) {
326-
return make_tuple(tuple_cat(
327-
make_tuple(std::forward<E>(e)), subs)...);
328-
});
329-
};
330-
return tuple_cat(prepend(std::forward<Elems>(elems))...);
331-
});
322+
return std::forward<First>(first).apply([&]<typename... Elems>(
323+
Elems &&...elems) {
324+
// NOTE: it's always used, but gcc sometimes gets it wrong :(
325+
[[maybe_unused]] auto const prepend = [&]<typename E>(E &&e) {
326+
return c.apply([&](auto... subs) {
327+
return make_tuple(
328+
tuple_cat(make_tuple(std::forward<E>(e)), subs)...);
329+
});
330+
};
331+
return tuple_cat(prepend(std::forward<Elems>(elems))...);
332+
});
332333
}(std::forward<Ts>(ts)...);
333334
}
334335
}

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,4 @@ if(${CMAKE_CXX_STANDARD} GREATER_EQUAL 20)
6464
endif()
6565

6666
add_subdirectory(fail)
67+
add_subdirectory(pbt)

test/pbt/CMakeLists.txt

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
set(COMPILER_ARGS
2+
--std=c++${CMAKE_CXX_STANDARD}
3+
-Wall
4+
-Wcast-align
5+
-Wconversion
6+
-Wdouble-promotion
7+
-Werror
8+
-Wextra
9+
-Wextra-semi
10+
-Wfatal-errors
11+
-Wformat=2
12+
-Wold-style-cast
13+
-Woverloaded-virtual
14+
-Wshadow
15+
-Wunused
16+
-Wno-missing-braces)
17+
18+
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
19+
list(
20+
APPEND
21+
COMPILER_ARGS
22+
-fbracket-depth=99999
23+
-Warray-bounds-pointer-arithmetic
24+
-Wextra-semi-stmt
25+
-Wgcc-compat
26+
-Wheader-hygiene
27+
-Widiomatic-parentheses
28+
-Wimplicit
29+
-Wnewline-eof
30+
-Wmissing-prototypes
31+
-Wno-gnu-string-literal-operator-template)
32+
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
33+
list(APPEND COMPILER_ARGS -Wduplicated-branches -Wduplicated-cond
34+
-Wlogical-op -Wuseless-cast)
35+
endif()
36+
37+
get_target_property(SANITIZER_COMPILER_ARGS sanitizers
38+
INTERFACE_COMPILE_OPTIONS)
39+
if(SANITIZER_COMPILER_ARGS AND NOT SANITIZER_COMPILER_ARGS STREQUAL
40+
"SANITIZER_COMPILER_ARGS-NOTFOUND")
41+
list(APPEND COMPILER_ARGS ${SANITIZER_COMPILER_ARGS})
42+
endif()
43+
44+
string(REPLACE ";" "," COMPILER_ARGS "${COMPILER_ARGS}")
45+
46+
get_target_property(INCLUDE_DIRS stdx INTERFACE_INCLUDE_DIRECTORIES)
47+
string(REPLACE ";" "," INCLUDE_DIRS "${INCLUDE_DIRS}")
48+
49+
if(${CMAKE_CXX_STANDARD} GREATER_EQUAL 20)
50+
add_unit_test(
51+
tuple
52+
PYTEST
53+
FILES
54+
tuple.py
55+
EXTRA_ARGS
56+
-vv
57+
-n2
58+
--compiler=${CMAKE_CXX_COMPILER}
59+
--compiler-args=${COMPILER_ARGS}
60+
--includes=${INCLUDE_DIRS})
61+
endif()

test/pbt/conftest.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import pytest
2+
import hypothesis
3+
import subprocess
4+
import tempfile
5+
import os
6+
7+
hypothesis.settings.register_profile("ci", max_examples=500)
8+
hypothesis.settings.register_profile("fast", max_examples=10)
9+
10+
11+
def pytest_addoption(parser):
12+
parser.addoption("--includes", action="store", help="C++ include directories", required=True)
13+
parser.addoption("--compiler", action="store", help="C++ compiler", required=True)
14+
parser.addoption("--compiler-args", action="store", help="C++ compiler arguments", default="", required=False)
15+
16+
17+
@pytest.fixture(scope="module")
18+
def compiler(pytestconfig):
19+
return pytestconfig.getoption("compiler")
20+
21+
@pytest.fixture(scope="module")
22+
def include_dirs(pytestconfig):
23+
return [i for i in pytestconfig.getoption("includes").split(",") if i]
24+
25+
@pytest.fixture(scope="module")
26+
def compiler_args(pytestconfig):
27+
args = pytestconfig.getoption("compiler_args")
28+
29+
if args:
30+
return [i for i in args.split(",") if i]
31+
else:
32+
return []
33+
34+
@pytest.fixture(scope="module")
35+
def compile(compiler, compiler_args, include_dirs):
36+
include_args = [f"-I{i}" for i in include_dirs]
37+
def f(code_str):
38+
code_str += "\n"
39+
with tempfile.NamedTemporaryFile(delete=False, suffix=".cpp") as temp_cpp_file:
40+
temp_cpp_file.write(code_str.encode('utf-8'))
41+
temp_cpp_file_path = temp_cpp_file.name
42+
43+
try:
44+
compile_command = [
45+
compiler, temp_cpp_file_path,
46+
"-o", temp_cpp_file_path + ".out"
47+
] + compiler_args + include_args
48+
49+
result = subprocess.run(compile_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
50+
51+
if result.returncode == 0:
52+
return True
53+
else:
54+
error_message = (
55+
f"Compiler returned non-zero exit code: {result.returncode}\n"
56+
f"Compilation command: {' '.join(compile_command)}\n"
57+
f"Source code:\n{code_str}\n"
58+
f"Compiler stderr:\n{result.stderr.decode('utf-8')}\n"
59+
f"Compiler stdout:\n{result.stdout.decode('utf-8')}\n"
60+
)
61+
pytest.fail(error_message)
62+
63+
except Exception as e:
64+
pytest.fail(str(e))
65+
finally:
66+
os.remove(temp_cpp_file_path)
67+
if os.path.exists(temp_cpp_file_path + ".out"):
68+
os.remove(temp_cpp_file_path + ".out")
69+
70+
return f
71+

0 commit comments

Comments
 (0)