Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .githooks/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ cd $SCRIPTPATH/../
set -e

CMD_TO_RUN="make && make test && make doc && cp build/linux/zeroerr.hpp ./zeroerr.hpp"
if [ -f "/etc/wsl.conf" ]; then
if [ "$(uname -o)" == "GNU/Linux" ]; then
bash -c "$CMD_TO_RUN"
elif [ -f "/etc/wsl.conf" ]; then
bash -c "$CMD_TO_RUN"
else
wsl -- bash -c "$CMD_TO_RUN"
Expand Down
8 changes: 8 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Windows 2_log",
"program": "${workspaceFolder}/build/windows/examples/Debug/2_log.exe",
"args": ["--testcase=parsing test"],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
Expand Down
5 changes: 0 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,6 @@ option(BUILD_EXAMPLES "Build examples(ON, OFF)" OFF)
option(BUILD_DOC "Build documentation" OFF)
option(BUILD_TEST "Build unittest" OFF)

add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
add_compile_options("$<$<CXX_COMPILER_ID:Clang>:-fstandalone-debug>")
# add_compile_options("$<$<CXX_COMPILER_ID:GNU>:-ftime-report>")

set(header_dirs
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/extension
Expand Down
11 changes: 7 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ all: linux windows
build/linux/Makefile: Makefile
mkdir -p build/linux
cmake -B build/linux -S . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=11 \
-DBUILD_EXAMPLES=ON -DBUILD_TEST=ON -DUSE_MOLD=ON -DENABLE_FUZZING=ON \
-DBUILD_EXAMPLES=ON -DBUILD_TEST=ON -DUSE_MOLD=ON -DDISABLE_CUDA_BUILD=OFF -DENABLE_FUZZING=ON \
-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang

linux: build/linux/Makefile
Expand All @@ -14,18 +14,21 @@ linux: build/linux/Makefile
build/windows/ZeroErr.sln:
mkdir -p build/windows
cmake.exe -B build/windows -S . \
-DBUILD_EXAMPLES=ON -DBUILD_TEST=ON -T host=x64 -A x64
-DBUILD_EXAMPLES=ON -DBUILD_TEST=ON -DDISABLE_CUDA_BUILD=OFF -T host=x64 -A x64

windows: build/windows/ZeroErr.sln
cmake.exe --build build/windows --config Debug -j `nproc`

test: linux-test windows-test fuzz-test

cuda-test: windows
cd build/windows/test && ./Debug/cudatest.exe

fuzz-test: linux
cd build/linux/test && ./unittest --testcase=fuzz_serialize.*

fuzz: linux
cd build/linux/test && ./unittest -f --testcase=fuzz_test.*
cd build/linux/test && ./unittest -f --testcase=presentation

linux-test: linux
cd build/linux/test && ./unittest
Expand All @@ -34,7 +37,7 @@ reporter: linux
cd build/linux/test && ./unittest --no-color --log-to-report --reporters=xml

windows-test: windows
cd build/windows/test && ./Debug/unittest.exe
cd build/windows/test && ../examples/Debug/2_log.exe --testcase="parsing test"


build/linux-release/Makefile: Makefile
Expand Down
23 changes: 15 additions & 8 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,26 @@ clang++ -std=c++11 -fsanitize=fuzzer-no-link -L=`clang++ -print-runtime-dir` -lc
```


## Other Good Features
## CppCon 24 Talk

If you are interested in the design and internal techiques used in `zeroerr`, please checkout [the talk in CppCon 24](https://youtu.be/otSPZyXqY_M?si=LLSHh8gkfCiQk983).

[![](docs/fig/video-screenshot.png)](https://youtu.be/otSPZyXqY_M?si=LLSHh8gkfCiQk983)

## Header-only libraries

* dbg
* print (without use extern functions)
* assert
* color (if always enabled)


## Other Good Features

Here are a list of features we provided:

1. Partially include
You can only include what you need. If you need only assertion but no unit testing, no problem.
You can only include what you need. If you need only assertion but no unit testing, you can only include the header `zeroerr/assert.h`.

2. Optional thread safety
You can choose to build with/without thread safety.
Expand Down Expand Up @@ -235,12 +248,6 @@ We can support output structured information directly into plain text or lisp fo
13. Automatic Tracing with logging
While logging at the end, we can record the time consuming for this function.

## Header-only libraries

* dbg
* print (without use extern functions)
* assert
* color (if always enabled)


## The logo generation
Expand Down
Binary file added docs/fig/video-screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion examples/1_basic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,5 @@ TEST_CASE("fib function test") {
CHECK(fib(3) == 2);
CHECK(fib(4) == 3);
CHECK(fib(5) == 5);
CHECK(fib(20) == 6765);
CHECK_THROWS(fib(20));
}
79 changes: 79 additions & 0 deletions examples/2_log.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#define ZEROERR_IMPLEMENTATION
#include "zeroerr.hpp"

using namespace zeroerr;

TEST_CASE("1. basic log test") {
LOG("Basic log");
WARN("Warning log");
ERR("Error log");
FATAL("Fatal log");

LOG("log with basic thype {} {} {} {}", 1, true, 1.0, "string");

std::vector<std::tuple<int, float, std::string>> data = {
{1, 1.0, "string"}, {2, 2.0, "string"}
};
LOG("log with complex type: {data}", data);

LOG_IF(1==1, "log if condition is true");
LOG_FIRST(1==1, "log only at the first time condition is true");
WARN_EVERY_(2, "log every 2 times");
WARN_IF_EVERY_(2, 1==1, "log if condition is true every 2 times");

DLOG(WARN_IF, 1==1, "debug log for WARN_IF");
}


struct Expr {
virtual Expr* Clone() { return new Expr(); };
virtual ~Expr() {}
};

Expr* parse_the_input(std::string input) {
return new Expr();
}


Expr* parseExpr(std::string input)
{
static std::map<std::string, Expr*> cache;
if (cache.count(input) == 0) {
Expr* expr = parse_the_input(input);
cache[input] = expr;
return expr;
} else {
LOG("CacheHit: input = {input}", input);
return cache[input]->Clone();
}
}

TEST_CASE("parsing test") {
zeroerr::suspendLog();
std::string log;
Expr* e1 = parseExpr("1 + 2");
log = LOG_GET(parseExpr, "CacheHit", input, std::string);
CHECK(log == std::string{});
Expr* e2 = parseExpr("1 + 2");
log = zeroerr::LogStream::getDefault()
.getLog<std::string>("parseExpr", "CacheHit", "input");
CHECK(log == "1 + 2");
zeroerr::resumeLog();
}


TEST_CASE("iterate log stream") {
zeroerr::suspendLog();

auto& stream = zeroerr::LogStream::getDefault();

for (auto p = stream.begin("function log {sum}, {i}"); p != stream.end(); ++p) {
std::cerr << "p.get<int>(\"sum\") = " << p.get<int>("sum") << std::endl;
std::cerr << "p.get<int>(\"i\") = " << p.get<int>("i") << std::endl;
CHECK(p.get<int>("sum") == 10);
CHECK(p.get<int>("i") == 1);
}

zeroerr::resumeLog();
}

41 changes: 41 additions & 0 deletions examples/3_fuzzing.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#define ZEROERR_IMPLEMENTATION
#define ZEROERR_FUZZING
#include "zeroerr.hpp"

using namespace zeroerr;



int find_the_biggest(std::vector<int> vec) {
if (vec.empty()) {
WARN("Empty vector, vec.size() = {size}", vec.size());
return 0;
}
int max = 0;
for (int i = 0; i < vec.size(); ++i) {
if (vec[i] > max) {max = vec[i];}
}
return max;
}

FUZZ_TEST_CASE("presentation") {
LOG("Run fuzz_test");
FUZZ_FUNC([=](std::vector<int> vec) {
int ans = find_the_biggest(vec);
// verify the result
for (int i = 0; i < vec.size(); ++i) {
CHECK(ans >= vec[i]);
}
if (vec.size() == 0) {
CHECK(ans == 0);
// verify WARN message to make sure the path is correct
CHECK(LOG_GET(find_the_biggest,
"Empty vector, vec.size() = {size}", size, size_t) == 0);
}
})
.WithDomains(ContainerOf<std::vector<int>>(
InRange<int>(0, 100)))
.WithSeeds({{{0, 1, 2, 3, 4, 5}}, {{1, 8, 4, 2, 3}}})
.Run(100);

}
10 changes: 8 additions & 2 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
add_executable(1_basic ${CMAKE_CURRENT_SOURCE_DIR}/1_basic.cpp)
add_dependencies(1_basic assemble_single_header)
macro(define_example name)
add_executable(${name} ${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp)
add_dependencies(${name} assemble_single_header)
endmacro(define_example)

define_example(1_basic)
define_example(2_log)
define_example(3_fuzzing)
10 changes: 10 additions & 0 deletions include/zeroerr/assert.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
#define ZEROERR_G_CONTEXT_SCOPE(x)
#endif


/**
* @brief Default printer for assertion messages
*
* This macro defines the default printer for assertion messages.
* It prints the assertion message in different colors based on the assertion level.
*
* The macro can be overridden by defining ZEROERR_PRINT_ASSERT_DEFAULT_PRINTER before
* including this header. (Or undefine it and implement your own printer.)
*/
#ifndef ZEROERR_PRINT_ASSERT_DEFAULT_PRINTER
#define ZEROERR_PRINT_ASSERT_DEFAULT_PRINTER(cond, level, ...) \
do { \
Expand Down
19 changes: 10 additions & 9 deletions include/zeroerr/benchmark.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@

ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH

#define ZEROERR_CREATE_BENCHMARK_FUNC(function, name) \
static void function(zeroerr::TestContext*); \
static zeroerr::detail::regTest ZEROERR_NAMEGEN(_zeroerr_reg)( \
{name, __FILE__, __LINE__, function}, zeroerr::TestType::bench); \
#define ZEROERR_CREATE_BENCHMARK_FUNC(function, name, ...) \
static void function(zeroerr::TestContext*); \
static zeroerr::detail::regTest ZEROERR_NAMEGEN(_zeroerr_reg)( \
{name, __FILE__, __LINE__, function, {__VA_ARGS__}}, zeroerr::TestType::bench); \
static void function(ZEROERR_UNUSED(zeroerr::TestContext* _ZEROERR_TEST_CONTEXT))

#define BENCHMARK(name) ZEROERR_CREATE_BENCHMARK_FUNC(ZEROERR_NAMEGEN(_zeroerr_benchmark), name)
#define BENCHMARK(name, ...) \
ZEROERR_CREATE_BENCHMARK_FUNC(ZEROERR_NAMEGEN(_zeroerr_benchmark), name, __VA_ARGS__)


namespace zeroerr {
Expand Down Expand Up @@ -61,7 +62,7 @@ struct PerformanceCounter {
void endMeasure();
void updateResults(uint64_t numIters);

PerfCountSet<uint64_t> const& val() const noexcept { return _val; }
const PerfCountSet<uint64_t>& val() const noexcept { return _val; }
PerfCountSet<bool> has() const noexcept { return _has; }

static PerformanceCounter& inst();
Expand Down Expand Up @@ -164,10 +165,10 @@ struct Benchmark {
namespace detail {

#if defined(_MSC_VER)
void doNotOptimizeAwaySink(void const*);
void doNotOptimizeAwaySink(const void*);

template <typename T>
void doNotOptimizeAway(T const& val) {
void doNotOptimizeAway(const T& val) {
doNotOptimizeAwaySink(&val);
}

Expand All @@ -178,7 +179,7 @@ void doNotOptimizeAway(T const& val) {
// Google Benchmark seemed to be the most well tested anyways. see
// https://github.com/google/benchmark/blob/master/include/benchmark/benchmark.h#L307
template <typename T>
void doNotOptimizeAway(T const& val) {
void doNotOptimizeAway(const T& val) {
// NOLINTNEXTLINE(hicpp-no-assembler)
asm volatile("" : : "r,m"(val) : "memory");
}
Expand Down
24 changes: 24 additions & 0 deletions include/zeroerr/domains/aggregate_of.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,30 @@ ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH

namespace zeroerr {


/**
* @brief AggregateOf is a domain that combines multiple inner domains into a tuple or aggregate type
*
* @tparam T The aggregate type to generate (e.g. struct or tuple)
* @tparam Inner The inner domain types that will generate each field
*
* This domain allows generating structured data by composing multiple inner domains.
* Each inner domain generates one field of the aggregate type.
*
* Example:
* ```cpp
* struct Point {
* int x;
* int y;
* };
*
* auto domain = AggregateOf<Point>(
* InRange(0, 100), // Domain for x
* InRange(0, 100) // Domain for y
* );
* ```
*/

template <typename T, typename... Inner>
class AggregateOf : public Domain<T, std::tuple<typename Inner::CorpusType...>> {
public:
Expand Down
Loading