You've already forked bitshift-validate
Hello BitShift Validate
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
indent_size = 4
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
@@ -0,0 +1 @@
|
||||
* text=auto
|
||||
@@ -0,0 +1,70 @@
|
||||
name: on-push
|
||||
|
||||
on:
|
||||
push:
|
||||
tags-ignore:
|
||||
- '**'
|
||||
branches:
|
||||
- '**'
|
||||
|
||||
jobs:
|
||||
gcc:
|
||||
runs-on: linux
|
||||
container: code.helloryan.se/infra/buildenv/f44-x86_64-unified:latest
|
||||
steps:
|
||||
- name: Prepare environment
|
||||
run: |
|
||||
mkdir /src
|
||||
- name: Configure repository access
|
||||
run: |
|
||||
git config --global http.$GITHUB_SERVER_URL/.extraheader "Authorization: token ${{ secrets.PACKAGE_PULL_TOKEN }}"
|
||||
- name: Fetch repository
|
||||
run: |
|
||||
cd /src
|
||||
git clone $GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git .
|
||||
git checkout "$GITHUB_SHA"
|
||||
- name: Create build configuration
|
||||
run: |
|
||||
bpkg create -d /build cc config.cxx=g++ config.cc.coptions="-Wall -Werror"
|
||||
- name: Initialize
|
||||
run: |
|
||||
cd /src
|
||||
bdep init -A /build
|
||||
- name: Build
|
||||
run: |
|
||||
cd /src
|
||||
b
|
||||
- name: Test
|
||||
run: |
|
||||
cd /src
|
||||
b -j 1 -s test
|
||||
clang:
|
||||
runs-on: linux
|
||||
container: code.helloryan.se/infra/buildenv/f44-x86_64-unified:latest
|
||||
steps:
|
||||
- name: Prepare environment
|
||||
run: |
|
||||
mkdir /src
|
||||
- name: Configure repository access
|
||||
run: |
|
||||
git config --global http.$GITHUB_SERVER_URL/.extraheader "Authorization: token ${{ secrets.PACKAGE_PULL_TOKEN }}"
|
||||
- name: Fetch repository
|
||||
run: |
|
||||
cd /src
|
||||
git clone $GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git .
|
||||
git checkout "$GITHUB_SHA"
|
||||
- name: Create build configuration
|
||||
run: |
|
||||
bpkg create -d /build cc config.cxx=clang++ config.cc.coptions="-Wall -Werror"
|
||||
- name: Initialize
|
||||
run: |
|
||||
cd /src
|
||||
bdep init -A /build
|
||||
- name: Build
|
||||
run: |
|
||||
cd /src
|
||||
b
|
||||
- name: Test
|
||||
run: |
|
||||
cd /src
|
||||
b -j 1 -s test
|
||||
@@ -0,0 +1,38 @@
|
||||
name: on-push
|
||||
|
||||
on: workflow_dispatch
|
||||
|
||||
jobs:
|
||||
publish-docs:
|
||||
runs-on: linux
|
||||
container: code.helloryan.se/infra/buildenv/f44-x86_64-unified:latest
|
||||
steps:
|
||||
- name: Prepare environment
|
||||
run: |
|
||||
mkdir /src
|
||||
- name: Configure repository access
|
||||
run: |
|
||||
git config --global http.$GITHUB_SERVER_URL/.extraheader "Authorization: token ${{ secrets.PACKAGE_PULL_TOKEN }}"
|
||||
- name: Configure MinIO CLI
|
||||
run: |
|
||||
mc alias set garage https://buckets.helloryan.se/ ${{ secrets.BITSHIFT_S3_KEY_ID }} ${{ secrets.BITSHIFT_S3_SECRET_KEY }}
|
||||
- name: Fetch repository
|
||||
run: |
|
||||
cd /src
|
||||
git clone $GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git .
|
||||
git checkout "$GITHUB_SHA"
|
||||
- name: Create build configuration
|
||||
run: |
|
||||
bpkg create -d /build cc config.cxx=g++ config.cc.coptions="-Wall -Werror"
|
||||
- name: Initialize
|
||||
run: |
|
||||
cd /src
|
||||
bdep init -A /build
|
||||
- name: Build Documentation
|
||||
run: |
|
||||
cd /src
|
||||
b alias{docs}
|
||||
- name: Publish Documentation
|
||||
run: |
|
||||
cd /build/bitshift-validate/docs/html
|
||||
mc mirror --remove --overwrite . garage/validate.bitshift.helloryan.se/
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
.bdep/
|
||||
|
||||
# Local default options files.
|
||||
#
|
||||
.build2/local/
|
||||
|
||||
# Compiler/linker output.
|
||||
#
|
||||
# Note that *.exe.dlls directories can be symlinks thus
|
||||
# no trailing /.
|
||||
#
|
||||
*.d
|
||||
*.t
|
||||
*.i
|
||||
*.i.*
|
||||
*.ii
|
||||
*.ii.*
|
||||
*.o
|
||||
*.obj
|
||||
*.gcm
|
||||
*.pcm
|
||||
*.ifc
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
*.a
|
||||
*.lib
|
||||
*.exp
|
||||
*.pdb
|
||||
*.ilk
|
||||
*.exe
|
||||
*.exe.dlls
|
||||
*.exe.manifest
|
||||
*.pc
|
||||
|
||||
# Compilation database.
|
||||
#
|
||||
compile_commands.json
|
||||
+2933
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
Copyright © 2026 Per Ryan Edin and the BitShift Contributors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,101 @@
|
||||
Validate
|
||||
========
|
||||
|
||||
BitShift Validate is a minimalist unit-testing library for C++. Its primary
|
||||
purpose is to test the various other BitShift projects without making them
|
||||
dependent on larger unit-testing libraries.
|
||||
|
||||
Why BitShift Validate?
|
||||
----------------------
|
||||
|
||||
A small and dependency-free unit-testing library with first-class build2
|
||||
support was required for the other BitShift Projects.
|
||||
|
||||
And a shitload of other reasons, for example, not embracing CMake(Shit) or
|
||||
supporting Google world-dominance by using GTest.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
- A modern C++ compiler with C++23 suppport (GCC 14+ or Clang 18+),
|
||||
|
||||
- [build2][build2]: The build2 build and package management system.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
To start using BitShift Validate to test your project, add the following
|
||||
`depends` value to your `manifest`, adjusting the version constraint as
|
||||
appropriate:
|
||||
|
||||
```
|
||||
depends: bitshift-validate ^<VERSION>
|
||||
```
|
||||
|
||||
Then import the library in your `buildfile`:
|
||||
|
||||
```
|
||||
test_libs =
|
||||
import test_libs =+ bitshift-validate%lib{validate}
|
||||
|
||||
./: exe{my-test}: {hxx ixx txx cxx}{**} $test_libs
|
||||
```
|
||||
|
||||
Importable Targets
|
||||
------------------
|
||||
|
||||
This package provides the following importable targets:
|
||||
|
||||
```
|
||||
lib{validate}
|
||||
```
|
||||
|
||||
### `lib{validate}`
|
||||
|
||||
Implementation of the test library.
|
||||
|
||||
Usage Example
|
||||
-------------
|
||||
|
||||
```c++
|
||||
#include <bitshift/validate/validate.hxx>
|
||||
|
||||
BV_TEST(example.test, "an example test")
|
||||
{
|
||||
int x = 0;
|
||||
int y = 1;
|
||||
|
||||
BV_ASSERT_NOT_EQUAL(x, y);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
return bitshift::validate::main(argc, argv);
|
||||
}
|
||||
```
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
The latest API reference documentation can be found at:
|
||||
https://bitshift.helloryan.se/validate/
|
||||
|
||||
Bugs
|
||||
----
|
||||
|
||||
There are probably many goblins lurking in the code. If you find one, please
|
||||
report it promptly to [ryan@helloryan.se][ryan@helloryan.se]. Please include as
|
||||
much information as possible and preferably a link to a reproducible.
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
If you want to actively contribute to the project, send an e-mail to
|
||||
[ryan@helloryan.se][ryan@helloryan.se], to discuss repository access.
|
||||
|
||||
Contributions are welcome in many forms, from code contributions to simple
|
||||
issue reporting. Don't hesitate to get in touch!
|
||||
|
||||
[build2]: https://build2.org/
|
||||
[ryan@helloryan.se]: mailto:ryan@helloryan.se
|
||||
@@ -0,0 +1,9 @@
|
||||
# Generated version header.
|
||||
#
|
||||
version.hxx
|
||||
|
||||
# Unit test executables and Testscript output directories
|
||||
# (can be symlinks).
|
||||
#
|
||||
*.test
|
||||
test-*.test
|
||||
@@ -0,0 +1,115 @@
|
||||
#include <bitshift/validate/ansi.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
ansi::
|
||||
ansi()
|
||||
{}
|
||||
|
||||
ansi::
|
||||
ansi(color color, style style)
|
||||
: _color{color}, _style{style}
|
||||
{}
|
||||
|
||||
ansi::color
|
||||
ansi::
|
||||
get_color() const
|
||||
{
|
||||
return _color;
|
||||
}
|
||||
|
||||
ansi::style
|
||||
ansi::
|
||||
get_style() const
|
||||
{
|
||||
return _style;
|
||||
}
|
||||
|
||||
ansi::style
|
||||
operator|(ansi::style lhs, ansi::style rhs)
|
||||
{
|
||||
return static_cast<ansi::style>(
|
||||
static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs)
|
||||
);
|
||||
}
|
||||
|
||||
ostream&
|
||||
operator<<(ostream& o, ansi const& ansi)
|
||||
{
|
||||
o << "\033[0m";
|
||||
|
||||
switch (ansi.get_color()) {
|
||||
case ansi::kBlack:
|
||||
o << "\033[30";
|
||||
break;
|
||||
|
||||
case ansi::kRed:
|
||||
o << "\033[31";
|
||||
break;
|
||||
|
||||
case ansi::kGreen:
|
||||
o << "\033[32";
|
||||
break;
|
||||
|
||||
case ansi::kYellow:
|
||||
o << "\033[33";
|
||||
break;
|
||||
|
||||
case ansi::kBlue:
|
||||
o << "\033[34";
|
||||
break;
|
||||
|
||||
case ansi::kPurple:
|
||||
o << "\033[35";
|
||||
break;
|
||||
|
||||
case ansi::kCyan:
|
||||
o << "\033[36";
|
||||
break;
|
||||
|
||||
case ansi::kWhite:
|
||||
o << "\033[37";
|
||||
break;
|
||||
}
|
||||
|
||||
if ((ansi.get_style() & ansi::kBold) != 0) {
|
||||
o << ";1";
|
||||
}
|
||||
|
||||
if ((ansi.get_style() & ansi::kItalic) != 0) {
|
||||
o << ";3";
|
||||
}
|
||||
|
||||
if ((ansi.get_style() & ansi::kUnderline) != 0) {
|
||||
o << ";4";
|
||||
}
|
||||
|
||||
if ((ansi.get_style() & ansi::kBlinking) != 0) {
|
||||
o << ";5";
|
||||
}
|
||||
|
||||
o << 'm';
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
ostream&
|
||||
operator<<(ostream& o, ansi::reset_t const&)
|
||||
{
|
||||
return o << "\033[0m";
|
||||
}
|
||||
|
||||
ostream&
|
||||
operator<<(ostream& o, ansi::color const& color)
|
||||
{
|
||||
return o << ansi{color};
|
||||
}
|
||||
|
||||
ostream&
|
||||
operator<<(ostream& o, ansi::style const& style)
|
||||
{
|
||||
return o << ansi{ansi::color::kBlack, style};
|
||||
}
|
||||
|
||||
} // namespace bitshift::validate
|
||||
@@ -0,0 +1,94 @@
|
||||
#ifndef bitshift__validate__ansi_hxx_
|
||||
#define bitshift__validate__ansi_hxx_
|
||||
|
||||
#include <bitshift/validate/types.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
/// @brief Terminal ANSI-styles class
|
||||
///
|
||||
class ansi
|
||||
{
|
||||
public:
|
||||
/// @brief Terminal color enumeration.
|
||||
///
|
||||
enum color
|
||||
: uint8_t
|
||||
{
|
||||
kBlack,
|
||||
kRed,
|
||||
kGreen,
|
||||
kYellow,
|
||||
kBlue,
|
||||
kPurple,
|
||||
kCyan,
|
||||
kWhite
|
||||
|
||||
};
|
||||
|
||||
/// @brief Terminal style enumeration.
|
||||
///
|
||||
enum style
|
||||
: uint8_t
|
||||
{
|
||||
kNormal = 0,
|
||||
kBold = 1 << 1,
|
||||
kItalic = 1 << 2,
|
||||
kUnderline = 1 << 3,
|
||||
kBlinking = 1 << 4
|
||||
|
||||
};
|
||||
|
||||
/// @brief Tag-dispatch type for reset.
|
||||
///
|
||||
struct reset_t { };
|
||||
|
||||
/// @brief Tag for reset.
|
||||
///
|
||||
static constexpr reset_t const reset{};
|
||||
|
||||
/// @brief Constructor.
|
||||
///
|
||||
ansi();
|
||||
|
||||
/// @brief Constructor.
|
||||
///
|
||||
ansi(color, style = kNormal);
|
||||
|
||||
/// @brief Get color.
|
||||
///
|
||||
color
|
||||
get_color() const;
|
||||
|
||||
/// @brief Get style.
|
||||
///
|
||||
style
|
||||
get_style() const;
|
||||
|
||||
private:
|
||||
color _color{kBlack};
|
||||
style _style{kNormal};
|
||||
|
||||
};
|
||||
|
||||
/// @brief Style-combinator operator.
|
||||
///
|
||||
ansi::style
|
||||
operator|(ansi::style, ansi::style);
|
||||
|
||||
ostream&
|
||||
operator<<(ostream&, ansi const&);
|
||||
|
||||
ostream&
|
||||
operator<<(ostream&, ansi::reset_t const&);
|
||||
|
||||
ostream&
|
||||
operator<<(ostream&, ansi::color const&);
|
||||
|
||||
ostream&
|
||||
operator<<(ostream&, ansi::style const&);
|
||||
|
||||
} // namespace bitshift::validate
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
#ifndef bitshift__validate__assert_hxx_
|
||||
#define bitshift__validate__assert_hxx_
|
||||
|
||||
#include <bitshift/validate/types.hxx>
|
||||
#include <bitshift/validate/failure.hxx>
|
||||
#include <bitshift/validate/traits.hxx>
|
||||
|
||||
namespace bitshift::validate::assertion
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
assert_true(T const& expr,
|
||||
string const& expr_str,
|
||||
source_location const& origin = source_location::current());
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
assert_false(T const& expr,
|
||||
string const& expr_str,
|
||||
source_location const& origin = source_location::current());
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
assert_nullptr(T const& expr,
|
||||
string const& expr_str,
|
||||
source_location const& origin = source_location::current());
|
||||
|
||||
template<typename T1, typename T2 = T1>
|
||||
void
|
||||
assert_equal(T1 const& lhs,
|
||||
T2 const& rhs,
|
||||
string const& lhs_str,
|
||||
string const& rhs_str,
|
||||
source_location const& origin = source_location::current());
|
||||
|
||||
template<typename T1, typename T2 = T1>
|
||||
void
|
||||
assert_not_equal(T1 const& lhs,
|
||||
T2 const& rhs,
|
||||
string const& lhs_str,
|
||||
string const& rhs_str,
|
||||
source_location const& origin = source_location::current());
|
||||
|
||||
} // namespace bitshift::validate::assertion
|
||||
|
||||
#include <bitshift/validate/assert.txx>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,161 @@
|
||||
namespace bitshift::validate::assertion
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
assert_true(T const& expr,
|
||||
string const& expr_str,
|
||||
source_location const& origin)
|
||||
{
|
||||
if (expr == true) {
|
||||
return;
|
||||
}
|
||||
|
||||
string value_str;
|
||||
|
||||
if constexpr (traits::has_output_operator<T>) {
|
||||
stringstream str;
|
||||
str << expr;
|
||||
value_str = str.str();
|
||||
}
|
||||
|
||||
throw unary_assertion_failure{
|
||||
"expected expression to be true; was false",
|
||||
origin.file_name(),
|
||||
origin.line(),
|
||||
std::move(expr_str),
|
||||
std::move(value_str)
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
assert_false(T const& expr,
|
||||
string const& expr_str,
|
||||
source_location const& origin)
|
||||
{
|
||||
if (expr == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
string value_str;
|
||||
|
||||
if constexpr (traits::has_output_operator<T>) {
|
||||
stringstream str;
|
||||
str << expr;
|
||||
value_str = str.str();
|
||||
}
|
||||
|
||||
throw unary_assertion_failure{
|
||||
"expected expression to be false; was true",
|
||||
origin.file_name(),
|
||||
origin.line(),
|
||||
std::move(expr_str),
|
||||
std::move(value_str)
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
assert_nullptr(T const& expr,
|
||||
string const& expr_str,
|
||||
source_location const& origin)
|
||||
{
|
||||
if (expr == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
string value_str;
|
||||
|
||||
if constexpr (traits::has_output_operator<T>) {
|
||||
stringstream str;
|
||||
str << expr;
|
||||
value_str = str.str();
|
||||
}
|
||||
|
||||
throw unary_assertion_failure{
|
||||
"expected expression to be null; was not null",
|
||||
origin.file_name(),
|
||||
origin.line(),
|
||||
std::move(expr_str),
|
||||
std::move(value_str)
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
void
|
||||
assert_equal(T1 const& lhs,
|
||||
T2 const& rhs,
|
||||
string const& lhs_str,
|
||||
string const& rhs_str,
|
||||
source_location const& origin)
|
||||
{
|
||||
if (lhs == rhs) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string lhs_val;
|
||||
std::string rhs_val;
|
||||
|
||||
if constexpr (traits::has_output_operator<T1>) {
|
||||
std::stringstream str;
|
||||
str << lhs;
|
||||
lhs_val = str.str();
|
||||
}
|
||||
|
||||
if constexpr (traits::has_output_operator<T2>) {
|
||||
std::stringstream str;
|
||||
str << rhs;
|
||||
rhs_val = str.str();
|
||||
}
|
||||
|
||||
throw binary_assertion_failure{
|
||||
"expected lhs to equal rhs",
|
||||
origin.file_name(),
|
||||
origin.line(),
|
||||
std::move(lhs_str),
|
||||
std::move(lhs_val),
|
||||
std::move(rhs_str),
|
||||
std::move(rhs_val)
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
void
|
||||
assert_not_equal(T1 const& lhs,
|
||||
T2 const& rhs,
|
||||
string const& lhs_str,
|
||||
string const& rhs_str,
|
||||
source_location const& origin)
|
||||
{
|
||||
if (lhs != rhs) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string lhs_val;
|
||||
std::string rhs_val;
|
||||
|
||||
if constexpr (traits::has_output_operator<T1>) {
|
||||
std::stringstream str;
|
||||
str << lhs;
|
||||
lhs_val = str.str();
|
||||
}
|
||||
|
||||
if constexpr (traits::has_output_operator<T2>) {
|
||||
std::stringstream str;
|
||||
str << rhs;
|
||||
rhs_val = str.str();
|
||||
}
|
||||
|
||||
throw binary_assertion_failure{
|
||||
"expected lhs to not equal rhs",
|
||||
origin.file_name(),
|
||||
origin.line(),
|
||||
std::move(lhs_str),
|
||||
std::move(lhs_val),
|
||||
std::move(rhs_str),
|
||||
std::move(rhs_val)
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace bitshift::validate::assertion
|
||||
@@ -0,0 +1,58 @@
|
||||
intf_libs = # Interface dependencies.
|
||||
impl_libs = # Implementation dependencies.
|
||||
|
||||
./: lib{validate}: libul{validate}
|
||||
|
||||
libul{validate}: {hxx ixx txx cxx}{** -**.test... -version} \
|
||||
{hxx }{ version}
|
||||
|
||||
libul{validate}: $impl_libs $intf_libs
|
||||
|
||||
# Unit tests.
|
||||
#
|
||||
exe{*.test}:
|
||||
{
|
||||
test = true
|
||||
install = false
|
||||
}
|
||||
|
||||
for t: cxx{**.test...}
|
||||
{
|
||||
d = $directory($t)
|
||||
n = $name($t)...
|
||||
|
||||
./: $d/exe{$n}: $t $d/{hxx ixx txx}{+$n} $d/testscript{+$n}
|
||||
$d/exe{$n}: libul{validate}: bin.whole = false
|
||||
}
|
||||
|
||||
hxx{version}: in{version} $src_root/manifest
|
||||
|
||||
# Build options.
|
||||
#
|
||||
cxx.poptions =+ "-I$out_root" "-I$src_root"
|
||||
|
||||
# Export options.
|
||||
#
|
||||
lib{validate}:
|
||||
{
|
||||
cxx.export.poptions = "-I$out_root" "-I$src_root"
|
||||
cxx.export.libs = $intf_libs
|
||||
}
|
||||
|
||||
# For pre-releases use the complete version to make sure they cannot
|
||||
# be used in place of another pre-release or the final version. See
|
||||
# the version module for details on the version.* variable values.
|
||||
#
|
||||
if $version.pre_release
|
||||
lib{validate}: bin.lib.version = "-$version.project_id"
|
||||
else
|
||||
lib{validate}: bin.lib.version = "-$version.major.$version.minor"
|
||||
|
||||
# Install into the bitshift/validate/ subdirectory of, say, /usr/include/
|
||||
# recreating subdirectories.
|
||||
#
|
||||
{hxx ixx txx}{*}:
|
||||
{
|
||||
install = include/bitshift/validate/
|
||||
install.subdirs = true
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
#include <bitshift/validate/execute.hxx>
|
||||
|
||||
#include <bitshift/validate/failure.hxx>
|
||||
#include <bitshift/validate/filter.hxx>
|
||||
#include <bitshift/validate/setup.hxx>
|
||||
#include <bitshift/validate/teardown.hxx>
|
||||
#include <bitshift/validate/test-case.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
/// @brief Execute setup functions.
|
||||
///
|
||||
static
|
||||
void
|
||||
execute_setup(reporter& r)
|
||||
{
|
||||
auto current = setup::first();
|
||||
|
||||
if (!current) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
r.log_setup(current->file(), current->line());
|
||||
|
||||
current->run();
|
||||
current = current->next();
|
||||
} while (current && current != setup::first());
|
||||
}
|
||||
|
||||
/// @brief Execute teardown functions.
|
||||
///
|
||||
static
|
||||
void
|
||||
execute_teardown(reporter& r)
|
||||
{
|
||||
auto current = teardown::first();
|
||||
|
||||
if (!current) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
r.log_teardown(current->file(), current->line());
|
||||
|
||||
current->run();
|
||||
current = current->next();
|
||||
} while (current && current != teardown::first());
|
||||
}
|
||||
|
||||
enum execute_result
|
||||
{
|
||||
kExecuteIgnored,
|
||||
kExecutePassed,
|
||||
kExecuteFailed
|
||||
|
||||
};
|
||||
|
||||
/// @brief Execute a single test case.
|
||||
///
|
||||
/// @param r The reporter.
|
||||
/// @param tc The test case to execute.
|
||||
///
|
||||
static
|
||||
execute_result
|
||||
execute_single(reporter& r, test_case& tc)
|
||||
{
|
||||
execute_setup(r);
|
||||
|
||||
r.log_test_case(tc.name(), tc.description(), tc.file(), tc.line());
|
||||
|
||||
try {
|
||||
tc.run();
|
||||
}
|
||||
catch (ignore const&) {
|
||||
execute_teardown(r);
|
||||
return kExecuteIgnored;
|
||||
}
|
||||
catch (assertion_failure const& failure) {
|
||||
failure.report(r);
|
||||
execute_teardown(r);
|
||||
return kExecuteFailed;
|
||||
}
|
||||
|
||||
execute_teardown(r);
|
||||
|
||||
return kExecutePassed;
|
||||
}
|
||||
|
||||
bool
|
||||
execute_all(reporter& r, strings const& filters)
|
||||
{
|
||||
auto current = test_case::first();
|
||||
|
||||
if (!current) {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t total{};
|
||||
uint16_t ignored{};
|
||||
uint16_t pass{};
|
||||
uint16_t fail{};
|
||||
|
||||
do {
|
||||
bool selected{filters.empty()};
|
||||
|
||||
for (auto const& j : filters) {
|
||||
if (match_filter(j, current->name())) {
|
||||
selected = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (selected) {
|
||||
++total;
|
||||
|
||||
auto result = execute_single(r, *current);
|
||||
|
||||
switch (result) {
|
||||
case kExecuteIgnored:
|
||||
++ignored;
|
||||
break;
|
||||
|
||||
case kExecutePassed:
|
||||
++pass;
|
||||
break;
|
||||
|
||||
case kExecuteFailed:
|
||||
++fail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
current = current->next();
|
||||
} while (current && current != test_case::first());
|
||||
|
||||
r.log_summary(total, ignored, pass, fail);
|
||||
|
||||
return fail == 0;
|
||||
}
|
||||
|
||||
} // namespace bitshift::validate
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef bitshift__validate__execute_hxx_
|
||||
#define bitshift__validate__execute_hxx_
|
||||
|
||||
#include <bitshift/validate/types.hxx>
|
||||
#include <bitshift/validate/reporting.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
/// @brief Execute all test cases.
|
||||
///
|
||||
/// @param r The reporter.
|
||||
/// @param filters Test case filters.
|
||||
///
|
||||
/// @return Returns @c true if all tests passed; @c false otherwise.
|
||||
///
|
||||
bool
|
||||
execute_all(reporter& r, strings const& filters);
|
||||
|
||||
} // namespace bitshift::validate
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,130 @@
|
||||
#include <bitshift/validate/failure.hxx>
|
||||
|
||||
#include <bitshift/validate/reporting.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
unary_assertion_failure::
|
||||
unary_assertion_failure(string message,
|
||||
string file,
|
||||
uint32_t line,
|
||||
string expr,
|
||||
string val)
|
||||
: _message{std::move(message)}
|
||||
, _file {std::move(file)}
|
||||
, _line {line}
|
||||
, _expr {std::move(expr)}
|
||||
, _val {std::move(val)}
|
||||
{}
|
||||
|
||||
string const&
|
||||
unary_assertion_failure::
|
||||
get_file() const
|
||||
{
|
||||
return _file;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
unary_assertion_failure::
|
||||
get_line() const
|
||||
{
|
||||
return _line;
|
||||
}
|
||||
|
||||
string const&
|
||||
unary_assertion_failure::
|
||||
get_expr() const
|
||||
{
|
||||
return _expr;
|
||||
}
|
||||
|
||||
string const&
|
||||
unary_assertion_failure::
|
||||
get_val() const
|
||||
{
|
||||
return _val;
|
||||
}
|
||||
|
||||
void
|
||||
unary_assertion_failure::
|
||||
report(reporter& r) const
|
||||
{
|
||||
auto p = r.log_failure(_message, _file, _line);
|
||||
|
||||
p << "expression: " << _expr << '\n';
|
||||
p << "value : " << _val << '\n';
|
||||
}
|
||||
|
||||
binary_assertion_failure::
|
||||
binary_assertion_failure(string message,
|
||||
string file,
|
||||
uint32_t line,
|
||||
string lhs_expr,
|
||||
string lhs_val,
|
||||
string rhs_expr,
|
||||
string rhs_val)
|
||||
: _message {std::move(message)}
|
||||
, _file {std::move(file)}
|
||||
, _line {line}
|
||||
, _lhs_expr{std::move(lhs_expr)}
|
||||
, _lhs_val {std::move(lhs_val)}
|
||||
, _rhs_expr{std::move(rhs_expr)}
|
||||
, _rhs_val {std::move(rhs_val)}
|
||||
{}
|
||||
|
||||
string const&
|
||||
binary_assertion_failure::
|
||||
get_file() const
|
||||
{
|
||||
return _file;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
binary_assertion_failure::
|
||||
get_line() const
|
||||
{
|
||||
return _line;
|
||||
}
|
||||
|
||||
string const&
|
||||
binary_assertion_failure::
|
||||
get_lhs_expr() const
|
||||
{
|
||||
return _lhs_expr;
|
||||
}
|
||||
|
||||
string const&
|
||||
binary_assertion_failure::
|
||||
get_lhs_val() const
|
||||
{
|
||||
return _lhs_val;
|
||||
}
|
||||
|
||||
string const&
|
||||
binary_assertion_failure::
|
||||
get_rhs_expr() const
|
||||
{
|
||||
return _rhs_expr;
|
||||
}
|
||||
|
||||
string const&
|
||||
binary_assertion_failure::
|
||||
get_rhs_val() const
|
||||
{
|
||||
return _rhs_val;
|
||||
}
|
||||
|
||||
void
|
||||
binary_assertion_failure::
|
||||
report(reporter& r) const
|
||||
{
|
||||
auto p = r.log_failure(_message, _file, _line);
|
||||
|
||||
p << "lhs expression: " << _lhs_expr << '\n';
|
||||
p << "lhs value : " << _lhs_val << '\n';
|
||||
p << "rhs expression: " << _rhs_expr << '\n';
|
||||
p << "rhs value : " << _rhs_val << '\n';
|
||||
}
|
||||
|
||||
} // namespace bitshift::validate
|
||||
@@ -0,0 +1,208 @@
|
||||
#ifndef bitshift__validate__failure_hxx_
|
||||
#define bitshift__validate__failure_hxx_
|
||||
|
||||
#include <bitshift/validate/types.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
struct ignore { };
|
||||
|
||||
class reporter;
|
||||
|
||||
/// @brief Class used to indicate an assertion failure.
|
||||
///
|
||||
class assertion_failure
|
||||
{
|
||||
public:
|
||||
/// @brief Destructor.
|
||||
///
|
||||
virtual
|
||||
~assertion_failure() noexcept = default;
|
||||
|
||||
/// @brief Report assertion failure.
|
||||
///
|
||||
/// @param r The reporter.
|
||||
///
|
||||
virtual
|
||||
void
|
||||
report(reporter& r) const = 0;
|
||||
|
||||
protected:
|
||||
/// @brief Constructor.
|
||||
///
|
||||
assertion_failure() = default;
|
||||
|
||||
/// @brief Copy-construction is disabled.
|
||||
///
|
||||
assertion_failure(assertion_failure const&) = delete;
|
||||
|
||||
/// @brief Move-construction is disabled.
|
||||
///
|
||||
assertion_failure(assertion_failure&&) = delete;
|
||||
|
||||
/// @brief Copy-assignment is disabled.
|
||||
///
|
||||
assertion_failure& operator=(assertion_failure const&) = delete;
|
||||
|
||||
/// @brief Move-assignment is disabled.
|
||||
///
|
||||
assertion_failure& operator=(assertion_failure&&) = delete;
|
||||
|
||||
};
|
||||
|
||||
/// @brief Indicates a unary assertion failure.
|
||||
///
|
||||
class unary_assertion_failure
|
||||
: public assertion_failure
|
||||
{
|
||||
public:
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param message The assertion failure message.
|
||||
/// @param file The file in which the assertion failure occurred.
|
||||
/// @param line The line on which the assertion failure occurred.
|
||||
/// @param expr The expression that caused the assertion failure.
|
||||
/// @param val The expression value that caused the assertion failure.
|
||||
///
|
||||
unary_assertion_failure(string message,
|
||||
string file,
|
||||
uint32_t line,
|
||||
string expr,
|
||||
string val);
|
||||
|
||||
/// @brief Copy-construction is disabled.
|
||||
///
|
||||
unary_assertion_failure(unary_assertion_failure const&) = delete;
|
||||
|
||||
/// @brief Move-construction is disabled.
|
||||
///
|
||||
unary_assertion_failure(unary_assertion_failure&&) = delete;
|
||||
|
||||
/// @brief Get file.
|
||||
///
|
||||
string const&
|
||||
get_file() const;
|
||||
|
||||
/// @brief Get line.
|
||||
///
|
||||
uint32_t
|
||||
get_line() const;
|
||||
|
||||
/// @brief Get expression.
|
||||
///
|
||||
string const&
|
||||
get_expr() const;
|
||||
|
||||
/// @brief Get expression value.
|
||||
///
|
||||
string const&
|
||||
get_val() const;
|
||||
|
||||
void
|
||||
report(reporter&) const override;
|
||||
|
||||
/// @brief Copy-assignment is disabled.
|
||||
///
|
||||
unary_assertion_failure& operator=(unary_assertion_failure const&) = delete;
|
||||
|
||||
/// @brief Move-assignment is disabled.
|
||||
///
|
||||
unary_assertion_failure& operator=(unary_assertion_failure&&) = delete;
|
||||
|
||||
private:
|
||||
string _message;
|
||||
string _file;
|
||||
uint32_t _line{};
|
||||
string _expr;
|
||||
string _val;
|
||||
|
||||
};
|
||||
|
||||
/// @brief Indicates a binary assertion failure.
|
||||
///
|
||||
class binary_assertion_failure
|
||||
: public assertion_failure
|
||||
{
|
||||
public:
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param message The assertion failure message.
|
||||
/// @param file The file in which the assertion failure occurred.
|
||||
/// @param line The line on which the assertion failure occurred.
|
||||
/// @param lhs_expr The left-hand side expression that caused the assertion failure.
|
||||
/// @param lhs_val The left-hand side expression value that caused the assertion failure.
|
||||
/// @param rhs_expr The right-hand side expression that caused the assertion failure.
|
||||
/// @param rhs_val The right-hand side expression value that caused the assertion failure.
|
||||
///
|
||||
binary_assertion_failure(string message,
|
||||
string file,
|
||||
uint32_t line,
|
||||
string lhs_expr,
|
||||
string lhs_val,
|
||||
string rhs_expr,
|
||||
string rhs_val);
|
||||
|
||||
/// @brief Copy-construction is disabled.
|
||||
///
|
||||
binary_assertion_failure(binary_assertion_failure const&) = delete;
|
||||
|
||||
/// @brief Move-construction is disabled.
|
||||
///
|
||||
binary_assertion_failure(binary_assertion_failure&&) = delete;
|
||||
|
||||
/// @brief Get file.
|
||||
///
|
||||
string const&
|
||||
get_file() const;
|
||||
|
||||
/// @brief Get line.
|
||||
///
|
||||
uint32_t
|
||||
get_line() const;
|
||||
|
||||
/// @brief Get left-hand side expression.
|
||||
///
|
||||
string const&
|
||||
get_lhs_expr() const;
|
||||
|
||||
/// @brief Get left-hand side expression value.
|
||||
///
|
||||
string const&
|
||||
get_lhs_val() const;
|
||||
|
||||
/// @brief Get right-hand side expression.
|
||||
///
|
||||
string const&
|
||||
get_rhs_expr() const;
|
||||
|
||||
/// @brief Get right-hand side expression value.
|
||||
///
|
||||
string const&
|
||||
get_rhs_val() const;
|
||||
|
||||
void
|
||||
report(reporter&) const override;
|
||||
|
||||
/// @brief Copy-assignment is disabled.
|
||||
///
|
||||
binary_assertion_failure& operator=(binary_assertion_failure const&) = delete;
|
||||
|
||||
/// @brief Move-assignment is disabled.
|
||||
///
|
||||
binary_assertion_failure& operator=(binary_assertion_failure&&) = delete;
|
||||
|
||||
private:
|
||||
string _message;
|
||||
string _file;
|
||||
uint32_t _line{};
|
||||
string _lhs_expr;
|
||||
string _lhs_val;
|
||||
string _rhs_expr;
|
||||
string _rhs_val;
|
||||
|
||||
};
|
||||
|
||||
} // namespace bitshift::validate
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <bitshift/validate/filter.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
bool
|
||||
match_filter(string const& filter, string const& subject)
|
||||
{
|
||||
auto fcur = filter.begin();
|
||||
auto fend = filter.end();
|
||||
|
||||
auto scur = subject.begin();
|
||||
auto send = subject.end();
|
||||
|
||||
while (fcur != fend && scur != send) {
|
||||
auto a = fcur;
|
||||
|
||||
for (;;) {
|
||||
if (fcur == fend || *fcur == '.') {
|
||||
break;
|
||||
}
|
||||
++fcur;
|
||||
}
|
||||
|
||||
auto aend = fcur;
|
||||
|
||||
if (fcur != fend && *fcur == '.') {
|
||||
++fcur;
|
||||
}
|
||||
|
||||
auto b = scur;
|
||||
|
||||
for (;;) {
|
||||
if (scur == send || *scur == '.') {
|
||||
break;
|
||||
}
|
||||
++scur;
|
||||
}
|
||||
|
||||
auto bend = scur;
|
||||
|
||||
if (scur != send && *scur == '.') {
|
||||
++scur;
|
||||
}
|
||||
|
||||
string astr{a, aend};
|
||||
string bstr{b, bend};
|
||||
|
||||
if (astr == "*") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (astr != bstr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// We determine a match by check that we've reached the end of both the
|
||||
// filter and the subject we're testing.
|
||||
//
|
||||
return fcur == fend && scur == send;
|
||||
}
|
||||
|
||||
} // namespace bitshift::validate
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef bitshift__validate__filter_hxx_
|
||||
#define bitshift__validate__filter_hxx_
|
||||
|
||||
#include <bitshift/validate/types.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
/// @brief Match subject against a given filter pattern.
|
||||
///
|
||||
/// @param filter The filter pattern to match against.
|
||||
/// @param subject The subject to test.
|
||||
///
|
||||
bool
|
||||
match_filter(string const& filter, string const& subject);
|
||||
|
||||
} // namespace bitshift::validate
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,114 @@
|
||||
#ifndef bitshift__validate__intrusive_list_hxx_
|
||||
#define bitshift__validate__intrusive_list_hxx_
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
class intrusive_list
|
||||
{
|
||||
public:
|
||||
|
||||
protected:
|
||||
/// @brief Constructor.
|
||||
///
|
||||
intrusive_list()
|
||||
{
|
||||
if (!first()) {
|
||||
first() = self();
|
||||
}
|
||||
|
||||
if (!last()) {
|
||||
last() = self();
|
||||
}
|
||||
|
||||
first()->_prev = self();
|
||||
last()->_next = self();
|
||||
|
||||
_prev = last();
|
||||
_next = first();
|
||||
|
||||
last() = self();
|
||||
}
|
||||
|
||||
/// @brief Copy-construction is disabled.
|
||||
///
|
||||
intrusive_list(intrusive_list<T> const&) = delete;
|
||||
|
||||
/// @brief Move-construction is disabled.
|
||||
///
|
||||
intrusive_list(intrusive_list<T>&&) = delete;
|
||||
|
||||
/// @brief Destructor.
|
||||
///
|
||||
~intrusive_list() noexcept
|
||||
{
|
||||
if (first() == this) {
|
||||
first() = _next;
|
||||
}
|
||||
|
||||
if (last() == this) {
|
||||
last() = _prev;
|
||||
}
|
||||
|
||||
_prev->_next = _next;
|
||||
_next->_prev = _prev;
|
||||
}
|
||||
|
||||
/// @brief Copy-assignment is disabled.
|
||||
///
|
||||
intrusive_list<T>& operator=(intrusive_list<T> const&) = delete;
|
||||
|
||||
/// @brief Move-assignment is disabled.
|
||||
///
|
||||
intrusive_list<T>& operator=(intrusive_list<T>&&) = delete;
|
||||
|
||||
protected:
|
||||
/// @brief Get the previous node.
|
||||
///
|
||||
T*
|
||||
previous()
|
||||
{
|
||||
return static_cast<T*>(_prev);
|
||||
}
|
||||
|
||||
/// @brief Get the next node.
|
||||
///
|
||||
T*
|
||||
next()
|
||||
{
|
||||
return static_cast<T*>(_next);
|
||||
}
|
||||
|
||||
static
|
||||
T*&
|
||||
first()
|
||||
{
|
||||
static T* ptr{nullptr};
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static
|
||||
T*&
|
||||
last()
|
||||
{
|
||||
static T* ptr{nullptr};
|
||||
return ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
T*
|
||||
self()
|
||||
{
|
||||
return static_cast<T*>(this);
|
||||
}
|
||||
|
||||
private:
|
||||
T* _prev{nullptr};
|
||||
T* _next{nullptr};
|
||||
|
||||
};
|
||||
|
||||
} // namespace bitshift::validate
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,202 @@
|
||||
#ifndef bitshift__validate__macro_hxx_
|
||||
#define bitshift__validate__macro_hxx_
|
||||
|
||||
#include <bitshift/validate/assert.hxx>
|
||||
#include <bitshift/validate/setup.hxx>
|
||||
#include <bitshift/validate/teardown.hxx>
|
||||
#include <bitshift/validate/test-case.hxx>
|
||||
|
||||
/// @defgroup assertions Assertions
|
||||
///
|
||||
/// @brief Describes the BitShift Validate assertion macros.
|
||||
///
|
||||
|
||||
#define BV_TEST_SETUP_2(file, line) \
|
||||
static \
|
||||
void \
|
||||
test_setup_func_##line(); \
|
||||
bitshift::validate::setup \
|
||||
test_setup_##line{file, line, &test_setup_func_##line}; \
|
||||
void \
|
||||
test_setup_func_##line()
|
||||
|
||||
#define BV_TEST_SETUP_1(file, line) \
|
||||
BV_TEST_SETUP_2(file, line)
|
||||
|
||||
/// @ingroup assertions
|
||||
/// @brief Register a test setup function.
|
||||
/// @param desc A description of the setup function.
|
||||
/// @hideinitializer
|
||||
///
|
||||
/// ### Usage Example:
|
||||
///
|
||||
/// ```cxx
|
||||
/// BV_TEST_SETUP(setup environment)
|
||||
/// {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
#define BV_TEST_SETUP(desc) \
|
||||
BV_TEST_SETUP_1(__FILE__, __LINE__)
|
||||
|
||||
#define BV_TEST_TEARDOWN_2(file, line) \
|
||||
static \
|
||||
void \
|
||||
test_teardown_func_##line(); \
|
||||
bitshift::validate::teardown \
|
||||
test_teardown_##line{file, line, &test_teardown_func_##line}; \
|
||||
void \
|
||||
test_teardown_func_##line()
|
||||
|
||||
#define BV_TEST_TEARDOWN_1(file, line) \
|
||||
BV_TEST_TEARDOWN_2(file, line)
|
||||
|
||||
/// @ingroup assertions
|
||||
/// @brief Register a test teardown function.
|
||||
/// @param desc A description of the teardown function.
|
||||
/// @hideinitializer
|
||||
///
|
||||
/// ### Usage Example:
|
||||
///
|
||||
/// ```cxx
|
||||
/// BV_TEST_TEARDOWN(cleanup resources)
|
||||
/// {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
#define BV_TEST_TEARDOWN(desc) \
|
||||
BV_TEST_TEARDOWN_1(__FILE__, __LINE__)
|
||||
|
||||
#define BV_TEST_2(name, desc, file, line) \
|
||||
static \
|
||||
void \
|
||||
test_func_##line(); \
|
||||
bitshift::validate::test_case \
|
||||
test_##line{#name, desc, file, line, &test_func_##line}; \
|
||||
void \
|
||||
test_func_##line()
|
||||
|
||||
#define BV_TEST_1(name, desc, file, line) \
|
||||
BV_TEST_2(name, desc, file, line)
|
||||
|
||||
/// @ingroup assertions
|
||||
/// @brief Register a test function.
|
||||
/// @param name An identifier for the test.
|
||||
/// @param desc A decsription of the test.
|
||||
/// @hideinitializer
|
||||
///
|
||||
/// ### Usage Example:
|
||||
///
|
||||
/// ```cxx
|
||||
/// BV_TEST(str.length, "test string length")
|
||||
/// {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
#define BV_TEST(name, desc) \
|
||||
BV_TEST_1(name, desc, __FILE__, __LINE__)
|
||||
|
||||
/// @ingroup assertions
|
||||
/// @brief Ignore a test.
|
||||
/// @hideinitializer
|
||||
///
|
||||
#define BV_IGNORE throw bitshift::validate::ignore {};
|
||||
|
||||
/// @ingroup assertions
|
||||
/// @brief Assert a @c true value.
|
||||
/// @param expr The expression to test.
|
||||
/// @hideinitializer
|
||||
///
|
||||
/// ### Usage Example:
|
||||
///
|
||||
/// ```cxx
|
||||
/// BV_TEST(str.empty, "test string 'empty'")
|
||||
/// {
|
||||
/// std::string empty{};
|
||||
/// BV_ASSERT_TRUE(empty.empty());
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
#define BV_ASSERT_TRUE(expr) \
|
||||
bitshift::validate::assertion::assert_true((expr), #expr)
|
||||
|
||||
/// @ingroup assertions
|
||||
/// @brief Assert a @c false value.
|
||||
/// @param expr The expression to test.
|
||||
/// @hideinitializer
|
||||
///
|
||||
/// ### Usage Example:
|
||||
///
|
||||
/// ```cxx
|
||||
/// BV_TEST(str.not_empty, "test string not 'empty'")
|
||||
/// {
|
||||
/// std::string not_empty{"hello, world"};
|
||||
/// BV_ASSERT_FALSE(not_empty.empty());
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
#define BV_ASSERT_FALSE(expr) \
|
||||
bitshift::validate::assertion::assert_false((expr), #expr)
|
||||
|
||||
/// @ingroup assertions
|
||||
/// @brief Assert a @c nullptr value.
|
||||
/// @param expr The expression to test.
|
||||
/// @hideinitializer
|
||||
///
|
||||
/// ### Usage Example:
|
||||
///
|
||||
/// ```cxx
|
||||
/// BV_TEST(ptr.is_null, "test null pointer")
|
||||
/// {
|
||||
/// char const* this_is_null{nullptr};
|
||||
/// BV_ASSERT_NULLPTR(this_is_null);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
#define BV_ASSERT_NULLPTR(expr) \
|
||||
bitshift::validate::assertion::assert_nullptr((expr), #expr)
|
||||
|
||||
/// @ingroup assertions
|
||||
/// @brief Assert @a lhs is equal to @a rhs.
|
||||
/// @param lhs The left-hand side expression to test.
|
||||
/// @param rhs The right-hand side expression to test.
|
||||
/// @hideinitializer
|
||||
///
|
||||
/// ### Usage Example:
|
||||
///
|
||||
/// ```cxx
|
||||
/// BV_TEST(equal, "test equal")
|
||||
/// {
|
||||
/// int lhs = 1;
|
||||
/// int rhs = 1;
|
||||
/// BV_ASSERT_EQUAL(lhs, rhs);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
#define BV_ASSERT_EQUAL(lhs, rhs) \
|
||||
bitshift::validate::assertion::assert_equal((lhs), (rhs), #lhs, #rhs)
|
||||
|
||||
/// @ingroup assertions
|
||||
/// @brief Assert @a lhs is not equal to @a rhs.
|
||||
/// @param lhs The left-hand side expression to test.
|
||||
/// @param rhs The right-hand side expression to test.
|
||||
/// @hideinitializer
|
||||
///
|
||||
/// ### Usage Example:
|
||||
///
|
||||
/// ```cxx
|
||||
/// BV_TEST(not_equal, "test not equal")
|
||||
/// {
|
||||
/// int lhs = 1;
|
||||
/// int rhs = 2;
|
||||
/// BV_ASSERT_NOT_EQUAL(lhs, rhs);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
#define BV_ASSERT_NOT_EQUAL(lhs, rhs) \
|
||||
bitshift::validate::assertion::assert_not_equal((lhs), (rhs), #lhs, #rhs)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,165 @@
|
||||
#include <bitshift/validate/main.hxx>
|
||||
|
||||
#include <bitshift/validate/ansi.hxx>
|
||||
#include <bitshift/validate/execute.hxx>
|
||||
#include <bitshift/validate/options.hxx>
|
||||
#include <bitshift/validate/test-case.hxx>
|
||||
#include <bitshift/validate/version.hxx>
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
/// @brief Print version information.
|
||||
///
|
||||
/// @param os The output stream.
|
||||
///
|
||||
static
|
||||
void
|
||||
print_version(ostream& os)
|
||||
{
|
||||
os << "BitShift Validate Test Runner (" << BITSHIFT_VALIDATE_VERSION_STR << ")\n";
|
||||
}
|
||||
|
||||
/// @brief Print usage information.
|
||||
///
|
||||
/// @param execname The program execname.
|
||||
/// @param os The output stream.
|
||||
///
|
||||
static
|
||||
void
|
||||
print_usage(string const& execname, ostream& os)
|
||||
{
|
||||
auto b = [](auto&&... args) -> string
|
||||
{
|
||||
stringstream str;
|
||||
str << ansi::kBold;
|
||||
(
|
||||
(str << args), ...
|
||||
);
|
||||
str << ansi::reset;
|
||||
return str.str();
|
||||
};
|
||||
|
||||
os << b("usage: ") << execname << " [<option>...]\n"
|
||||
<< '\n'
|
||||
<< "This is the BitShift Validate Test Runner.\n"
|
||||
<< '\n'
|
||||
<< b("OPTIONS") << '\n'
|
||||
<< " -v, --version Show version information\n"
|
||||
<< " -h, --help Show this help\n"
|
||||
<< " -l, --list List all available tests\n"
|
||||
<< " -q, --quiet Silence all output\n"
|
||||
<< " --show-file Include file information in output\n"
|
||||
<< " --show-line Include line information in output\n"
|
||||
<< " -f, --filter <filter> Add a test filter\n"
|
||||
<< '\n'
|
||||
;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
list_test_cases(ostream& os)
|
||||
{
|
||||
auto current = test_case::first();
|
||||
|
||||
if (!current) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t max_length{0};
|
||||
|
||||
// Calculate the length of the longest test case name.
|
||||
//
|
||||
do {
|
||||
if (auto length = current->name().size(); length > max_length) {
|
||||
max_length = length;
|
||||
}
|
||||
|
||||
current = current->next();
|
||||
} while (current && current != test_case::first());
|
||||
|
||||
current = test_case::first();
|
||||
|
||||
if (!current) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
os << ansi::kBold << std::setw(max_length) << std::left
|
||||
<< current->name() << ansi::reset << ": "
|
||||
<< current->description()
|
||||
<< "\n";
|
||||
|
||||
current = current->next();
|
||||
} while (current && current != test_case::first());
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
try
|
||||
{
|
||||
options opts{strings{argv + 1, argc + argv}};
|
||||
|
||||
if (opts.version) {
|
||||
print_version(cout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (opts.usage) {
|
||||
print_usage(argv[0], cout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (opts.list) {
|
||||
list_test_cases(cout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
using vtype = variant<quiet_reporter, ostream_reporter>;
|
||||
|
||||
auto create_reporter = [&] -> vtype
|
||||
{
|
||||
if (opts.quiet) {
|
||||
return vtype{std::in_place_type<quiet_reporter>};
|
||||
}
|
||||
|
||||
return vtype{
|
||||
std::in_place_type<ostream_reporter>,
|
||||
cout,
|
||||
opts.show_file,
|
||||
opts.show_line
|
||||
};
|
||||
};
|
||||
|
||||
auto r = create_reporter();
|
||||
|
||||
auto get_reporter = [&] -> reporter&
|
||||
{
|
||||
if (std::holds_alternative<quiet_reporter>(r)) {
|
||||
return std::get<quiet_reporter>(r);
|
||||
}
|
||||
else if (std::holds_alternative<ostream_reporter>(r)) {
|
||||
return std::get<ostream_reporter>(r);
|
||||
}
|
||||
else {
|
||||
throw runtime_error{"invalid reporter"};
|
||||
}
|
||||
};
|
||||
|
||||
if (opts.show_line && !opts.show_file) {
|
||||
throw runtime_error{"'--show-line' requires '--show-file'"};
|
||||
}
|
||||
|
||||
return execute_all(get_reporter(), opts.filters) ? 0 : 1;
|
||||
}
|
||||
catch (exception const& ex) {
|
||||
cerr << argv[0] << ": error: " << ex.what() << '\n';
|
||||
return 1;
|
||||
}
|
||||
catch (...) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace bitshift::validate
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef bitshift__validate__main_hxx_
|
||||
#define bitshift__validate__main_hxx_
|
||||
|
||||
#include <bitshift/validate/types.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
/// @brief Main.
|
||||
///
|
||||
/// @param argc Your typical argc.
|
||||
/// @param argv Your typical argv.
|
||||
///
|
||||
int
|
||||
main(int argc, char* argv[]);
|
||||
|
||||
} // namespace bitshift::validate
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
#include <bitshift/validate/options.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
options::
|
||||
options(strings args)
|
||||
{
|
||||
for (auto it = args.begin(); it != args.end(); ++it) {
|
||||
if (it->empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*it == "--") {
|
||||
throw runtime_error{"invalid argument '--'"};
|
||||
}
|
||||
|
||||
if ('-' != (*it)[0] || 1 == it->size()) {
|
||||
throw runtime_error{"invalid argument '" + *it + "'"};
|
||||
}
|
||||
|
||||
if ('-' == (*it)[0] && '-' != (*it)[1]) {
|
||||
for (auto const& j : it->substr(1)) {
|
||||
switch (j) {
|
||||
case 'v':
|
||||
version = true;
|
||||
continue;
|
||||
|
||||
case 'h':
|
||||
usage = true;
|
||||
continue;
|
||||
|
||||
case 'l':
|
||||
list = true;
|
||||
continue;
|
||||
|
||||
case 'q':
|
||||
quiet = true;
|
||||
continue;
|
||||
|
||||
case 'f':
|
||||
++it;
|
||||
|
||||
if (it == args.end()) {
|
||||
throw runtime_error{"missing argument to '-f'"};
|
||||
}
|
||||
|
||||
filters.emplace_back(*it);
|
||||
continue;
|
||||
}
|
||||
|
||||
throw runtime_error{"unrecognized option '" + string{&j, 1} + "'"};
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*it == "--version") {
|
||||
version = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*it == "--help") {
|
||||
usage = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*it == "--list") {
|
||||
list = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*it == "--quiet") {
|
||||
quiet = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*it == "--show-file") {
|
||||
show_file = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*it == "--show-line") {
|
||||
show_line = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*it == "--filter") {
|
||||
++it;
|
||||
|
||||
if (it == args.end()) {
|
||||
throw runtime_error{"missing argument to '--filter'"};
|
||||
}
|
||||
|
||||
filters.emplace_back(*it);
|
||||
continue;
|
||||
}
|
||||
|
||||
throw runtime_error{"unrecognized option '" + *it + "'"};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace bitshift::validate
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef bitshift__validate__options_hxx_
|
||||
#define bitshift__validate__options_hxx_
|
||||
|
||||
#include <bitshift/validate/types.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
struct options
|
||||
{
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param args Program arguments.
|
||||
///
|
||||
explicit
|
||||
options(strings args);
|
||||
|
||||
/// @brief '-v' or '--version' specified on the command-line.
|
||||
///
|
||||
bool version{false};
|
||||
|
||||
/// @brief '-h- or '--help' specified on the command-line.
|
||||
///
|
||||
bool usage{false};
|
||||
|
||||
/// @brief '-l' or '--list' specified on the command-line.
|
||||
///
|
||||
bool list{};
|
||||
|
||||
/// @brief '-q' or '--quiet' specified on the command-line.
|
||||
///
|
||||
bool quiet{};
|
||||
|
||||
/// @brief '--show-file' specified on the command-line.
|
||||
///
|
||||
bool show_file{};
|
||||
|
||||
/// @brief '--show-line' specified on the command-line.
|
||||
///
|
||||
bool show_line{};
|
||||
|
||||
/// @brief '--filter' option(s).
|
||||
///
|
||||
strings filters;
|
||||
|
||||
};
|
||||
|
||||
} // namespace bitshift::validate
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,263 @@
|
||||
#include <bitshift/validate/reporting.hxx>
|
||||
|
||||
#include <bitshift/validate/ansi.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
static
|
||||
void
|
||||
indent(ostream& os, size_t count, string const& str)
|
||||
{
|
||||
stringstream sstr{str};
|
||||
|
||||
for (string line; std::getline(sstr, line);) {
|
||||
os << string(count, ' ') << line << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
string
|
||||
_bold(auto&&... args)
|
||||
{
|
||||
stringstream str;
|
||||
|
||||
str << ansi::kBold;
|
||||
(
|
||||
(str << args), ...
|
||||
);
|
||||
|
||||
str << ansi::reset;
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
reporter::
|
||||
~reporter() noexcept
|
||||
{}
|
||||
|
||||
reporter::proxy
|
||||
reporter::
|
||||
log_setup(string const& file, int line)
|
||||
{
|
||||
return proxy{
|
||||
[this, file, line](string const& detail)
|
||||
{
|
||||
do_log_setup(file, line, detail);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
reporter::proxy
|
||||
reporter::
|
||||
log_teardown(string const& file, int line)
|
||||
{
|
||||
return proxy{
|
||||
[this, file, line](string const& detail)
|
||||
{
|
||||
do_log_teardown(file, line, detail);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
reporter::proxy
|
||||
reporter::
|
||||
log_test_case(string const& name,
|
||||
string const& description,
|
||||
string const& file,
|
||||
int line)
|
||||
{
|
||||
return proxy{
|
||||
[this, name, description, file, line](string const& detail)
|
||||
{
|
||||
do_log_test_case(name, description, file, line, detail);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
reporter::proxy
|
||||
reporter::
|
||||
log_failure(string message, string file, int line)
|
||||
{
|
||||
return proxy{
|
||||
[this, message, file, line](string const& detail)
|
||||
{
|
||||
do_log_failure(message, file, line, detail);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
reporter::
|
||||
log_summary(uint16_t total,
|
||||
uint16_t ignored,
|
||||
uint16_t pass,
|
||||
uint16_t fail)
|
||||
{
|
||||
do_log_summary(total, ignored, pass, fail);
|
||||
}
|
||||
|
||||
reporter::
|
||||
reporter()
|
||||
{}
|
||||
|
||||
reporter::proxy::
|
||||
~proxy() noexcept(false) // noexcept(false) since _cb(...) may throw.
|
||||
{
|
||||
_cb(_detail.str());
|
||||
}
|
||||
|
||||
reporter::proxy::
|
||||
proxy(function<void(string const&)> cb)
|
||||
: _cb{cb}
|
||||
{}
|
||||
|
||||
ostream_reporter::
|
||||
ostream_reporter(ostream& os, bool show_file, bool show_line)
|
||||
: _os {os}
|
||||
, _show_file{show_file}
|
||||
, _show_line{show_line}
|
||||
{}
|
||||
|
||||
ostream_reporter::
|
||||
~ostream_reporter() noexcept
|
||||
{}
|
||||
|
||||
ostream&
|
||||
ostream_reporter::
|
||||
output()
|
||||
{
|
||||
return _os;
|
||||
}
|
||||
|
||||
void
|
||||
ostream_reporter::
|
||||
do_log_setup(string const& file, int line, string const& detail)
|
||||
{
|
||||
_os << "Executing setup...\n";
|
||||
|
||||
if (_show_file) {
|
||||
_os << " defined in " << file;
|
||||
|
||||
if (_show_line) {
|
||||
_os << " at line " << line;
|
||||
}
|
||||
|
||||
_os << '\n';
|
||||
}
|
||||
|
||||
indent(_os, 6, detail);
|
||||
}
|
||||
|
||||
void
|
||||
ostream_reporter::
|
||||
do_log_teardown(string const& file, int line, string const& detail)
|
||||
{
|
||||
_os << "Executing teardown...\n";
|
||||
|
||||
if (_show_file) {
|
||||
_os << " defined in " << file;
|
||||
|
||||
if (_show_line) {
|
||||
_os << " at line " << line;
|
||||
}
|
||||
|
||||
_os << '\n';
|
||||
}
|
||||
|
||||
indent(_os, 6, detail);
|
||||
}
|
||||
|
||||
void
|
||||
ostream_reporter::
|
||||
do_log_test_case(string const& name,
|
||||
string const& description,
|
||||
string const& file,
|
||||
int line,
|
||||
string const& detail)
|
||||
{
|
||||
_os << "Executing test case \""
|
||||
<< ansi::kBold << name << ansi::reset << "\": "
|
||||
<< description << "\n";
|
||||
|
||||
if (_show_file) {
|
||||
_os << " defined in " << file;
|
||||
|
||||
if (_show_line) {
|
||||
_os << " at line " << line;
|
||||
}
|
||||
|
||||
_os << '\n';
|
||||
}
|
||||
|
||||
indent(_os, 6, detail);
|
||||
}
|
||||
|
||||
void
|
||||
ostream_reporter::
|
||||
do_log_failure(string const& message,
|
||||
string const& file,
|
||||
int line,
|
||||
string const& detail)
|
||||
{
|
||||
|
||||
_os << ansi{ansi::kRed, ansi::kBold}
|
||||
<< " assertion failure: " << ansi::reset << message << '\n'
|
||||
<< " source " << file << ":" << line << ":\n";
|
||||
|
||||
indent(_os, 6, detail);
|
||||
}
|
||||
|
||||
void
|
||||
ostream_reporter::
|
||||
do_log_summary(uint16_t total,
|
||||
uint16_t ignored,
|
||||
uint16_t pass,
|
||||
uint16_t fail)
|
||||
{
|
||||
_os << ansi::kBold << "Test statistics\n" << ansi::reset
|
||||
<< " Tests : " << total << '\n'
|
||||
<< " Tests ignored: " << ignored << '\n'
|
||||
<< " Tests passed : " << pass << '\n'
|
||||
<< " Tests failed : " << fail << '\n'
|
||||
;
|
||||
}
|
||||
|
||||
quiet_reporter::
|
||||
quiet_reporter()
|
||||
{}
|
||||
|
||||
quiet_reporter::
|
||||
~quiet_reporter() noexcept
|
||||
{}
|
||||
|
||||
void
|
||||
quiet_reporter::
|
||||
do_log_setup(string const&, int, string const&)
|
||||
{}
|
||||
|
||||
void
|
||||
quiet_reporter::
|
||||
do_log_teardown(string const&, int, string const&)
|
||||
{}
|
||||
|
||||
void
|
||||
quiet_reporter::
|
||||
do_log_test_case(string const&,
|
||||
string const&,
|
||||
string const&,
|
||||
int,
|
||||
string const&)
|
||||
{}
|
||||
|
||||
void
|
||||
quiet_reporter::
|
||||
do_log_failure(string const&, string const&, int, string const&)
|
||||
{}
|
||||
|
||||
void
|
||||
quiet_reporter::
|
||||
do_log_summary(uint16_t, uint16_t, uint16_t, uint16_t)
|
||||
{}
|
||||
|
||||
} // namespace bitshift::validate
|
||||
@@ -0,0 +1,350 @@
|
||||
#ifndef bitshift__validate__reporting_hxx_
|
||||
#define bitshift__validate__reporting_hxx_
|
||||
|
||||
#include <bitshift/validate/types.hxx>
|
||||
|
||||
#include <bitshift/validate/setup.hxx>
|
||||
#include <bitshift/validate/teardown.hxx>
|
||||
#include <bitshift/validate/test-case.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
/// @brief Abstract test suite reporter.
|
||||
///
|
||||
class reporter
|
||||
{
|
||||
class proxy;
|
||||
friend proxy;
|
||||
|
||||
public:
|
||||
/// @brief Destructor.
|
||||
///
|
||||
virtual
|
||||
~reporter() noexcept;
|
||||
|
||||
/// @brief Log test suite setup execution.
|
||||
///
|
||||
/// @param file The file in which the setup is defined.
|
||||
/// @param line The line on which the setup is defined.
|
||||
///
|
||||
proxy
|
||||
log_setup(string const& file, int line);
|
||||
|
||||
/// @brief Log test suite teardown execution.
|
||||
///
|
||||
/// @param file The file in which the teardown is defined.
|
||||
/// @param line The line on which the teardown is defined.
|
||||
///
|
||||
proxy
|
||||
log_teardown(string const& file, int line);
|
||||
|
||||
/// @brief Log test case execution.
|
||||
///
|
||||
/// @param name The name of the test case.
|
||||
/// @param description A description of the test case.
|
||||
/// @param file The file in which the test case is defined.
|
||||
/// @param line The line on which the test case is defined.
|
||||
///
|
||||
proxy
|
||||
log_test_case(string const& name,
|
||||
string const& description,
|
||||
string const& file,
|
||||
int line);
|
||||
|
||||
/// @brief Log test case failure.
|
||||
///
|
||||
/// @param message A message describing the failure.
|
||||
/// @param file The file in which the failure occurred.
|
||||
/// @param line The line on which the error occurred.
|
||||
///
|
||||
proxy
|
||||
log_failure(string message, string file, int line);
|
||||
|
||||
/// @brief Log test suite summary.
|
||||
///
|
||||
/// @param total The total number of tests.
|
||||
/// @param ignored The total number of ignored tests.
|
||||
/// @param pass The total number of passed tests.
|
||||
/// @param fail The total number of failed tests.
|
||||
///
|
||||
void
|
||||
log_summary(uint16_t total,
|
||||
uint16_t ignored,
|
||||
uint16_t pass,
|
||||
uint16_t fail);
|
||||
|
||||
protected:
|
||||
/// @brief Constructor.
|
||||
///
|
||||
reporter();
|
||||
|
||||
/// @brief Copy-construction is disabled.
|
||||
///
|
||||
reporter(reporter const&) = delete;
|
||||
|
||||
/// @brief Move-construction is disabled.
|
||||
///
|
||||
reporter(reporter&&) = delete;
|
||||
|
||||
/// @brief Log test suite setup execution.
|
||||
///
|
||||
/// @param file The file in which the setup is defined.
|
||||
/// @param line The line on which the setup is defined.
|
||||
/// @param detail Extra details.
|
||||
///
|
||||
virtual
|
||||
void
|
||||
do_log_setup(string const& file, int line, string const& detail) = 0;
|
||||
|
||||
/// @brief Log test suite teardown execution.
|
||||
///
|
||||
/// @param file The file in which the teardown is defined.
|
||||
/// @param line The line on which the teardown is defined.
|
||||
/// @param detail Extra details.
|
||||
///
|
||||
virtual
|
||||
void
|
||||
do_log_teardown(string const& file, int line, string const& detail) = 0;
|
||||
|
||||
/// @brief Log test case execution.
|
||||
///
|
||||
/// @param name The name of the test case.
|
||||
/// @param description A description of the test case.
|
||||
/// @param file The file in which the test case is defined.
|
||||
/// @param line The line on which the test case is defined.
|
||||
/// @param detail Extra details.
|
||||
///
|
||||
virtual
|
||||
void
|
||||
do_log_test_case(string const& name,
|
||||
string const& description,
|
||||
string const& file,
|
||||
int line,
|
||||
string const& detail) = 0;
|
||||
|
||||
/// @brief Log test case failure.
|
||||
///
|
||||
/// @param message A message describing the failure.
|
||||
/// @param file The file in which the failure occurred.
|
||||
/// @param line The line on which the error occurred.
|
||||
/// @param detail Extra details.
|
||||
///
|
||||
virtual
|
||||
void
|
||||
do_log_failure(string const& message,
|
||||
string const& file,
|
||||
int line,
|
||||
string const& detail) = 0;
|
||||
|
||||
/// @brief Log test suite summary.
|
||||
///
|
||||
/// @param total The total number of tests.
|
||||
/// @param ignored The total number of ignored tests.
|
||||
/// @param pass The total number of passed tests.
|
||||
/// @param fail The total number of failed tests.
|
||||
///
|
||||
virtual
|
||||
void
|
||||
do_log_summary(uint16_t total,
|
||||
uint16_t ignored,
|
||||
uint16_t pass,
|
||||
uint16_t fail) = 0;
|
||||
|
||||
/// @brief Copy-construction is disabled.
|
||||
///
|
||||
reporter& operator=(reporter const&) = delete;
|
||||
|
||||
/// @brief Move-construction is disabled.
|
||||
///
|
||||
reporter& operator=(reporter&&) = delete;
|
||||
|
||||
};
|
||||
|
||||
class reporter::proxy
|
||||
{
|
||||
friend reporter;
|
||||
|
||||
public:
|
||||
/// @brief Destructor.
|
||||
///
|
||||
~proxy() noexcept(false);
|
||||
|
||||
template<typename U>
|
||||
proxy&
|
||||
operator<<(U const& other)
|
||||
{
|
||||
_detail << std::boolalpha << other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param cb Function call from destructor.
|
||||
///
|
||||
explicit
|
||||
proxy(function<void(string const&)> cb);
|
||||
|
||||
/// @brief Copy-construction is disabled.
|
||||
///
|
||||
proxy(proxy const&) = delete;
|
||||
|
||||
/// @brief Move-construction is disabled.
|
||||
///
|
||||
proxy(proxy&&) = delete;
|
||||
|
||||
/// @brief Copy-assignment is disabled.
|
||||
///
|
||||
proxy& operator=(proxy const&) = delete;
|
||||
|
||||
/// @brief Move-assignment is disabled.
|
||||
///
|
||||
proxy& operator=(proxy&&) = delete;
|
||||
|
||||
private:
|
||||
function<void(string const&)> _cb;
|
||||
stringstream _detail;
|
||||
|
||||
};
|
||||
|
||||
/// @brief Default ostream-based reporter.
|
||||
///
|
||||
class ostream_reporter
|
||||
: public reporter
|
||||
{
|
||||
public:
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param os The output stream.
|
||||
/// @param show_file Include file information in output.
|
||||
/// @param show_line Include line information in output.
|
||||
///
|
||||
ostream_reporter(ostream& os, bool show_file, bool show_line);
|
||||
|
||||
/// @brief Copy-construction is disabled.
|
||||
///
|
||||
ostream_reporter(ostream_reporter const&) = delete;
|
||||
|
||||
/// @brief Move-construction is disabled.
|
||||
///
|
||||
ostream_reporter(ostream_reporter&&) = delete;
|
||||
|
||||
/// @brief Destructor.
|
||||
///
|
||||
~ostream_reporter() noexcept override;
|
||||
|
||||
/// @brief Get a reference to the associated output stream.
|
||||
///
|
||||
ostream&
|
||||
output();
|
||||
|
||||
/// @brief Copy-assignment is disabled.
|
||||
///
|
||||
ostream_reporter& operator=(ostream_reporter const&) = delete;
|
||||
|
||||
/// @brief Move-assignment is disabled.
|
||||
///
|
||||
ostream_reporter& operator=(ostream_reporter&&) = delete;
|
||||
|
||||
protected:
|
||||
void
|
||||
do_log_setup(string const& file,
|
||||
int line,
|
||||
string const& detail) override;
|
||||
|
||||
void
|
||||
do_log_teardown(string const& file,
|
||||
int line,
|
||||
string const& detail) override;
|
||||
|
||||
void
|
||||
do_log_test_case(string const& name,
|
||||
string const& description,
|
||||
string const& file,
|
||||
int line,
|
||||
string const& detail) override;
|
||||
|
||||
void
|
||||
do_log_failure(string const& message,
|
||||
string const& file,
|
||||
int line,
|
||||
string const& detail) override;
|
||||
|
||||
void
|
||||
do_log_summary(uint16_t total,
|
||||
uint16_t ignored,
|
||||
uint16_t pass,
|
||||
uint16_t fail) override;
|
||||
|
||||
private:
|
||||
ostream& _os;
|
||||
bool _show_file{};
|
||||
bool _show_line{};
|
||||
|
||||
};
|
||||
|
||||
/// @brief Let there be silence.
|
||||
///
|
||||
class quiet_reporter
|
||||
: public reporter
|
||||
{
|
||||
public:
|
||||
/// @brief Constructor.
|
||||
///
|
||||
quiet_reporter();
|
||||
|
||||
/// @brief Copy-construction is disabled.
|
||||
///
|
||||
quiet_reporter(quiet_reporter const&) = delete;
|
||||
|
||||
/// @brief Move-construction is disabled.
|
||||
///
|
||||
quiet_reporter(quiet_reporter&&) = delete;
|
||||
|
||||
/// @brief Destructor.
|
||||
///
|
||||
~quiet_reporter() noexcept override;
|
||||
|
||||
/// @brief Copy-assignment is disabled.
|
||||
///
|
||||
quiet_reporter& operator=(quiet_reporter const&) = delete;
|
||||
|
||||
/// @brief Move-assignment is disabled.
|
||||
///
|
||||
quiet_reporter& operator=(quiet_reporter&&) = delete;
|
||||
|
||||
protected:
|
||||
void
|
||||
do_log_setup(string const& file,
|
||||
int line,
|
||||
string const& detail) override;
|
||||
|
||||
void
|
||||
do_log_teardown(string const& file,
|
||||
int line,
|
||||
string const& detail) override;
|
||||
|
||||
void
|
||||
do_log_test_case(string const& name,
|
||||
string const& description,
|
||||
string const& file,
|
||||
int line,
|
||||
string const& detail) override;
|
||||
|
||||
void
|
||||
do_log_failure(string const& message,
|
||||
string const& file,
|
||||
int line,
|
||||
string const& detail) override;
|
||||
|
||||
void
|
||||
do_log_summary(uint16_t total,
|
||||
uint16_t ignored,
|
||||
uint16_t pass,
|
||||
uint16_t fail) override;
|
||||
};
|
||||
|
||||
} // namespace bitshift::validate
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
#include <bitshift/validate/setup.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
setup::
|
||||
setup(string file, int line, function<void()> func)
|
||||
: _file{std::move(file)}
|
||||
, _line{line}
|
||||
, _func{func}
|
||||
{}
|
||||
|
||||
setup::
|
||||
~setup() noexcept
|
||||
{}
|
||||
|
||||
string const&
|
||||
setup::
|
||||
file() const
|
||||
{
|
||||
return _file;
|
||||
}
|
||||
|
||||
int
|
||||
setup::
|
||||
line() const
|
||||
{
|
||||
return _line;
|
||||
}
|
||||
|
||||
setup*
|
||||
setup::
|
||||
next()
|
||||
{
|
||||
return intrusive_list<setup>::next();
|
||||
}
|
||||
|
||||
setup*
|
||||
setup::
|
||||
previous()
|
||||
{
|
||||
return intrusive_list<setup>::previous();
|
||||
}
|
||||
|
||||
void
|
||||
setup::
|
||||
run()
|
||||
{
|
||||
_func();
|
||||
}
|
||||
|
||||
setup*
|
||||
setup::
|
||||
first()
|
||||
{
|
||||
return intrusive_list<setup>::first();
|
||||
}
|
||||
|
||||
setup*
|
||||
setup::
|
||||
last()
|
||||
{
|
||||
return intrusive_list<setup>::last();
|
||||
}
|
||||
|
||||
} // namespace bitshift::validate
|
||||
@@ -0,0 +1,91 @@
|
||||
#ifndef bitshift__validate__setup_hxx_
|
||||
#define bitshift__validate__setup_hxx_
|
||||
|
||||
#include <bitshift/validate/types.hxx>
|
||||
|
||||
#include <bitshift/validate/intrusive-list.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
class setup
|
||||
: intrusive_list<setup>
|
||||
{
|
||||
friend intrusive_list<setup>;
|
||||
|
||||
public:
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param file The file in which the setup function is defined.
|
||||
/// @param line The line on which the setup function is defined.
|
||||
/// @param func The setup function.
|
||||
///
|
||||
setup(string file, int line, function<void()> func);
|
||||
|
||||
/// @brief Copy-construction is disabled.
|
||||
///
|
||||
setup(setup const&) = delete;
|
||||
|
||||
/// @brief Move-construction is disabled.
|
||||
///
|
||||
setup(setup&&) = delete;
|
||||
|
||||
/// @brief Destructor.
|
||||
///
|
||||
~setup() noexcept;
|
||||
|
||||
/// @brief Get the file in which the setup function is defined.
|
||||
///
|
||||
string const&
|
||||
file() const;
|
||||
|
||||
/// @brief Get the line on which the setup function is defined.
|
||||
///
|
||||
int
|
||||
line() const;
|
||||
|
||||
/// @brief Get a pointer to the next setup function.
|
||||
///
|
||||
setup*
|
||||
next();
|
||||
|
||||
/// @brief Get a pointer to the previous setup function.
|
||||
///
|
||||
setup*
|
||||
previous();
|
||||
|
||||
/// @brief Run the setup function.
|
||||
///
|
||||
void
|
||||
run();
|
||||
|
||||
/// @brief Copy-construction is disabled.
|
||||
///
|
||||
setup& operator=(setup const&) = delete;
|
||||
|
||||
/// @brief Move-construction is disabled.
|
||||
///
|
||||
setup& operator=(setup&&) = delete;
|
||||
|
||||
/// @brief Get a pointer to the first setup function.
|
||||
///
|
||||
static
|
||||
setup*
|
||||
first();
|
||||
|
||||
/// @brief Get a pointer to the last setup function.
|
||||
///
|
||||
static
|
||||
setup*
|
||||
last();
|
||||
|
||||
private:
|
||||
string _file;
|
||||
int _line{};
|
||||
function<void()> _func;
|
||||
|
||||
};
|
||||
|
||||
} // namespace bitshift::validate
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
#include <bitshift/validate/teardown.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
teardown::
|
||||
teardown(string file, int line, function<void()> func)
|
||||
: _file{std::move(file)}
|
||||
, _line{line}
|
||||
, _func{func}
|
||||
{}
|
||||
|
||||
teardown::
|
||||
~teardown() noexcept
|
||||
{}
|
||||
|
||||
string const&
|
||||
teardown::
|
||||
file() const
|
||||
{
|
||||
return _file;
|
||||
}
|
||||
|
||||
int
|
||||
teardown::
|
||||
line() const
|
||||
{
|
||||
return _line;
|
||||
}
|
||||
|
||||
teardown*
|
||||
teardown::
|
||||
next()
|
||||
{
|
||||
return intrusive_list<teardown>::next();
|
||||
}
|
||||
|
||||
teardown*
|
||||
teardown::
|
||||
previous()
|
||||
{
|
||||
return intrusive_list<teardown>::previous();
|
||||
}
|
||||
|
||||
void
|
||||
teardown::
|
||||
run()
|
||||
{
|
||||
_func();
|
||||
}
|
||||
|
||||
teardown*
|
||||
teardown::
|
||||
first()
|
||||
{
|
||||
return intrusive_list<teardown>::first();
|
||||
}
|
||||
|
||||
teardown*
|
||||
teardown::
|
||||
last()
|
||||
{
|
||||
return intrusive_list<teardown>::last();
|
||||
}
|
||||
|
||||
} // namespace bitshift::validate
|
||||
@@ -0,0 +1,91 @@
|
||||
#ifndef bitshift__validate__teardown_hxx_
|
||||
#define bitshift__validate__teardown_hxx_
|
||||
|
||||
#include <bitshift/validate/types.hxx>
|
||||
|
||||
#include <bitshift/validate/intrusive-list.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
class teardown
|
||||
: intrusive_list<teardown>
|
||||
{
|
||||
friend intrusive_list<teardown>;
|
||||
|
||||
public:
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param file The file in which the teardown function is defined.
|
||||
/// @param line The line on which the teardown function is defined.
|
||||
/// @param func The teardown function.
|
||||
///
|
||||
teardown(string file, int line, function<void()> func);
|
||||
|
||||
/// @brief Copy-construction is disabled.
|
||||
///
|
||||
teardown(teardown const&) = delete;
|
||||
|
||||
/// @brief Move-construction is disabled.
|
||||
///
|
||||
teardown(teardown&&) = delete;
|
||||
|
||||
/// @brief Destructor.
|
||||
///
|
||||
~teardown() noexcept;
|
||||
|
||||
/// @brief Get the file in which the teardown function is defined.
|
||||
///
|
||||
string const&
|
||||
file() const;
|
||||
|
||||
/// @brief Get the line on which the teardown function is defined.
|
||||
///
|
||||
int
|
||||
line() const;
|
||||
|
||||
/// @brief Get a pointer to the next teardown function.
|
||||
///
|
||||
teardown*
|
||||
next();
|
||||
|
||||
/// @brief Get a pointer to the previous teardown function.
|
||||
///
|
||||
teardown*
|
||||
previous();
|
||||
|
||||
/// @brief Run the teardown function.
|
||||
///
|
||||
void
|
||||
run();
|
||||
|
||||
/// @brief Copy-construction is disabled.
|
||||
///
|
||||
teardown& operator=(teardown const&) = delete;
|
||||
|
||||
/// @brief Move-construction is disabled.
|
||||
///
|
||||
teardown& operator=(teardown&&) = delete;
|
||||
|
||||
/// @brief Get a pointer to the first teardown function.
|
||||
///
|
||||
static
|
||||
teardown*
|
||||
first();
|
||||
|
||||
/// @brief Get a pointer to the last teardown function.
|
||||
///
|
||||
static
|
||||
teardown*
|
||||
last();
|
||||
|
||||
private:
|
||||
string _file;
|
||||
int _line{};
|
||||
function<void()> _func;
|
||||
|
||||
};
|
||||
|
||||
} // namespace bitshift::validate
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,86 @@
|
||||
#include <bitshift/validate/test-case.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
test_case::
|
||||
test_case(string name,
|
||||
string description,
|
||||
string file,
|
||||
int line,
|
||||
function<void()> func)
|
||||
: _name {std::move(name)}
|
||||
, _description{std::move(description)}
|
||||
, _file {std::move(file)}
|
||||
, _line {line}
|
||||
, _func {func}
|
||||
{}
|
||||
|
||||
test_case::
|
||||
~test_case() noexcept
|
||||
{}
|
||||
|
||||
string const&
|
||||
test_case::
|
||||
name() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
string const&
|
||||
test_case::
|
||||
description() const
|
||||
{
|
||||
return _description;
|
||||
}
|
||||
|
||||
string const&
|
||||
test_case::
|
||||
file() const
|
||||
{
|
||||
return _file;
|
||||
}
|
||||
|
||||
int
|
||||
test_case::
|
||||
line() const
|
||||
{
|
||||
return _line;
|
||||
}
|
||||
|
||||
test_case*
|
||||
test_case::
|
||||
next()
|
||||
{
|
||||
return intrusive_list<test_case>::next();
|
||||
}
|
||||
|
||||
test_case*
|
||||
test_case::
|
||||
previous()
|
||||
{
|
||||
return intrusive_list<test_case>::previous();
|
||||
}
|
||||
|
||||
void
|
||||
test_case::
|
||||
run()
|
||||
{
|
||||
_func();
|
||||
}
|
||||
|
||||
test_case*
|
||||
test_case::
|
||||
first()
|
||||
{
|
||||
return intrusive_list<test_case>::first();
|
||||
}
|
||||
|
||||
test_case*
|
||||
test_case::
|
||||
last()
|
||||
{
|
||||
return intrusive_list<test_case>::last();
|
||||
}
|
||||
|
||||
} // namespace bitshift::validate
|
||||
@@ -0,0 +1,109 @@
|
||||
#ifndef bitshift__validate__test_case_hxx_
|
||||
#define bitshift__validate__test_case_hxx_
|
||||
|
||||
#include <bitshift/validate/types.hxx>
|
||||
|
||||
#include <bitshift/validate/intrusive-list.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
class test_case
|
||||
: intrusive_list<test_case>
|
||||
{
|
||||
friend intrusive_list<test_case>;
|
||||
|
||||
public:
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param name The name of the test case.
|
||||
/// @param description A description of the test case.
|
||||
/// @param file The file in which the test case function is defined.
|
||||
/// @param line The line on which the test case function is defined.
|
||||
/// @param func The test case function.
|
||||
///
|
||||
test_case(string name,
|
||||
string description,
|
||||
string file,
|
||||
int line,
|
||||
function<void()> func);
|
||||
|
||||
/// @brief Copy-construction is disabled.
|
||||
///
|
||||
test_case(test_case const&) = delete;
|
||||
|
||||
/// @brief Move-construction is disabled.
|
||||
///
|
||||
test_case(test_case&&) = delete;
|
||||
|
||||
/// @brief Destructor.
|
||||
///
|
||||
~test_case() noexcept;
|
||||
|
||||
/// @brief Get the name of the test case.
|
||||
///
|
||||
string const&
|
||||
name() const;
|
||||
|
||||
/// @brief Get the description of the test case.
|
||||
///
|
||||
string const&
|
||||
description() const;
|
||||
|
||||
/// @brief Get the file in which the test case function is defined.
|
||||
///
|
||||
string const&
|
||||
file() const;
|
||||
|
||||
/// @brief Get the line on which the test case function is defined.
|
||||
///
|
||||
int
|
||||
line() const;
|
||||
|
||||
/// @brief Get a pointer to the next test case function.
|
||||
///
|
||||
test_case*
|
||||
next();
|
||||
|
||||
/// @brief Get a pointer to the previous test case function.
|
||||
///
|
||||
test_case*
|
||||
previous();
|
||||
|
||||
/// @brief Run the test case function.
|
||||
///
|
||||
void
|
||||
run();
|
||||
|
||||
/// @brief Copy-construction is disabled.
|
||||
///
|
||||
test_case& operator=(test_case const&) = delete;
|
||||
|
||||
/// @brief Move-construction is disabled.
|
||||
///
|
||||
test_case& operator=(test_case&&) = delete;
|
||||
|
||||
/// @brief Get a pointer to the first test case function.
|
||||
///
|
||||
static
|
||||
test_case*
|
||||
first();
|
||||
|
||||
/// @brief Get a pointer to the last test case function.
|
||||
///
|
||||
static
|
||||
test_case*
|
||||
last();
|
||||
|
||||
private:
|
||||
string _name;
|
||||
string _description;
|
||||
string _file;
|
||||
int _line{};
|
||||
function<void()> _func;
|
||||
|
||||
};
|
||||
|
||||
} // namespace bitshift::validate
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef bitshift__validate__traits_hxx_
|
||||
#define bitshift__validate__traits_hxx_
|
||||
|
||||
#include <bitshift/validate/types.hxx>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
namespace traits
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
concept has_output_operator = requires(ostream& os, T const& v)
|
||||
{
|
||||
{ os << v };
|
||||
|
||||
};
|
||||
|
||||
} // namespace traits
|
||||
|
||||
} // namespace bitshift::validate
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
#ifndef bitshift__validate__types_hxx_
|
||||
#define bitshift__validate__types_hxx_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <source_location>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace bitshift::validate
|
||||
{
|
||||
|
||||
namespace types
|
||||
{
|
||||
|
||||
using std::size_t;
|
||||
|
||||
using std::int8_t;
|
||||
using std::int16_t;
|
||||
using std::int32_t;
|
||||
using std::int64_t;
|
||||
using std::uint8_t;
|
||||
using std::uint16_t;
|
||||
using std::uint32_t;
|
||||
using std::uint64_t;
|
||||
|
||||
using std::source_location;
|
||||
|
||||
using std::istream;
|
||||
using std::ostream;
|
||||
using std::iostream;
|
||||
|
||||
using std::stringstream;
|
||||
|
||||
using std::cin;
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
|
||||
using std::variant;
|
||||
|
||||
using std::list;
|
||||
using std::vector;
|
||||
|
||||
using std::string;
|
||||
using strings = vector<string>;
|
||||
|
||||
using std::function;
|
||||
|
||||
using std::exception;
|
||||
using std::runtime_error;
|
||||
|
||||
} // namespace types
|
||||
|
||||
using namespace types;
|
||||
|
||||
} // namespace bitshift::validate
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef bitshift__validate__validate_hxx_
|
||||
#define bitshift__validate__validate_hxx_
|
||||
|
||||
#include <bitshift/validate/macro.hxx>
|
||||
#include <bitshift/validate/main.hxx>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef bitshift__validate__version_hxx_
|
||||
#define bitshift__validate__version_hxx_
|
||||
|
||||
// The numeric version format is AAAAABBBBBCCCCCDDDE where:
|
||||
//
|
||||
// AAAAA - major version number
|
||||
// BBBBB - minor version number
|
||||
// CCCCC - bugfix version number
|
||||
// DDD - alpha / beta (DDD + 500) version number
|
||||
// E - final (0) / snapshot (1)
|
||||
//
|
||||
// When DDDE is not 0, 1 is subtracted from AAAAABBBBBCCCCC. For example:
|
||||
//
|
||||
// Version AAAAABBBBBCCCCCDDDE
|
||||
//
|
||||
// 0.1.0 0000000001000000000
|
||||
// 0.1.2 0000000001000020000
|
||||
// 1.2.3 0000100002000030000
|
||||
// 2.2.0-a.1 0000200001999990010
|
||||
// 3.0.0-b.2 0000299999999995020
|
||||
// 2.2.0-a.1.z 0000200001999990011
|
||||
//
|
||||
#define BITSHIFT_VALIDATE_VERSION $bitshift_validate.version.project_number$ULL
|
||||
#define BITSHIFT_VALIDATE_VERSION_STR "$bitshift_validate.version.project$"
|
||||
#define BITSHIFT_VALIDATE_VERSION_ID "$bitshift_validate.version.project_id$"
|
||||
#define BITSHIFT_VALIDATE_VERSION_FULL "$bitshift_validate.version$"
|
||||
|
||||
#define BITSHIFT_VALIDATE_VERSION_MAJOR $bitshift_validate.version.major$
|
||||
#define BITSHIFT_VALIDATE_VERSION_MINOR $bitshift_validate.version.minor$
|
||||
#define BITSHIFT_VALIDATE_VERSION_PATCH $bitshift_validate.version.patch$
|
||||
|
||||
#define BITSHIFT_VALIDATE_PRE_RELEASE $bitshift_validate.version.pre_release$
|
||||
|
||||
#define BITSHIFT_VALIDATE_SNAPSHOT_SN $bitshift_validate.version.snapshot_sn$ULL
|
||||
#define BITSHIFT_VALIDATE_SNAPSHOT_ID "$bitshift_validate.version.snapshot_id$"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,4 @@
|
||||
/config.build
|
||||
/root/
|
||||
/bootstrap/
|
||||
build/
|
||||
@@ -0,0 +1,7 @@
|
||||
project = bitshift-validate
|
||||
|
||||
using version
|
||||
using config
|
||||
using test
|
||||
using install
|
||||
using dist
|
||||
@@ -0,0 +1,6 @@
|
||||
$out_root/
|
||||
{
|
||||
include bitshift/validate/
|
||||
}
|
||||
|
||||
export $out_root/bitshift/validate/lib{validate}
|
||||
@@ -0,0 +1,14 @@
|
||||
cxx.internal.scope = current
|
||||
|
||||
cxx.std = latest
|
||||
|
||||
using cxx
|
||||
|
||||
hxx{*}: extension = hxx
|
||||
ixx{*}: extension = ixx
|
||||
txx{*}: extension = txx
|
||||
cxx{*}: extension = cxx
|
||||
|
||||
# The test target for cross-testing (running tests under Wine, etc).
|
||||
#
|
||||
test.target = $cxx.target
|
||||
@@ -0,0 +1,32 @@
|
||||
./: {bitshift/ tests/} doc{README.md} legal{LICENSE} manifest
|
||||
|
||||
# Don't install tests.
|
||||
#
|
||||
tests/: install = false
|
||||
|
||||
define doxyfile: file
|
||||
doxyfile{*}: extension = ""
|
||||
doxyfile{*}: in.substitution = lax
|
||||
|
||||
doxyfile{Doxyfile}: in{Doxyfile} $src_root/manifest
|
||||
{
|
||||
PROJECT_BRIEF = "BitShift Validate API Reference Documentation"
|
||||
OUTPUT_DIRECTORY = "$out_root/docs"
|
||||
INTERNAL = "NO"
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_GAMMA = 140
|
||||
}
|
||||
|
||||
./: fsdir{$out_root/docs}
|
||||
|
||||
fsdir{$out_root/docs}:
|
||||
% clean
|
||||
{{
|
||||
rm -rf $out_root/docs
|
||||
}}
|
||||
|
||||
alias{docs}: doxyfile{Doxyfile} fsdir{$out_root/docs}
|
||||
{{
|
||||
diag doxygen $path($<[0])
|
||||
doxygen $path($<[0])
|
||||
}}
|
||||
@@ -0,0 +1,2 @@
|
||||
@page bitshift-license BitShift License
|
||||
@includedoc LICENSE
|
||||
@@ -0,0 +1,27 @@
|
||||
@mainpage BitShift Validate
|
||||
|
||||
# Introduction
|
||||
|
||||
Welcome to the BitShift Validate API Reference documentation.
|
||||
|
||||
Purpose
|
||||
-------
|
||||
|
||||
This documentation aims to provide reference material for the BitShift Validate
|
||||
unit testing library.
|
||||
|
||||
See the @ref readme for a quick introduction on how to import and use BitShift
|
||||
Validate in your application.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
This documentation is released under the CC BY-NC-SA 4.0 license. See
|
||||
[creativecommons.org][cc-by-nc-sa] for license information and the legal
|
||||
details.
|
||||
|
||||
See @ref bitshift-license for source code license information.
|
||||
|
||||
[made-with-love-badge]: https://img.shields.io/badge/Made_with_%E2%9D%A4%EF%B8%8F_by-The%20BitShift%20Contributors-red
|
||||
[README]: README.md
|
||||
[cc-by-nc-sa]: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
@@ -0,0 +1,2 @@
|
||||
@page readme README
|
||||
@includedoc README.md
|
||||
@@ -0,0 +1,12 @@
|
||||
: 1
|
||||
name: bitshift-validate
|
||||
version: 0.1.0-a.0.z
|
||||
type: lib
|
||||
language: c++
|
||||
summary: bitshift-validate C++ unit-testing library
|
||||
license: BSD-2-Clause
|
||||
description-file: README.md
|
||||
url: https://bitshift.helloryan.se/validate/
|
||||
email: ryan@helloryan.se
|
||||
depends: * build2 >= 0.18.0
|
||||
depends: * bpkg >= 0.18.0
|
||||
@@ -0,0 +1,2 @@
|
||||
: 1
|
||||
summary: bitshift-validate project repository
|
||||
@@ -0,0 +1,8 @@
|
||||
# Test executables.
|
||||
#
|
||||
driver
|
||||
|
||||
# Testscript output directories (can be symlinks).
|
||||
#
|
||||
test
|
||||
test-*
|
||||
@@ -0,0 +1,4 @@
|
||||
/config.build
|
||||
/root/
|
||||
/bootstrap/
|
||||
build/
|
||||
@@ -0,0 +1,6 @@
|
||||
project = # Unnamed tests subproject.
|
||||
|
||||
using version
|
||||
using config
|
||||
using test
|
||||
using dist
|
||||
@@ -0,0 +1,16 @@
|
||||
cxx.std = latest
|
||||
|
||||
using cxx
|
||||
|
||||
hxx{*}: extension = hxx
|
||||
ixx{*}: extension = ixx
|
||||
txx{*}: extension = txx
|
||||
cxx{*}: extension = cxx
|
||||
|
||||
# Every exe{} in this subproject is by default a test.
|
||||
#
|
||||
exe{*}: test = true
|
||||
|
||||
# The test target for cross-testing (running tests under Wine, etc).
|
||||
#
|
||||
test.target = $cxx.target
|
||||
@@ -0,0 +1 @@
|
||||
./: {*/ -build/}
|
||||
@@ -0,0 +1,4 @@
|
||||
libs =
|
||||
import libs = bitshift-validate%lib{validate}
|
||||
|
||||
./: exe{driver}: {hxx ixx txx cxx}{**} $libs
|
||||
@@ -0,0 +1,21 @@
|
||||
#include <bitshift/validate/validate.hxx>
|
||||
|
||||
BV_TEST(sanity, "basic sanity check")
|
||||
{
|
||||
BV_ASSERT_TRUE(true);
|
||||
BV_ASSERT_FALSE(false);
|
||||
BV_ASSERT_NULLPTR(nullptr);
|
||||
BV_ASSERT_EQUAL(1, 1);
|
||||
BV_ASSERT_NOT_EQUAL(0, 1);
|
||||
}
|
||||
|
||||
BV_TEST(ignored, "ignored test")
|
||||
{
|
||||
BV_IGNORE;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
return bitshift::validate::main(argc, argv);
|
||||
}
|
||||
Reference in New Issue
Block a user