From 57a4db23484232f808fdb67fca9f315fd4877c8b Mon Sep 17 00:00:00 2001 From: Oliver Lee Date: Mon, 25 Dec 2023 23:11:03 -0800 Subject: [PATCH] add usage examples (#19) Change-Id: I306b87c0350ae407bbea123a467970a4b4c81d87 --- example/BUILD.bazel | 106 ++++++++++++++++++++++++++++ example/additional_output.cpp | 20 ++++++ example/additional_output.log | 8 +++ example/binary_comparisons.cpp | 20 ++++++ example/described_predicates.cpp | 25 +++++++ example/described_predicates.log | 4 ++ example/described_predicates_20.cpp | 15 ++++ example/described_predicates_20.log | Bin 0 -> 156 bytes example/logical_operations.cpp | 12 ++++ example/minimal_fail.cpp | 10 +++ example/minimal_fail.log | 4 ++ example/minimal_pass.cpp | 9 +++ example/minimal_pass.log | 2 + example/param_parameterized.cpp | 14 ++++ example/param_ref_parameterized.cpp | 23 ++++++ example/type_parameterized.cpp | 22 ++++++ example/user_defined_predicates.cpp | 17 +++++ example/user_defined_predicates.log | 4 ++ example/value_parameterized.cpp | 13 ++++ rules/binary_log.bzl | 97 +++++++++++++++++++++++++ 20 files changed, 425 insertions(+) create mode 100644 example/BUILD.bazel create mode 100644 example/additional_output.cpp create mode 100644 example/additional_output.log create mode 100644 example/binary_comparisons.cpp create mode 100644 example/described_predicates.cpp create mode 100644 example/described_predicates.log create mode 100644 example/described_predicates_20.cpp create mode 100644 example/described_predicates_20.log create mode 100644 example/logical_operations.cpp create mode 100644 example/minimal_fail.cpp create mode 100644 example/minimal_fail.log create mode 100644 example/minimal_pass.cpp create mode 100644 example/minimal_pass.log create mode 100644 example/param_parameterized.cpp create mode 100644 example/param_ref_parameterized.cpp create mode 100644 example/type_parameterized.cpp create mode 100644 example/user_defined_predicates.cpp create mode 100644 example/user_defined_predicates.log create mode 100644 example/value_parameterized.cpp create mode 100644 rules/binary_log.bzl diff --git a/example/BUILD.bazel b/example/BUILD.bazel new file mode 100644 index 0000000..1ef4086 --- /dev/null +++ b/example/BUILD.bazel @@ -0,0 +1,106 @@ +load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_test") +load("//rules:binary_log.bzl", "synchronized_binary_log") + +cc_binary( + name = "minimal_pass", + srcs = ["minimal_pass.cpp"], + deps = ["//:skytest"], +) + +synchronized_binary_log( + name = "minimal_pass_log", + src = ":minimal_pass", +) + +cc_binary( + name = "minimal_fail", + srcs = ["minimal_fail.cpp"], + deps = ["//:skytest"], +) + +synchronized_binary_log( + name = "minimal_fail_log", + src = ":minimal_fail", +) + +cc_test( + name = "binary_comparisons", + srcs = ["binary_comparisons.cpp"], + deps = ["//:skytest"], +) + +cc_test( + name = "logical_operations", + srcs = ["logical_operations.cpp"], + deps = ["//:skytest"], +) + +cc_binary( + name = "additional_output", + srcs = ["additional_output.cpp"], + deps = ["//:skytest"], +) + +synchronized_binary_log( + name = "additional_output_log", + src = ":additional_output", +) + +cc_binary( + name = "user_defined_predicates", + srcs = ["user_defined_predicates.cpp"], + deps = ["//:skytest"], +) + +synchronized_binary_log( + name = "user_defined_predicates_log", + src = ":user_defined_predicates", +) + +cc_binary( + name = "described_predicates_20", + srcs = ["described_predicates_20.cpp"], + copts = ["-std=c++20"], + deps = ["//:skytest"], +) + +synchronized_binary_log( + name = "described_predicates_20_log", + src = ":described_predicates_20", +) + +cc_binary( + name = "described_predicates", + srcs = ["described_predicates.cpp"], + deps = ["//:skytest"], +) + +synchronized_binary_log( + name = "described_predicates_log", + src = ":described_predicates", +) + +cc_test( + name = "type_parameterized", + srcs = ["type_parameterized.cpp"], + deps = ["//:skytest"], +) + +cc_test( + name = "value_parameterized", + srcs = ["value_parameterized.cpp"], + deps = ["//:skytest"], +) + +cc_test( + name = "param_ref_parameterized", + srcs = ["param_ref_parameterized.cpp"], + deps = ["//:skytest"], +) + +cc_test( + name = "param_parameterized", + srcs = ["param_parameterized.cpp"], + copts = ["-std=c++20"], + deps = ["//:skytest"], +) diff --git a/example/additional_output.cpp b/example/additional_output.cpp new file mode 100644 index 0000000..e9806fa --- /dev/null +++ b/example/additional_output.cpp @@ -0,0 +1,20 @@ +#include "skytest/skytest.hpp" + +#include + +auto main() -> int +{ + using namespace skytest::literals; + using ::skytest::eq; + using ::skytest::expect; + + "string-view-ish"_test = [] { return expect(eq(1, 2), "a message"); }; + + "ostream invocable closure"_test = [] { + const auto x = std::pair{1, 2}; + const auto y = std::pair{2, 1}; + return expect(eq(x, y), [=](auto& os) { + os << x.first << ", " << y.first << "\n"; + }); + }; +} diff --git a/example/additional_output.log b/example/additional_output.log new file mode 100644 index 0000000..46458f1 --- /dev/null +++ b/example/additional_output.log @@ -0,0 +1,8 @@ +test `string-view-ish`...[CONSTEXPR FAIL] example/additional_output.cpp:11 +(1 == 2) +a message +test `ostream invocable closure`...[CONSTEXPR FAIL] example/additional_output.cpp:16 +(std::pair{...} == std::pair{...}) +1, 2 + +0 tests passed | 2 tests failed diff --git a/example/binary_comparisons.cpp b/example/binary_comparisons.cpp new file mode 100644 index 0000000..108e215 --- /dev/null +++ b/example/binary_comparisons.cpp @@ -0,0 +1,20 @@ +#include "skytest/skytest.hpp" + +auto main() -> int +{ + using namespace skytest::literals; + using ::skytest::eq; + using ::skytest::expect; + using ::skytest::ge; + using ::skytest::gt; + using ::skytest::le; + using ::skytest::lt; + using ::skytest::ne; + + "eq"_test = [] { return expect(eq(1, 1)); }; + "ne"_test = [] { return expect(ne(1, 0)); }; + "lt"_test = [] { return expect(lt(0, 1)); }; + "gt"_test = [] { return expect(gt(1, 0)); }; + "le"_test = [] { return expect(le(1, 1)); }; + "ge"_test = [] { return expect(ge(1, 1)); }; +} diff --git a/example/described_predicates.cpp b/example/described_predicates.cpp new file mode 100644 index 0000000..83fe202 --- /dev/null +++ b/example/described_predicates.cpp @@ -0,0 +1,25 @@ + +#include "skytest/skytest.hpp" + +#include +#include + +using namespace skytest::literals; +using ::skytest::expect; +using ::skytest::pred; + +struct empty_desc +{ + using notation_type = skytest::notation::function; + static constexpr auto symbol = std::string_view{"empty"}; +}; + +static constexpr auto empty = pred(empty_desc{}, [](const auto& rng) { + return std::empty(rng); +}); + +auto main() -> int +{ + + "empty array"_test = [] { return expect(empty(std::array{1, 2, 3})); }; +} diff --git a/example/described_predicates.log b/example/described_predicates.log new file mode 100644 index 0000000..8fb578a --- /dev/null +++ b/example/described_predicates.log @@ -0,0 +1,4 @@ +test `empty array`...[CONSTEXPR FAIL] example/described_predicates.cpp:24 +empty([1, 2, 3]) + +0 tests passed | 1 test failed diff --git a/example/described_predicates_20.cpp b/example/described_predicates_20.cpp new file mode 100644 index 0000000..0955bb9 --- /dev/null +++ b/example/described_predicates_20.cpp @@ -0,0 +1,15 @@ +#include "skytest/skytest.hpp" + +#include + +auto main() -> int +{ + using namespace skytest::literals; + using ::skytest::expect; + using ::skytest::function; + using ::skytest::pred; + + static constexpr auto empty = pred(function<"∅">, std::ranges::empty); + + "empty array"_test = [] { return expect(empty(std::array{1, 2, 3})); }; +} diff --git a/example/described_predicates_20.log b/example/described_predicates_20.log new file mode 100644 index 0000000000000000000000000000000000000000..8b4b7d2a98174322cb5187722f0939e072a456ac GIT binary patch literal 156 zcmW;EF$)4A7=Yns|ANam796HtQ`->*K~z*jAjh5Q7YHYaI&{z)^gH_{mFvsHn=xhR z(T6;Oj!}<2V~na=c(pq0&zJS}c!Eu{-L+J45BShN3^=!#OmsK2U5IF%(HT=GIWr+F r#e$RpRnmXnugO%23S int +{ + using namespace skytest::literals; + using ::skytest::expect; + using ::skytest::lt; + + "and"_test = [] { return expect(lt(1, 2) and lt(2, 3)); }; + "or"_test = [] { return expect(lt(3, 2) or lt(2, 3)); }; + "not"_test = [] { return expect(not lt(1, 0)); }; +} diff --git a/example/minimal_fail.cpp b/example/minimal_fail.cpp new file mode 100644 index 0000000..bb72483 --- /dev/null +++ b/example/minimal_fail.cpp @@ -0,0 +1,10 @@ +#include "skytest/skytest.hpp" + +auto main(int argc, char*[]) -> int +{ + using namespace skytest::literals; + using ::skytest::eq; + using ::skytest::expect; + + "falsy"_test = [&] { return expect(eq(0, argc)); }; +} diff --git a/example/minimal_fail.log b/example/minimal_fail.log new file mode 100644 index 0000000..950d6b8 --- /dev/null +++ b/example/minimal_fail.log @@ -0,0 +1,4 @@ +test `falsy`...[FAIL] example/minimal_fail.cpp:9 +(0 == 1) + +0 tests passed | 1 test failed diff --git a/example/minimal_pass.cpp b/example/minimal_pass.cpp new file mode 100644 index 0000000..8510a21 --- /dev/null +++ b/example/minimal_pass.cpp @@ -0,0 +1,9 @@ +#include "skytest/skytest.hpp" + +auto main() -> int +{ + using namespace skytest::literals; + using ::skytest::expect; + + "truthy"_test = [] { return expect(true); }; +} diff --git a/example/minimal_pass.log b/example/minimal_pass.log new file mode 100644 index 0000000..d6375f6 --- /dev/null +++ b/example/minimal_pass.log @@ -0,0 +1,2 @@ +test `truthy`...[CONSTEXPR PASS] +all tests passed (1 test) diff --git a/example/param_parameterized.cpp b/example/param_parameterized.cpp new file mode 100644 index 0000000..b0daeaa --- /dev/null +++ b/example/param_parameterized.cpp @@ -0,0 +1,14 @@ +#include "skytest/skytest.hpp" + +#include + +auto main() -> int +{ + using namespace ::skytest::literals; + using ::skytest::expect; + using ::skytest::lt; + using ::skytest::param; + + "with paramf"_test * param = // + [](auto param) { return expect(lt(0, param)); }; +} diff --git a/example/param_ref_parameterized.cpp b/example/param_ref_parameterized.cpp new file mode 100644 index 0000000..dfcec22 --- /dev/null +++ b/example/param_ref_parameterized.cpp @@ -0,0 +1,23 @@ +#include "skytest/skytest.hpp" + +#include +#include + +auto main() -> int +{ + using namespace ::skytest::literals; + using ::skytest::eq; + using ::skytest::expect; + using ::skytest::lt; + using ::skytest::param_ref; + + static constexpr auto type_params = std::tuple{1.0F, 1.0}; + + "types with param_ref"_test * param_ref = // + [](auto param) { return expect(eq(1, param)); }; + + static constexpr auto value_params = std::array{1, 2, 3}; + + "values with param_ref"_test * param_ref = // + [](auto param) { return expect(lt(0, param)); }; +} diff --git a/example/type_parameterized.cpp b/example/type_parameterized.cpp new file mode 100644 index 0000000..46066c5 --- /dev/null +++ b/example/type_parameterized.cpp @@ -0,0 +1,22 @@ +#include "skytest/skytest.hpp" + +#include +#include +#include + +auto main() -> int +{ + using namespace ::skytest::literals; + using ::skytest::eq; + using ::skytest::expect; + using ::skytest::types; + + "typed"_test * std::tuple>{} = // + [](auto param) { return expect(eq(0, std::abs(param))); }; + + "with types param"_test * types = // + [](auto type_id) { + using T = typename decltype(type_id)::type; + return expect(eq(T{}, T{} + T{})); + }; +} diff --git a/example/user_defined_predicates.cpp b/example/user_defined_predicates.cpp new file mode 100644 index 0000000..86849f5 --- /dev/null +++ b/example/user_defined_predicates.cpp @@ -0,0 +1,17 @@ +#include "skytest/skytest.hpp" + +#include +#include + +auto main() -> int +{ + using namespace skytest::literals; + using ::skytest::expect; + using ::skytest::pred; + + static constexpr auto empty = pred([](const auto& rng) { + return std::empty(rng); + }); + + "empty array"_test = [] { return expect(empty(std::array{1, 2, 3})); }; +} diff --git a/example/user_defined_predicates.log b/example/user_defined_predicates.log new file mode 100644 index 0000000..f063a66 --- /dev/null +++ b/example/user_defined_predicates.log @@ -0,0 +1,4 @@ +test `empty array`...[CONSTEXPR FAIL] example/user_defined_predicates.cpp:16 +(lambda at example/user_defined_predicates.cpp:12:38){}([1, 2, 3]) + +0 tests passed | 1 test failed diff --git a/example/value_parameterized.cpp b/example/value_parameterized.cpp new file mode 100644 index 0000000..f8a5a50 --- /dev/null +++ b/example/value_parameterized.cpp @@ -0,0 +1,13 @@ +#include "skytest/skytest.hpp" + +#include + +auto main() -> int +{ + using namespace ::skytest::literals; + using ::skytest::expect; + using ::skytest::lt; + + "values"_test * std::vector{1, 2, 3} = // + [](auto param) { return expect(lt(0, param)); }; +} diff --git a/rules/binary_log.bzl b/rules/binary_log.bzl new file mode 100644 index 0000000..ac92657 --- /dev/null +++ b/rules/binary_log.bzl @@ -0,0 +1,97 @@ +""" +Rule for generating and testing log files for a binary's output +""" + +load("@bazel_skylib//rules:diff_test.bzl", "diff_test") + +def binary_log( + name, + src, + log): + """ + Create a log file from running a binary. + + Args: + name: string + Name for `binary_log` rule + src: string_label + Source binary file to run + log: string + Filename for created log. + """ + native.genrule( + name = name, + srcs = [src], + outs = [log], + cmd = "$(execpath {}) > $@ || true".format(src), + testonly = True, + tags = ["manual"], + visibility = ["//visibility:private"], + target_compatible_with = select({ + # log files will differ for Clang and GCC due to how types are + # printed. + "@rules_cc//cc/compiler:gcc": ["@platforms//:incompatible"], + "//conditions:default": [], + }), + ) + +def synchronized_binary_log( + name, + src, + log = None): + """ + Test that a log file generated from running a binary is up to date. + + Args: + name: string + Name for `synchronized_binary_log` rule + src: string_label + Source binary file to run + log: string_label + Checked in log file. + """ + src_name = native.package_relative_label(src).name + generated_log = src_name + ".log.generated" + binary_log( + name = name + "_gen", + src = src, + log = generated_log, + ) + + label = native.package_relative_label(name) + log = log or src_name + ".log" + + native.genrule( + name = name + "_update_sh", + srcs = [ + src, + log, + ], + outs = [name + ".update.sh"], + cmd = """ +set -euo pipefail +echo "set -euo pipefail" > $@ +echo "" >> $@ +echo "cd \\$${{BUILD_WORKSPACE_DIRECTORY}}" >> $@ +echo "$(execpath {src}) > $(rootpath {log}) || true" >> $@ +""".format( + src = src, + log = log, + ), + tags = ["manual"], + visibility = ["//visibility:private"], + ) + + native.sh_binary( + name = name + ".update", + srcs = [name + ".update.sh"], + ) + + diff_test( + name = name, + file1 = log, + file2 = generated_log, + failure_message = "To update, run:\n\nbazel run {}.update".format( + str(label).replace("@//", "//"), + ), + )