Skip to content

Commit

Permalink
add build failure example with ctest (#29)
Browse files Browse the repository at this point in the history
Change-Id: I49f2a9991686715dda2e529b19206909ec1a7c79
  • Loading branch information
oliverlee authored Jan 6, 2024
1 parent 690e079 commit 4bfd605
Show file tree
Hide file tree
Showing 14 changed files with 172 additions and 47 deletions.
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,43 @@ When running tests, `skytest` will attempt to invoke test closures at
compile-time. If able to, results will be classified `CONSTEXPR PASS` or
`CONSTEXPR FAIL` instead of `PASS` or `FAIL`.

<details><summary>requiring compile-time evaluation of tests</summary>


The `ctest` literal can be used to require closures to be tested at
compile-time. In order to be usable with `ctest`, test closures must be empty
and non-constexpr functions must not be invoked.

```cpp:example/ctest_fail.cpp
#include "skytest/skytest.hpp"

auto main() -> int
{
using namespace skytest::literals;
using ::skytest::expect;
using ::skytest::lt;

static auto n = 0;
"read non-const"_ctest = [] { return expect(lt(0, n)); };
}

```

results in the follow build error (snippet):

```console:example/ctest_fail.log
external/skytest/src/detail/test_style.hpp:43:27: error: the value of 'n' is not usable in a constant expression
43 | static constexpr auto value = std::optional<bool>{bool{F{}()}};
| ^~~~~
ctest_fail.cpp:9:15: note: 'int n' is not const
9 | static auto n = 0;
| ^
```

</details>


## examples

#### binary comparisons
Expand Down
12 changes: 12 additions & 0 deletions example/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
load("//rules:sh_binary_template.bzl", "sh_binary_template")
load("//rules:binary_log.bzl", "synchronized_binary_log")

cc_library(
Expand Down Expand Up @@ -30,6 +31,17 @@ synchronized_binary_log(
src = ":minimal_fail",
)

sh_binary_template(
name = "ctest_fail",
srcs = ["ctest_fail.sh.tmpl"],
data = ["ctest_fail.cpp"],
)

synchronized_binary_log(
name = "ctest_fail_log",
src = ":ctest_fail",
)

cc_test(
name = "binary_comparisons",
srcs = ["binary_comparisons.cpp"],
Expand Down
11 changes: 11 additions & 0 deletions example/ctest_fail.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "skytest/skytest.hpp"

auto main() -> int
{
using namespace skytest::literals;
using ::skytest::expect;
using ::skytest::lt;

static auto n = 0;
"read non-const"_ctest = [] { return expect(lt(0, n)); };
}
6 changes: 6 additions & 0 deletions example/ctest_fail.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
external/skytest/src/detail/test_style.hpp:43:27: error: the value of 'n' is not usable in a constant expression
43 | static constexpr auto value = std::optional<bool>{bool{F{}()}};
| ^~~~~
ctest_fail.cpp:9:15: note: 'int n' is not const
9 | static auto n = 0;
| ^
43 changes: 43 additions & 0 deletions example/ctest_fail.sh.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
set -euo pipefail

source $(find -L . -path \*/rules/prelude.sh -print -quit)
prelude "${BASH_SOURCE[0]}"

cp $(find -L . -path \*/example/ctest_fail.cpp -print -quit) .

cat >>BUILD.bazel <<EOF
cc_binary(
name = "ctest_fail",
srcs = ["ctest_fail.cpp"],
copts = [
"-Werror",
"-Wall",
"-Wextra",
],
deps = [":external_skytest"],
)
EOF

startup_opts=(
--output_user_root=/tmp/bazel
--output_base=/tmp/bazel/output
)
build_opts=(
--symlink_prefix=/
--noshow_progress
--ui_event_filters=-info,-stdout
--color=no
)

start="error: the value of 'n' is not usable in a constant expression"
stop="Target .*:ctest_fail failed to build"

bazel \
${startup_opts[@]} \
build \
${build_opts[@]} \
//:ctest_fail 2>&1 \
| sed -n "/$start/,/$stop/ p" `# only print from start to stop` \
| sed '$d' # remove the stop line

32 changes: 32 additions & 0 deletions rules/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,36 @@
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
load(
"@local_config_info//:defs.bzl",
"BAZEL_BIN",
"BAZEL_EXTERNAL_DIR",
"BAZEL_WORKSPACE_ROOT",
"XDG_CACHE_HOME",
)

exports_files(
["skytest_test.sh"],
visibility = ["//test:__pkg__"],
)

expand_template(
name = "gen_prelude_sh",
out = "prelude.sh",
substitutions = {
"$BAZEL_BIN": BAZEL_BIN,
"$BAZEL_EXTERNAL_DIR": BAZEL_EXTERNAL_DIR,
"$BAZEL_WORKSPACE_ROOT": BAZEL_WORKSPACE_ROOT,
"$XDG_CACHE_HOME": XDG_CACHE_HOME,
},
tags = ["manual"],
template = "prelude.sh.tmpl",
visibility = ["//visibility:private"],
)

sh_library(
name = "prelude_sh",
srcs = ["prelude.sh"],
visibility = [
"//example:__pkg__",
"//test:__pkg__",
],
)
14 changes: 6 additions & 8 deletions rules/binary_log.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ def binary_log(
"""
native.genrule(
name = name,
srcs = [src],
tools = [src],
outs = [log],
cmd = "$(execpath {}) > $@ || true".format(src),
cmd = "$(execpath {}) &> $@ || true".format(src),
testonly = True,
tags = ["manual"],
visibility = ["//visibility:private"],
Expand Down Expand Up @@ -64,17 +64,14 @@ def synchronized_binary_log(

native.genrule(
name = name + "_update_sh",
srcs = [
src,
log,
],
srcs = [log],
tools = [src],
outs = [name + ".update.sh"],
cmd = """
set -euo pipefail
echo "set -euo pipefail" > $@
echo "" >> $@
echo "cd {workspace_dir}" >> $@
echo "$(execpath {src}) > $(rootpath {log}) || true" >> $@
echo "{workspace_dir}/$(execpath {src}) &> {workspace_dir}/$(rootpath {log}) || true" >> $@
""".format(
src = src,
log = log,
Expand All @@ -96,4 +93,5 @@ echo "$(execpath {src}) > $(rootpath {log}) || true" >> $@
native.sh_binary(
name = name + ".update",
srcs = [name + ".update.sh"],
data = [src],
)
7 changes: 5 additions & 2 deletions test/prelude.sh.tmpl → rules/prelude.sh.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ set -euo pipefail
function prelude() {

TEST_PATH="$(readlink -f $1)"
SCRIPT_NAME="${TEST_PATH##*/test/}}"
WORKSPACE="${SCRIPT_NAME%.*}"

PRUNE_TEST="${TEST_PATH##*/test/}}"
PRUNE_EXAMPLE="${PRUNE_TEST##*/example/}}"

WORKSPACE="${PRUNE_EXAMPLE%.*}"

cat >> .bazelrc <<EOF
startup --max_idle_secs=1
Expand Down
13 changes: 8 additions & 5 deletions rules/sh_binary_template.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ load("@bazel_skylib//rules:expand_template.bzl", "expand_template")

def sh_binary_template(
name,
substitutions,
substitutions = {},
template = None,
out = None,
srcs = [],
deps = []):
**kwargs):
"""
Combines expand_template with sh_binary
Expand All @@ -25,8 +25,8 @@ def sh_binary_template(
Key-value mappings.
srcs: string_label_list
`srcs` used for `sh_binary`
deps: string_label_list
`deps` used for `sh_binary`
**kwargs: dict
additional args passed to `sh_binary`
"""
if len(srcs) == 1 and template == None:
template = srcs[0]
Expand All @@ -45,8 +45,11 @@ def sh_binary_template(

binary_src = lambda src: src if src != template else out

data = kwargs.pop("data", [])

native.sh_binary(
name = name,
srcs = [binary_src(src) for src in srcs],
deps = deps,
data = data + ["//rules:prelude_sh"],
**kwargs
)
1 change: 0 additions & 1 deletion rules/skytest_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ echo "done" >> $@
"$CC_BINARY_CXXSTD": std,
"$CC_BINARY_MALLOC": malloc,
},
"deps": ["//test:prelude_sh"],
}
else:
fail("unhandled binary_type: {}".format(binary_type))
Expand Down
13 changes: 13 additions & 0 deletions scripts/README.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,23 @@ When running tests, `skytest` will attempt to invoke test closures at
compile-time. If able to, results will be classified `CONSTEXPR PASS` or
`CONSTEXPR FAIL` instead of `PASS` or `FAIL`.

<details><summary>requiring compile-time evaluation of tests</summary>


The `ctest` literal can be used to require closures to be tested at
compile-time. In order to be usable with `ctest`, test closures must be empty
and non-constexpr functions must not be invoked.

```cpp:example/ctest_fail.cpp
```

results in the follow build error (snippet):

```console:example/ctest_fail.log
```

</details>

## examples

#### binary comparisons
Expand Down
28 changes: 0 additions & 28 deletions test/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,34 +1,6 @@
load("//rules:skytest_test.bzl", "skytest_test")
load("//rules:sh_binary_template.bzl", "sh_binary_template")
load("@rules_cc//cc:defs.bzl", "cc_library")
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
load(
"@local_config_info//:defs.bzl",
"BAZEL_BIN",
"BAZEL_EXTERNAL_DIR",
"BAZEL_WORKSPACE_ROOT",
"XDG_CACHE_HOME",
)

expand_template(
name = "gen_prelude_sh",
testonly = True,
out = "prelude.sh",
substitutions = {
"$BAZEL_BIN": BAZEL_BIN,
"$BAZEL_EXTERNAL_DIR": BAZEL_EXTERNAL_DIR,
"$BAZEL_WORKSPACE_ROOT": BAZEL_WORKSPACE_ROOT,
"$XDG_CACHE_HOME": XDG_CACHE_HOME,
},
tags = ["manual"],
template = "prelude.sh.tmpl",
visibility = ["//visibility:private"],
)

sh_library(
name = "prelude_sh",
srcs = ["prelude.sh"],
)

skytest_test(
name = "pass_test",
Expand Down
4 changes: 2 additions & 2 deletions test/ctest_build_failure.sh.tmpl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail

source test/prelude.sh
source rules/prelude.sh
prelude "${BASH_SOURCE[0]}"

cat >>BUILD.bazel <<EOF
Expand Down Expand Up @@ -40,4 +40,4 @@ auto main() -> int
}
EOF

bazel build -s //:ctest_build_failure
bazel build -s //:ctest_build_failure
2 changes: 1 addition & 1 deletion test/noreturn_expect.sh.tmpl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail

source test/prelude.sh
source rules/prelude.sh
prelude "${BASH_SOURCE[0]}"

cat >>BUILD.bazel <<EOF
Expand Down

0 comments on commit 4bfd605

Please sign in to comment.