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