Hello libcode-validation
This commit is contained in:
commit
2601654936
17
.editorconfig
Normal file
17
.editorconfig
Normal file
@ -0,0 +1,17 @@
|
||||
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
|
||||
|
||||
[*.yaml]
|
||||
indent_size = 2
|
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
* text=auto
|
20
.gitea/workflows/on-push.yaml
Normal file
20
.gitea/workflows/on-push.yaml
Normal file
@ -0,0 +1,20 @@
|
||||
name: on-push
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
runs-on: linux
|
||||
container: code.helloryan.se/infra/buildenv/cxx-amd64-fedora-40:latest
|
||||
volumes:
|
||||
- /build
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Initialize
|
||||
run: |
|
||||
bpkg create -d /build cc config.cc.coptions="-Wall -Werror"
|
||||
bdep init -A /build
|
||||
- name: Build
|
||||
run: b
|
||||
- name: Test
|
||||
run: b test
|
31
.gitignore
vendored
Normal file
31
.gitignore
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
.bdep/
|
||||
|
||||
# Local default options files.
|
||||
#
|
||||
.build2/local/
|
||||
|
||||
# Compiler/linker output.
|
||||
#
|
||||
*.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
|
31
LICENSE
Normal file
31
LICENSE
Normal file
@ -0,0 +1,31 @@
|
||||
Copyright © 2024 Ryan. All rights reserved.
|
||||
|
||||
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.
|
||||
|
||||
3. All advertising materials mentioning features or use of this software must
|
||||
display the following acknowledgement:
|
||||
|
||||
This product includes software developed by Ryan, http://helloryan.se/.
|
||||
|
||||
4. Neither the name(s) of the copyright holder(s) nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER "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 COPYRIGHT HOLDER 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.
|
21
README.md
Normal file
21
README.md
Normal file
@ -0,0 +1,21 @@
|
||||
# libcode-validation
|
||||
|
||||
![Build status](https://code.helloryan.se/code/libcode-validation/actions/workflows/on-push.yaml/badge.svg)
|
||||
|
||||
## Requirements
|
||||
|
||||
None, other than a modern C++-compiler.
|
||||
|
||||
## Building
|
||||
|
||||
See the wiki, https://code.helloryan.se/code/wiki/wiki/Build-Instructions, for
|
||||
build instructions.
|
||||
|
||||
## Contact
|
||||
|
||||
Please report bugs and issues by sending an e-mail to: ryan@helloryan.se.
|
||||
|
||||
## Contributing
|
||||
|
||||
Please send an e-mail to ryan@helloryan.se to request an account and
|
||||
write-access to the libcode-validation repository.
|
4
build/.gitignore
vendored
Normal file
4
build/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/config.build
|
||||
/root/
|
||||
/bootstrap/
|
||||
build/
|
7
build/bootstrap.build
Normal file
7
build/bootstrap.build
Normal file
@ -0,0 +1,7 @@
|
||||
project = libcode-validation
|
||||
|
||||
using version
|
||||
using config
|
||||
using test
|
||||
using install
|
||||
using dist
|
6
build/export.build
Normal file
6
build/export.build
Normal file
@ -0,0 +1,6 @@
|
||||
$out_root/
|
||||
{
|
||||
include code/validation/
|
||||
}
|
||||
|
||||
export $out_root/code/validation/$import.target
|
16
build/root.build
Normal file
16
build/root.build
Normal file
@ -0,0 +1,16 @@
|
||||
# Uncomment to suppress warnings coming from external libraries.
|
||||
#
|
||||
#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
|
5
buildfile
Normal file
5
buildfile
Normal file
@ -0,0 +1,5 @@
|
||||
./: {code/ tests/} doc{README.md} legal{LICENSE} manifest
|
||||
|
||||
# Don't install tests.
|
||||
#
|
||||
tests/: install = false
|
9
code/validation/.gitignore
vendored
Normal file
9
code/validation/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
# Generated version header.
|
||||
#
|
||||
version.hxx
|
||||
|
||||
# Unit test executables and Testscript output directories
|
||||
# (can be symlinks).
|
||||
#
|
||||
*.test
|
||||
test-*.test
|
51
code/validation/assert.hxx
Normal file
51
code/validation/assert.hxx
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef code__validation__assert_hxx_
|
||||
#define code__validation__assert_hxx_
|
||||
|
||||
#include <code/validation/except.hxx>
|
||||
#include <code/validation/traits.hxx>
|
||||
|
||||
#include <cstdint>
|
||||
#include <source_location>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace code::validation::Assert
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
assert_true(T const&,
|
||||
std::string,
|
||||
std::source_location const& = std::source_location::current());
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
assert_false(T const&,
|
||||
std::string,
|
||||
std::source_location const& = std::source_location::current());
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
assert_null(T const&,
|
||||
std::string,
|
||||
std::source_location const& = std::source_location::current());
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
assert_not_null(T const&,
|
||||
std::string,
|
||||
std::source_location const& = std::source_location::current());
|
||||
|
||||
template<typename T1, typename T2 = T1>
|
||||
void
|
||||
assert_equal(T1 const&,
|
||||
T2 const&,
|
||||
std::string,
|
||||
std::string,
|
||||
std::source_location const& = std::source_location::current());
|
||||
|
||||
} // namespace code::validation::Assert
|
||||
|
||||
#include <code/validation/assert.txx>
|
||||
|
||||
#endif
|
210
code/validation/assert.txx
Normal file
210
code/validation/assert.txx
Normal file
@ -0,0 +1,210 @@
|
||||
namespace code::validation::Assert
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class Unary_expression_failure
|
||||
{
|
||||
public:
|
||||
Unary_expression_failure(std::string message,
|
||||
std::string file,
|
||||
std::uint32_t line,
|
||||
std::string expr,
|
||||
std::string val)
|
||||
: message_{std::move(message)},
|
||||
file_{std::move(file)},
|
||||
line_{line},
|
||||
expr_{std::move(expr)},
|
||||
val_{std::move(val)}
|
||||
{}
|
||||
|
||||
void
|
||||
print(std::ostream& o) const
|
||||
{
|
||||
o << " " << message_ << '\n';
|
||||
o << " source: " << file_ << ':' << line_ << ":\n";
|
||||
o << " expression: " << expr_ << '\n';
|
||||
o << " value : " << val_ << '\n';
|
||||
}
|
||||
|
||||
private:
|
||||
std::string message_;
|
||||
std::string file_;
|
||||
std::uint32_t line_;
|
||||
std::string expr_;
|
||||
std::string val_;
|
||||
|
||||
};
|
||||
|
||||
class Binary_expression_failure
|
||||
{
|
||||
public:
|
||||
Binary_expression_failure(std::string message,
|
||||
std::string file,
|
||||
std::uint32_t line,
|
||||
std::string lhs_expr,
|
||||
std::string lhs_val,
|
||||
std::string rhs_expr,
|
||||
std::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)}
|
||||
{}
|
||||
|
||||
void
|
||||
print(std::ostream& o) const
|
||||
{
|
||||
o << " " << message_ << '\n';
|
||||
o << " source: " << file_ << ':' << line_ << ":\n";
|
||||
o << " left-hand expression : " << lhs_expr_ << '\n';
|
||||
o << " left-hand value : " << lhs_val_ << '\n';
|
||||
o << " right-hand expression: " << rhs_expr_ << '\n';
|
||||
o << " right-hand value : " << rhs_val_ << '\n';
|
||||
}
|
||||
|
||||
private:
|
||||
std::string message_;
|
||||
std::string file_;
|
||||
std::uint32_t line_;
|
||||
std::string lhs_expr_;
|
||||
std::string lhs_val_;
|
||||
std::string rhs_expr_;
|
||||
std::string rhs_val_;
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
assert_true(T const& value,
|
||||
std::string expr,
|
||||
std::source_location const& source)
|
||||
{
|
||||
if (value == true) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string expr_str;
|
||||
|
||||
if constexpr (has_output_operator<T>) {
|
||||
std::stringstream str;
|
||||
str << value;
|
||||
expr_str = str.str();
|
||||
}
|
||||
|
||||
throw Fail{
|
||||
Unary_expression_failure{
|
||||
"expected expression to be true; was false",
|
||||
source.file_name(),
|
||||
source.line(),
|
||||
std::move(expr),
|
||||
std::move(expr_str)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
assert_false(T const& value,
|
||||
std::string expr,
|
||||
std::source_location const& source)
|
||||
{
|
||||
if (value == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string expr_str;
|
||||
|
||||
if constexpr (has_output_operator<T>) {
|
||||
std::stringstream str;
|
||||
str << value;
|
||||
expr_str = str.str();
|
||||
}
|
||||
|
||||
throw Fail{
|
||||
Unary_expression_failure{
|
||||
"expected expression to be false; was true",
|
||||
source.file_name(),
|
||||
source.line(),
|
||||
std::move(expr),
|
||||
std::move(expr_str)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
assert_null(T const& value,
|
||||
std::string expr,
|
||||
std::source_location const& source)
|
||||
{
|
||||
if (value == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string expr_str;
|
||||
|
||||
if constexpr (has_output_operator<T>) {
|
||||
std::stringstream str;
|
||||
str << value;
|
||||
expr_str = str.str();
|
||||
}
|
||||
|
||||
throw Fail{
|
||||
Unary_expression_failure{
|
||||
"expected expression to be nullptr; was not",
|
||||
source.file_name(),
|
||||
source.line(),
|
||||
std::move(expr),
|
||||
std::move(expr_str)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
void
|
||||
assert_equal(T1 const& lhs,
|
||||
T2 const& rhs,
|
||||
std::string lhs_expr,
|
||||
std::string rhs_expr,
|
||||
std::source_location const& source)
|
||||
{
|
||||
if (lhs == rhs) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string lhs_val;
|
||||
std::string rhs_val;
|
||||
|
||||
if constexpr (has_output_operator<T1>) {
|
||||
std::stringstream str;
|
||||
str << lhs;
|
||||
lhs_val = str.str();
|
||||
}
|
||||
|
||||
if constexpr (has_output_operator<T2>) {
|
||||
std::stringstream str;
|
||||
str << rhs;
|
||||
rhs_val = str.str();
|
||||
}
|
||||
|
||||
throw Fail{
|
||||
Binary_expression_failure{
|
||||
"expected lhs to equal rhs; they did not",
|
||||
source.file_name(),
|
||||
source.line(),
|
||||
std::move(lhs_expr),
|
||||
std::move(lhs_val),
|
||||
std::move(rhs_expr),
|
||||
std::move(rhs_val)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace code::validation::Assert
|
62
code/validation/buildfile
Normal file
62
code/validation/buildfile
Normal file
@ -0,0 +1,62 @@
|
||||
intf_libs = # Interface dependencies.
|
||||
impl_libs = # Implementation dependencies.
|
||||
|
||||
./: lib{code-validation}: libul{code-validation}
|
||||
|
||||
libul{code-validation}: {hxx ixx txx cxx}{** -**.test... -version} \
|
||||
{hxx }{ version}
|
||||
|
||||
libul{code-validation}: $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{code-validation}: bin.whole = false
|
||||
}
|
||||
|
||||
hxx{version}: in{version} $src_root/manifest
|
||||
{
|
||||
dist = true
|
||||
clean = ($src_root != $out_root)
|
||||
}
|
||||
|
||||
# Build options.
|
||||
#
|
||||
cxx.poptions =+ "-I$out_root" "-I$src_root"
|
||||
|
||||
# Export options.
|
||||
#
|
||||
lib{code-validation}:
|
||||
{
|
||||
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{code-validation}: bin.lib.version = "-$version.project_id"
|
||||
else
|
||||
lib{code-validation}: bin.lib.version = "-$version.major.$version.minor"
|
||||
|
||||
# Install into the code/validation/ subdirectory of, say, /usr/include/
|
||||
# recreating subdirectories.
|
||||
#
|
||||
{hxx ixx txx}{*}:
|
||||
{
|
||||
install = include/code/validation/
|
||||
install.subdirs = true
|
||||
}
|
29
code/validation/except.hxx
Normal file
29
code/validation/except.hxx
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef code__validation__except_hxx_
|
||||
#define code__validation__except_hxx_
|
||||
|
||||
#include <code/validation/test-fail-extras.hxx>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
class Fail
|
||||
{
|
||||
public:
|
||||
Fail(Test_fail_extras extras)
|
||||
: extras_{std::move(extras)}
|
||||
{}
|
||||
|
||||
Test_fail_extras const&
|
||||
extras() const
|
||||
{
|
||||
return extras_;
|
||||
}
|
||||
|
||||
private:
|
||||
Test_fail_extras extras_;
|
||||
|
||||
};
|
||||
|
||||
} // namespace code::validation
|
||||
|
||||
#endif
|
118
code/validation/exec.cxx
Normal file
118
code/validation/exec.cxx
Normal file
@ -0,0 +1,118 @@
|
||||
#include <code/validation/exec.hxx>
|
||||
|
||||
#include <code/validation/except.hxx>
|
||||
#include <code/validation/setup.hxx>
|
||||
#include <code/validation/teardown.hxx>
|
||||
#include <code/validation/test-case.hxx>
|
||||
#include <code/validation/test-result.hxx>
|
||||
#include <code/validation/utility.hxx>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
static
|
||||
void
|
||||
exec_setup()
|
||||
{
|
||||
auto current = Setup::first();
|
||||
|
||||
if (!current) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
// fixme: report setup exceptions. fail entire unit test on exception.
|
||||
//
|
||||
current->run();
|
||||
current = current->next();
|
||||
} while (current && current != Setup::first());
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
exec_teardown()
|
||||
{
|
||||
auto current = Teardown::first();
|
||||
|
||||
if (!current) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
// fixme: report teardown exceptions. fail entire unit test on exception.
|
||||
//
|
||||
current->run();
|
||||
current = current->next();
|
||||
} while (current && current != Teardown::first());
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
exec_test_case(Test_summary& summary, Test_case& test_case)
|
||||
{
|
||||
try {
|
||||
Utility::Current<Test_case> current{&test_case};
|
||||
|
||||
exec_setup();
|
||||
|
||||
try {
|
||||
test_case.run();
|
||||
}
|
||||
catch (...) {
|
||||
exec_teardown();
|
||||
throw;
|
||||
}
|
||||
|
||||
exec_teardown();
|
||||
|
||||
summary.append({
|
||||
test_case.description(),
|
||||
test_case.file(),
|
||||
test_case.line(),
|
||||
"passed"
|
||||
});
|
||||
|
||||
summary.inc_pass();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Fail const& fail) {
|
||||
summary.append({
|
||||
test_case.description(),
|
||||
test_case.file(),
|
||||
test_case.line(),
|
||||
"failed",
|
||||
fail.extras()
|
||||
});
|
||||
|
||||
summary.inc_fail();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
exec(Test_summary& summary)
|
||||
{
|
||||
auto current = &Test_case::first();
|
||||
|
||||
if (!current) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool all_passed{true};
|
||||
|
||||
do {
|
||||
bool passed = exec_test_case(summary, *current);
|
||||
|
||||
if (!passed) {
|
||||
all_passed = false;
|
||||
}
|
||||
|
||||
current = ¤t->next();
|
||||
} while (current != &Test_case::first());
|
||||
|
||||
return all_passed;
|
||||
}
|
||||
|
||||
} // namespace code::validation
|
16
code/validation/exec.hxx
Normal file
16
code/validation/exec.hxx
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef code__validation__exec_hxx_
|
||||
#define code__validation__exec_hxx_
|
||||
|
||||
#include <code/validation/test-summary.hxx>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
bool
|
||||
exec(Test_summary& summary);
|
||||
|
||||
} // namespace code::validation
|
||||
|
||||
#endif
|
54
code/validation/macros.hxx
Normal file
54
code/validation/macros.hxx
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef code__validation__macros_hxx_
|
||||
#define code__validation__macros_hxx_
|
||||
|
||||
#include <code/validation/assert.hxx>
|
||||
#include <code/validation/setup.hxx>
|
||||
#include <code/validation/teardown.hxx>
|
||||
#include <code/validation/test-case.hxx>
|
||||
|
||||
#define VALIDATION_TEST_SETUP_2(file, line) \
|
||||
static void test_setup_func_##line(); \
|
||||
code::validation::Setup test_setup_##line(file, line, &test_setup_func_##line); \
|
||||
void test_setup_func_##line()
|
||||
|
||||
#define VALIDATION_TEST_SETUP_1(file, line) \
|
||||
VALIDATION_TEST_SETUP_2(file, line)
|
||||
|
||||
#define VALIDATION_TEST_SETUP \
|
||||
VALIDATION_TEST_SETUP_1(__FILE__, __LINE__)
|
||||
|
||||
#define VALIDATION_TEST_TEARDOWN_2(file, line) \
|
||||
static void test_teardown_func_##line(); \
|
||||
code::validation::Teardown test_teardown_##line(file, line, &test_teardown_func_##line); \
|
||||
void test_teardown_func_##line()
|
||||
|
||||
#define VALIDATION_TEST_TEARDOWN_1(file, line) \
|
||||
VALIDATION_TEST_TEARDOWN_2(file, line)
|
||||
|
||||
#define VALIDATION_TEST_TEARDOWN \
|
||||
VALIDATION_TEST_TEARDOWN_1(__FILE__, __LINE__)
|
||||
|
||||
#define VALIDATION_TEST_2(name, file, line) \
|
||||
void test_func_##line(); \
|
||||
code::validation::Test_case test_##line(#name, (file), (line), &test_func_##line); \
|
||||
void test_func_##line()
|
||||
|
||||
#define VALIDATION_TEST_1(name, file, line) \
|
||||
VALIDATION_TEST_2(name, file, line)
|
||||
|
||||
#define VALIDATION_TEST(name) \
|
||||
VALIDATION_TEST_1(name, __FILE__, __LINE__)
|
||||
|
||||
#define VALIDATION_ASSERT_TRUE(expr) \
|
||||
::code::validation::Assert::assert_true((expr), #expr)
|
||||
|
||||
#define VALIDATION_ASSERT_FALSE(expr) \
|
||||
::code::validation::Assert::assert_false((expr), #expr)
|
||||
|
||||
#define VALIDATION_ASSERT_NULL(expr) \
|
||||
::code::validation::Assert::assert_null((expr), #expr)
|
||||
|
||||
#define VALIDATION_ASSERT_EQUAL(lhs, rhs) \
|
||||
::code::validation::Assert::assert_equal((lhs), (rhs), #lhs, #rhs)
|
||||
|
||||
#endif
|
43
code/validation/main.cxx
Normal file
43
code/validation/main.cxx
Normal file
@ -0,0 +1,43 @@
|
||||
#include <code/validation/main.hxx>
|
||||
|
||||
#include <code/validation/exec.hxx>
|
||||
#include <code/validation/test-summary.hxx>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
int verbosity{0};
|
||||
bool print_stats{false};
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (strcmp(argv[i], "--verbose") == 0) {
|
||||
++verbosity;
|
||||
}
|
||||
else if (strcmp(argv[i], "-v") == 0) {
|
||||
++verbosity;
|
||||
}
|
||||
else if (strcmp(argv[i], "--stats") == 0) {
|
||||
print_stats = true;
|
||||
}
|
||||
}
|
||||
|
||||
Test_summary summary;
|
||||
|
||||
bool success = exec(summary);
|
||||
|
||||
bool print_summary = verbosity > 0;
|
||||
bool print_extras = verbosity > 1;
|
||||
|
||||
if (print_summary) {
|
||||
summary.print(std::cout, print_extras, print_stats);
|
||||
}
|
||||
|
||||
return success ? 0 : -1;
|
||||
}
|
||||
|
||||
} // namespace code::validation
|
15
code/validation/main.hxx
Normal file
15
code/validation/main.hxx
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef code__validation__main_hxx_
|
||||
#define code__validation__main_hxx_
|
||||
|
||||
#include <code/validation/macros.hxx>
|
||||
#include <code/validation/assert.hxx>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
int
|
||||
main(int argc, char* argv[]);
|
||||
|
||||
} // namespace code::validation
|
||||
|
||||
#endif
|
60
code/validation/setup.cxx
Normal file
60
code/validation/setup.cxx
Normal file
@ -0,0 +1,60 @@
|
||||
#include <code/validation/setup.hxx>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
Setup::
|
||||
Setup(std::string file, int line, std::function<void()> function)
|
||||
: file_{std::move(file)}, line_{line}, function_{function}
|
||||
{}
|
||||
|
||||
std::string const&
|
||||
Setup::
|
||||
file() const
|
||||
{
|
||||
return file_;
|
||||
}
|
||||
|
||||
int
|
||||
Setup::
|
||||
line() const
|
||||
{
|
||||
return line_;
|
||||
}
|
||||
|
||||
Setup*
|
||||
Setup::
|
||||
next()
|
||||
{
|
||||
return Utility::Intrusive_list<Setup>::next();
|
||||
}
|
||||
|
||||
Setup*
|
||||
Setup::
|
||||
previous()
|
||||
{
|
||||
return Utility::Intrusive_list<Setup>::previous();
|
||||
}
|
||||
|
||||
void
|
||||
Setup::
|
||||
run()
|
||||
{
|
||||
function_();
|
||||
}
|
||||
|
||||
Setup*
|
||||
Setup::
|
||||
first()
|
||||
{
|
||||
return Utility::Intrusive_list<Setup>::first();
|
||||
}
|
||||
|
||||
Setup*
|
||||
Setup::
|
||||
last()
|
||||
{
|
||||
return Utility::Intrusive_list<Setup>::last();
|
||||
}
|
||||
|
||||
} // namespace code::validation
|
54
code/validation/setup.hxx
Normal file
54
code/validation/setup.hxx
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef code__validation__setup_hxx_
|
||||
#define code__validation__setup_hxx_
|
||||
|
||||
#include <code/validation/utility.hxx>
|
||||
|
||||
#include <functional>
|
||||
#include <source_location>
|
||||
#include <string>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
class Setup
|
||||
: Utility::Intrusive_list<Setup>
|
||||
{
|
||||
friend Utility::Intrusive_list<Setup>;
|
||||
|
||||
public:
|
||||
Setup(std::string, int, std::function<void()> function);
|
||||
|
||||
std::string const&
|
||||
file() const;
|
||||
|
||||
int
|
||||
line() const;
|
||||
|
||||
Setup*
|
||||
next();
|
||||
|
||||
Setup*
|
||||
previous();
|
||||
|
||||
void
|
||||
run();
|
||||
|
||||
static
|
||||
Setup*
|
||||
first();
|
||||
|
||||
static
|
||||
Setup*
|
||||
last();
|
||||
|
||||
private:
|
||||
std::string file_;
|
||||
int line_;
|
||||
std::function<void()> function_;
|
||||
|
||||
};
|
||||
|
||||
} // namespace code::validation
|
||||
|
||||
#endif
|
||||
|
60
code/validation/teardown.cxx
Normal file
60
code/validation/teardown.cxx
Normal file
@ -0,0 +1,60 @@
|
||||
#include <code/validation/teardown.hxx>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
Teardown::
|
||||
Teardown(std::string file, int line, std::function<void()> function)
|
||||
: file_{std::move(file)}, line_{line}, function_{function}
|
||||
{}
|
||||
|
||||
std::string const&
|
||||
Teardown::
|
||||
file() const
|
||||
{
|
||||
return file_;
|
||||
}
|
||||
|
||||
int
|
||||
Teardown::
|
||||
line() const
|
||||
{
|
||||
return line_;
|
||||
}
|
||||
|
||||
Teardown*
|
||||
Teardown::
|
||||
next()
|
||||
{
|
||||
return Utility::Intrusive_list<Teardown>::next();
|
||||
}
|
||||
|
||||
Teardown*
|
||||
Teardown::
|
||||
previous()
|
||||
{
|
||||
return Utility::Intrusive_list<Teardown>::previous();
|
||||
}
|
||||
|
||||
void
|
||||
Teardown::
|
||||
run()
|
||||
{
|
||||
function_();
|
||||
}
|
||||
|
||||
Teardown*
|
||||
Teardown::
|
||||
first()
|
||||
{
|
||||
return Utility::Intrusive_list<Teardown>::first();
|
||||
}
|
||||
|
||||
Teardown*
|
||||
Teardown::
|
||||
last()
|
||||
{
|
||||
return Utility::Intrusive_list<Teardown>::last();
|
||||
}
|
||||
|
||||
} // namespace code::validation
|
54
code/validation/teardown.hxx
Normal file
54
code/validation/teardown.hxx
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef code__validation__teardown_hxx_
|
||||
#define code__validation__teardown_hxx_
|
||||
|
||||
#include <code/validation/utility.hxx>
|
||||
|
||||
#include <functional>
|
||||
#include <source_location>
|
||||
#include <string>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
class Teardown
|
||||
: Utility::Intrusive_list<Teardown>
|
||||
{
|
||||
friend Utility::Intrusive_list<Teardown>;
|
||||
|
||||
public:
|
||||
Teardown(std::string, int, std::function<void()> function);
|
||||
|
||||
std::string const&
|
||||
file() const;
|
||||
|
||||
int
|
||||
line() const;
|
||||
|
||||
Teardown*
|
||||
next();
|
||||
|
||||
Teardown*
|
||||
previous();
|
||||
|
||||
void
|
||||
run();
|
||||
|
||||
static
|
||||
Teardown*
|
||||
first();
|
||||
|
||||
static
|
||||
Teardown*
|
||||
last();
|
||||
|
||||
private:
|
||||
std::string file_;
|
||||
int line_;
|
||||
std::function<void()> function_;
|
||||
|
||||
};
|
||||
|
||||
} // namespace code::validation
|
||||
|
||||
#endif
|
||||
|
73
code/validation/test-case.cxx
Normal file
73
code/validation/test-case.cxx
Normal file
@ -0,0 +1,73 @@
|
||||
#include <code/validation/test-case.hxx>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
Test_case::
|
||||
Test_case(std::string description,
|
||||
std::string file,
|
||||
int line,
|
||||
std::function<void()> function)
|
||||
: description_{std::move(description)},
|
||||
file_{std::move(file)},
|
||||
line_{line},
|
||||
function_{function}
|
||||
{}
|
||||
|
||||
std::string const&
|
||||
Test_case::
|
||||
description() const
|
||||
{
|
||||
return description_;
|
||||
}
|
||||
|
||||
std::string const&
|
||||
Test_case::
|
||||
file() const
|
||||
{
|
||||
return file_;
|
||||
}
|
||||
|
||||
int
|
||||
Test_case::
|
||||
line() const
|
||||
{
|
||||
return line_;
|
||||
}
|
||||
|
||||
Test_case&
|
||||
Test_case::
|
||||
next()
|
||||
{
|
||||
return *Utility::Intrusive_list<Test_case>::next();
|
||||
}
|
||||
|
||||
Test_case&
|
||||
Test_case::
|
||||
previous()
|
||||
{
|
||||
return *Utility::Intrusive_list<Test_case>::previous();
|
||||
}
|
||||
|
||||
void
|
||||
Test_case::
|
||||
run()
|
||||
{
|
||||
function_();
|
||||
}
|
||||
|
||||
Test_case&
|
||||
Test_case::
|
||||
first()
|
||||
{
|
||||
return *Utility::Intrusive_list<Test_case>::first();
|
||||
}
|
||||
|
||||
Test_case&
|
||||
Test_case::
|
||||
last()
|
||||
{
|
||||
return *Utility::Intrusive_list<Test_case>::last();
|
||||
}
|
||||
|
||||
} // namespace code::validation
|
57
code/validation/test-case.hxx
Normal file
57
code/validation/test-case.hxx
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef code__validation__test_case_hxx_
|
||||
#define code__validation__test_case_hxx_
|
||||
|
||||
#include <code/validation/utility.hxx>
|
||||
|
||||
#include <functional>
|
||||
#include <source_location>
|
||||
#include <string>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
class Test_case
|
||||
: Utility::Intrusive_list<Test_case>
|
||||
{
|
||||
friend Utility::Intrusive_list<Test_case>;
|
||||
|
||||
public:
|
||||
Test_case(std::string, std::string, int, std::function<void()> function);
|
||||
|
||||
std::string const&
|
||||
description() const;
|
||||
|
||||
std::string const&
|
||||
file() const;
|
||||
|
||||
int
|
||||
line() const;
|
||||
|
||||
Test_case&
|
||||
next();
|
||||
|
||||
Test_case&
|
||||
previous();
|
||||
|
||||
void
|
||||
run();
|
||||
|
||||
static
|
||||
Test_case&
|
||||
first();
|
||||
|
||||
static
|
||||
Test_case&
|
||||
last();
|
||||
|
||||
private:
|
||||
std::string description_;
|
||||
std::string file_;
|
||||
int line_;
|
||||
std::function<void()> function_;
|
||||
|
||||
};
|
||||
|
||||
} // namespace code::validation
|
||||
|
||||
#endif
|
13
code/validation/test-fail-extras.cxx
Normal file
13
code/validation/test-fail-extras.cxx
Normal file
@ -0,0 +1,13 @@
|
||||
#include <code/validation/test-result.hxx>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
void
|
||||
Test_fail_extras::
|
||||
print(std::ostream& o) const
|
||||
{
|
||||
extras_->do_print(o);
|
||||
}
|
||||
|
||||
}
|
58
code/validation/test-fail-extras.hxx
Normal file
58
code/validation/test-fail-extras.hxx
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef code__validation__test_fail_extras_hxx_
|
||||
#define code__validation__test_fail_extras_hxx_
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
class Test_fail_extras
|
||||
{
|
||||
public:
|
||||
template<typename T>
|
||||
Test_fail_extras(T extras)
|
||||
: extras_{std::make_shared<Wrapper<T>>(std::move(extras))}
|
||||
{}
|
||||
|
||||
void
|
||||
print(std::ostream&) const;
|
||||
|
||||
private:
|
||||
struct Abstraction
|
||||
{
|
||||
virtual
|
||||
~Abstraction() noexcept = default;
|
||||
|
||||
virtual
|
||||
void
|
||||
do_print(std::ostream&) const = 0;
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Wrapper
|
||||
: Abstraction
|
||||
{
|
||||
template<typename... Args>
|
||||
Wrapper(Args&&... args)
|
||||
: extras{std::forward<Args>(args)...}
|
||||
{}
|
||||
|
||||
void
|
||||
do_print(std::ostream& o) const override
|
||||
{
|
||||
extras.print(o);
|
||||
}
|
||||
|
||||
T extras;
|
||||
|
||||
};
|
||||
|
||||
std::shared_ptr<Abstraction const> extras_;
|
||||
|
||||
};
|
||||
|
||||
} // namespace code::validation
|
||||
|
||||
#endif
|
69
code/validation/test-result.cxx
Normal file
69
code/validation/test-result.cxx
Normal file
@ -0,0 +1,69 @@
|
||||
#include <code/validation/test-result.hxx>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
Test_result::
|
||||
Test_result(std::string description,
|
||||
std::string file,
|
||||
int line,
|
||||
std::string message)
|
||||
: description_{std::move(description)},
|
||||
file_{std::move(file)},
|
||||
line_{line_},
|
||||
message_{std::move(message)}
|
||||
{}
|
||||
|
||||
Test_result::
|
||||
Test_result(std::string description,
|
||||
std::string file,
|
||||
int line,
|
||||
std::string message,
|
||||
Test_fail_extras extras)
|
||||
: description_{std::move(description)},
|
||||
file_{std::move(file)},
|
||||
line_{line_},
|
||||
message_{std::move(message)},
|
||||
extras_{extras}
|
||||
{}
|
||||
|
||||
std::string const&
|
||||
Test_result::
|
||||
description() const
|
||||
{
|
||||
return description_;
|
||||
}
|
||||
|
||||
std::string const&
|
||||
Test_result::
|
||||
file() const
|
||||
{
|
||||
return file_;
|
||||
}
|
||||
|
||||
int
|
||||
Test_result::
|
||||
line() const
|
||||
{
|
||||
return line_;
|
||||
}
|
||||
|
||||
std::string const&
|
||||
Test_result::
|
||||
message() const
|
||||
{
|
||||
return message_;
|
||||
}
|
||||
|
||||
void
|
||||
Test_result::
|
||||
print(std::ostream& o, bool print_extras) const
|
||||
{
|
||||
o << "test: " << description() << ": " << message() << '\n';
|
||||
|
||||
if (print_extras && extras_) {
|
||||
extras_->print(o);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace code::validation
|
45
code/validation/test-result.hxx
Normal file
45
code/validation/test-result.hxx
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef code__validation__test_result_hxx_
|
||||
#define code__validation__test_result_hxx_
|
||||
|
||||
#include <code/validation/test-fail-extras.hxx>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
class Test_result
|
||||
{
|
||||
public:
|
||||
Test_result(std::string, std::string, int, std::string);
|
||||
|
||||
Test_result(std::string, std::string, int, std::string, Test_fail_extras);
|
||||
|
||||
std::string const&
|
||||
description() const;
|
||||
|
||||
std::string const&
|
||||
file() const;
|
||||
|
||||
int
|
||||
line() const;
|
||||
|
||||
std::string const&
|
||||
message() const;
|
||||
|
||||
void
|
||||
print(std::ostream&, bool) const;
|
||||
|
||||
private:
|
||||
std::string description_;
|
||||
std::string file_;
|
||||
int line_;
|
||||
std::string message_;
|
||||
std::optional<Test_fail_extras> extras_;
|
||||
|
||||
};
|
||||
|
||||
} // namespace code::validation
|
||||
|
||||
#endif
|
48
code/validation/test-summary.cxx
Normal file
48
code/validation/test-summary.cxx
Normal file
@ -0,0 +1,48 @@
|
||||
#include <code/validation/test-summary.hxx>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
void
|
||||
Test_summary::
|
||||
append(Test_result result)
|
||||
{
|
||||
results_.emplace_back(std::move(result));
|
||||
}
|
||||
|
||||
void
|
||||
Test_summary::
|
||||
inc_pass()
|
||||
{
|
||||
++pass_;
|
||||
}
|
||||
|
||||
void
|
||||
Test_summary::
|
||||
inc_fail()
|
||||
{
|
||||
++fail_;
|
||||
}
|
||||
|
||||
void
|
||||
Test_summary::
|
||||
print(std::ostream& o, bool print_extras, bool stats) const
|
||||
{
|
||||
for (auto const& j : results_) {
|
||||
j.print(o, print_extras);
|
||||
}
|
||||
|
||||
if (stats) {
|
||||
auto total = pass_ + fail_;
|
||||
|
||||
o << "test statistics:\n"
|
||||
<< "tests : " << total << '\n'
|
||||
<< "tests passed: " << pass_ << '\n'
|
||||
<< "tests failed: " << fail_ << '\n'
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace code::validation
|
38
code/validation/test-summary.hxx
Normal file
38
code/validation/test-summary.hxx
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef code__validation__test_summary_hxx_
|
||||
#define code__validation__test_summary_hxx_
|
||||
|
||||
#include <code/validation/test-result.hxx>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
class Test_summary
|
||||
{
|
||||
public:
|
||||
Test_summary() = default;
|
||||
|
||||
void
|
||||
append(Test_result);
|
||||
|
||||
void
|
||||
inc_pass();
|
||||
|
||||
void
|
||||
inc_fail();
|
||||
|
||||
void
|
||||
print(std::ostream&, bool, bool) const;
|
||||
|
||||
private:
|
||||
std::vector<Test_result> results_;
|
||||
int pass_{};
|
||||
int fail_{};
|
||||
|
||||
};
|
||||
|
||||
} // namespace code::validation
|
||||
|
||||
#endif
|
23
code/validation/traits.hxx
Normal file
23
code/validation/traits.hxx
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef code__validation__traits_hxx_
|
||||
#define code__validation__traits_hxx_
|
||||
|
||||
#include <concepts>
|
||||
#include <iostream>
|
||||
|
||||
namespace code::validation
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
concept has_output_operator = requires(std::ostream& o, T const& value)
|
||||
{
|
||||
// check if T can be written to an std::ostream.
|
||||
//
|
||||
{
|
||||
o << value
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
} // namespace code::validation
|
||||
|
||||
#endif
|
138
code/validation/utility.hxx
Normal file
138
code/validation/utility.hxx
Normal file
@ -0,0 +1,138 @@
|
||||
#ifndef code__validation__utility_hxx_
|
||||
#define code__validation__utility_hxx_
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace code::validation::Utility
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
class Intrusive_list
|
||||
{
|
||||
protected:
|
||||
Intrusive_list()
|
||||
{
|
||||
if (!first_ || !last_) {
|
||||
first_ = this;
|
||||
last_ = this;
|
||||
}
|
||||
|
||||
first_->prev_ = this;
|
||||
last_->next_ = this;
|
||||
|
||||
prev_ = last_;
|
||||
next_ = first_;
|
||||
|
||||
last_ = this;
|
||||
|
||||
++counter_;
|
||||
}
|
||||
|
||||
Intrusive_list(Intrusive_list const&) = delete;
|
||||
Intrusive_list(Intrusive_list&&) = delete;
|
||||
|
||||
~Intrusive_list() noexcept
|
||||
{
|
||||
if (first_ == this) {
|
||||
first_ = next_;
|
||||
}
|
||||
|
||||
if (last_ == this) {
|
||||
last_ = prev_;
|
||||
}
|
||||
|
||||
prev_->next_ = next_;
|
||||
next_->prev_ = prev_;
|
||||
|
||||
--counter_;
|
||||
}
|
||||
|
||||
Intrusive_list& operator=(Intrusive_list const&) = delete;
|
||||
Intrusive_list& operator=(Intrusive_list&&) = delete;
|
||||
|
||||
T*
|
||||
previous()
|
||||
{
|
||||
return static_cast<T*>(prev_);
|
||||
}
|
||||
|
||||
T*
|
||||
next()
|
||||
{
|
||||
return static_cast<T*>(next_);
|
||||
}
|
||||
|
||||
static
|
||||
T*
|
||||
first()
|
||||
{
|
||||
return static_cast<T*>(first_);
|
||||
}
|
||||
|
||||
static
|
||||
T*
|
||||
last()
|
||||
{
|
||||
return static_cast<T*>(last_);
|
||||
}
|
||||
|
||||
static
|
||||
std::size_t
|
||||
count()
|
||||
{
|
||||
return counter_;
|
||||
}
|
||||
|
||||
private:
|
||||
Intrusive_list<T>* prev_{nullptr};
|
||||
Intrusive_list<T>* next_{nullptr};
|
||||
|
||||
static Intrusive_list<T>* first_;
|
||||
static Intrusive_list<T>* last_;
|
||||
|
||||
static std::size_t counter_;
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
Intrusive_list<T>* Intrusive_list<T>::first_{nullptr};
|
||||
|
||||
template<typename T>
|
||||
Intrusive_list<T>* Intrusive_list<T>::last_{nullptr};
|
||||
|
||||
template<typename T>
|
||||
std::size_t Intrusive_list<T>::counter_{0};
|
||||
|
||||
template<typename T>
|
||||
class Current
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
Current(T* current)
|
||||
{
|
||||
current_ = current;
|
||||
}
|
||||
|
||||
~Current() noexcept
|
||||
{
|
||||
current_ = nullptr;
|
||||
}
|
||||
|
||||
static
|
||||
T*
|
||||
get()
|
||||
{
|
||||
return current_;
|
||||
}
|
||||
|
||||
private:
|
||||
static T* current_;
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T* Current<T>::current_{nullptr};
|
||||
|
||||
} // namespace code::validation::Utility
|
||||
|
||||
#endif
|
8
code/validation/validate.hxx
Normal file
8
code/validation/validate.hxx
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef code__validation__validation_hxx_
|
||||
#define code__validation__validation_hxx_
|
||||
|
||||
#include <code/validation/exec.hxx>
|
||||
#include <code/validation/macros.hxx>
|
||||
#include <code/validation/main.hxx>
|
||||
|
||||
#endif
|
37
code/validation/version.hxx.in
Normal file
37
code/validation/version.hxx.in
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef code__validation___version_hxx_
|
||||
#define code__validation___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 LIBCODE_VALIDATION_VERSION $libcode_validation.version.project_number$ULL
|
||||
#define LIBCODE_VALIDATION_VERSION_STR "$libcode_validation.version.project$"
|
||||
#define LIBCODE_VALIDATION_VERSION_ID "$libcode_validation.version.project_id$"
|
||||
#define LIBCODE_VALIDATION_VERSION_FULL "$libcode_validation.version$"
|
||||
|
||||
#define LIBCODE_VALIDATION_VERSION_MAJOR $libcode_validation.version.major$
|
||||
#define LIBCODE_VALIDATION_VERSION_MINOR $libcode_validation.version.minor$
|
||||
#define LIBCODE_VALIDATION_VERSION_PATCH $libcode_validation.version.patch$
|
||||
|
||||
#define LIBCODE_VALIDATION_PRE_RELEASE $libcode_validation.version.pre_release$
|
||||
|
||||
#define LIBCODE_VALIDATION_SNAPSHOT_SN $libcode_validation.version.snapshot_sn$ULL
|
||||
#define LIBCODE_VALIDATION_SNAPSHOT_ID "$libcode_validation.version.snapshot_id$"
|
||||
|
||||
#endif
|
11
manifest
Normal file
11
manifest
Normal file
@ -0,0 +1,11 @@
|
||||
: 1
|
||||
name: libcode-validation
|
||||
version: 0.1.0-a.0.z
|
||||
language: c++
|
||||
summary: libcode-validation C++ library
|
||||
license: BSD-4-Clause
|
||||
description-file: README.md
|
||||
url: https://helloryan.se/code/
|
||||
email: ryan@helloryan.se
|
||||
depends: * build2 >= 0.17.0
|
||||
depends: * bpkg >= 0.17.0
|
2
repositories.manifest
Normal file
2
repositories.manifest
Normal file
@ -0,0 +1,2 @@
|
||||
: 1
|
||||
summary: libcode-validation project repository
|
8
tests/.gitignore
vendored
Normal file
8
tests/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Test executables.
|
||||
#
|
||||
driver
|
||||
|
||||
# Testscript output directories (can be symlinks).
|
||||
#
|
||||
test
|
||||
test-*
|
1
tests/basics/.gitignore
vendored
Normal file
1
tests/basics/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
basics
|
31
tests/basics/basics.cxx
Normal file
31
tests/basics/basics.cxx
Normal file
@ -0,0 +1,31 @@
|
||||
#include <code/validation/main.hxx>
|
||||
|
||||
VALIDATION_TEST_SETUP
|
||||
{
|
||||
}
|
||||
|
||||
VALIDATION_TEST_TEARDOWN
|
||||
{
|
||||
}
|
||||
|
||||
VALIDATION_TEST(test_true)
|
||||
{
|
||||
VALIDATION_ASSERT_TRUE(true == true);
|
||||
}
|
||||
|
||||
VALIDATION_TEST(test_false)
|
||||
{
|
||||
VALIDATION_ASSERT_FALSE(true == false);
|
||||
}
|
||||
|
||||
VALIDATION_TEST(test_null)
|
||||
{
|
||||
int* ptr{nullptr};
|
||||
VALIDATION_ASSERT_NULL(ptr);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
return code::validation::main(argc, argv);
|
||||
}
|
4
tests/basics/buildfile
Normal file
4
tests/basics/buildfile
Normal file
@ -0,0 +1,4 @@
|
||||
import libs = libcode-validation%lib{code-validation}
|
||||
|
||||
exe{basics}: {hxx ixx txx cxx}{**} $libs testscript{**}
|
||||
exe{basics}: test.options = -v -v
|
4
tests/build/.gitignore
vendored
Normal file
4
tests/build/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/config.build
|
||||
/root/
|
||||
/bootstrap/
|
||||
build/
|
5
tests/build/bootstrap.build
Normal file
5
tests/build/bootstrap.build
Normal file
@ -0,0 +1,5 @@
|
||||
project = # Unnamed tests subproject.
|
||||
|
||||
using config
|
||||
using test
|
||||
using dist
|
16
tests/build/root.build
Normal file
16
tests/build/root.build
Normal file
@ -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
|
1
tests/buildfile
Normal file
1
tests/buildfile
Normal file
@ -0,0 +1 @@
|
||||
./: {*/ -build/}
|
Loading…
x
Reference in New Issue
Block a user