@ -0,0 +1,2 @@ |
|||
.nodepy |
|||
build |
@ -0,0 +1,20 @@ |
|||
|
|||
namespace = 'tests' |
|||
|
|||
import craftr from 'craftr' |
|||
import cxx from '@craftr/cxx' |
|||
import '@craftr/googlebenchmark' |
|||
import '@craftr/googletest' |
|||
|
|||
cxx.binary( |
|||
name = 'tests', |
|||
deps = [ |
|||
'//@craftr/googlebenchmark:googlebenchmark', |
|||
'//@craftr/googletest:googletest' |
|||
], |
|||
srcs = craftr.glob('*.cpp'), |
|||
cpp_std = 'c++11', |
|||
includes = [craftr.localpath('../include')] |
|||
) |
|||
|
|||
cxx.run(':tests') |
@ -0,0 +1,36 @@ |
|||
/**
|
|||
* Copyright (c) 2018 Niklas Rosenstein |
|||
* MIT licensed. |
|||
*/ |
|||
|
|||
#include <benchmark/benchmark.h>
|
|||
#include <gtest/gtest.h>
|
|||
|
|||
int main(int argc, char** argv) { |
|||
::testing::InitGoogleTest(&argc, argv); |
|||
::benchmark::Initialize(&argc, argv); |
|||
|
|||
bool run_tests = true; |
|||
bool run_benchmarks = true; |
|||
if (argc == 2) { |
|||
if (strcmp(argv[1], "test") == 0) { |
|||
run_benchmarks = false; |
|||
--argc; |
|||
} |
|||
else if (strcmp(argv[1], "benchmark") == 0) { |
|||
run_tests = false; |
|||
--argc; |
|||
} |
|||
} |
|||
if (argc > 1) { |
|||
fprintf(stdout, "%s: error: unhandled argument: %s", argv[0], argv[1]); |
|||
return 1; |
|||
} |
|||
|
|||
int res = 0; |
|||
if (run_tests) |
|||
res = RUN_ALL_TESTS(); |
|||
if (run_benchmarks) |
|||
::benchmark::RunSpecifiedBenchmarks(); |
|||
return res; |
|||
} |
@ -0,0 +1,87 @@ |
|||
/**
|
|||
* Copyright (c) 2018 Niklas Rosenstein |
|||
* MIT licensed. |
|||
*/ |
|||
|
|||
#include <benchmark/benchmark.h>
|
|||
#include <gtest/gtest.h>
|
|||
|
|||
#include <iostream>
|
|||
#include <vector>
|
|||
|
|||
#include <NiklasRosenstein/enumerate.hpp>
|
|||
#include <NiklasRosenstein/filter.hpp>
|
|||
#include <NiklasRosenstein/range.hpp>
|
|||
|
|||
namespace nr = niklasrosenstein; |
|||
|
|||
|
|||
TEST(Iterator, range) { |
|||
std::size_t index1 = 2; |
|||
for (std::size_t index2 : nr::range<std::size_t>(2, 10)) { |
|||
ASSERT_EQ(index1++, index2); |
|||
} |
|||
} |
|||
|
|||
TEST(Iterator, enumerator_rvalue) { |
|||
std::size_t index1 = 5; |
|||
for (auto item : nr::enumerate(nr::range<std::size_t>(5, 27))) { |
|||
ASSERT_EQ(index1 - 5, item.index); |
|||
ASSERT_EQ(index1++, item.value); |
|||
} |
|||
ASSERT_EQ(index1, 27); |
|||
} |
|||
|
|||
TEST(Iterator, enumerator_lvalue) { |
|||
std::size_t index = 0; |
|||
std::vector<int> items; |
|||
items.push_back(1); |
|||
items.push_back(2); |
|||
items.push_back(3); |
|||
items.push_back(4); |
|||
for (auto item : nr::enumerate(items)) { |
|||
ASSERT_EQ(item.index, item.value - 1); |
|||
ASSERT_EQ(index++, item.index); |
|||
} |
|||
ASSERT_EQ(index, 4); |
|||
} |
|||
|
|||
struct Element { |
|||
int value; |
|||
Element() : value(-1) {} |
|||
Element(int value_) : value(value_) {} |
|||
Element(Element&& other) : value(std::move(other.value)) {} |
|||
Element(Element const&) = delete; |
|||
Element& operator = (Element const&) = delete; |
|||
}; |
|||
|
|||
TEST(Iterator, enumerator_value_by_reference) { |
|||
size_t index = 0; |
|||
std::vector<Element> elements; |
|||
elements.push_back({1}); |
|||
elements.push_back({2}); |
|||
elements.push_back({3}); |
|||
elements.push_back({4}); |
|||
for (auto item : nr::enumerate(elements)) { |
|||
ASSERT_EQ(item.index, item.value.value - 1); |
|||
ASSERT_EQ(&item.value, &elements[item.index]); |
|||
ASSERT_EQ(index++, item.index); |
|||
} |
|||
ASSERT_EQ(index, 4); |
|||
} |
|||
|
|||
TEST(Iterator, filter_range_bool) { |
|||
size_t index = 0; |
|||
for (size_t value : nr::filter(nr::range<size_t>(10))) { |
|||
ASSERT_EQ(index++, value - 1); |
|||
} |
|||
ASSERT_EQ(index, 9); |
|||
} |
|||
|
|||
TEST(Iterator, filter_range_func) { |
|||
size_t index = 0; |
|||
for (size_t value : nr::filter(nr::range<size_t>(10), [](size_t v) { return v%2 == 0; })) { |
|||
ASSERT_EQ(index++, value / 2); |
|||
} |
|||
ASSERT_EQ(index, 5); |
|||
} |
@ -0,0 +1,27 @@ |
|||
/**
|
|||
* Copyright (c) 2018 Niklas Rosenstein |
|||
* MIT licensed. |
|||
*/ |
|||
|
|||
#include <gtest/gtest.h>
|
|||
#include <NiklasRosenstein/md5.hpp>
|
|||
#include <NiklasRosenstein/string.hpp>
|
|||
|
|||
namespace nr = niklasrosenstein; |
|||
|
|||
|
|||
static char const* testcases[] = { |
|||
"5d41402abc4b2a76b9719d911017c592", "hello", |
|||
"7ba5f2fbcbdc4ae2c534b3e465d7289d", "Foo!fzxfBar", |
|||
"459eb8ae005b152640eef3d83a0b31a6", "http://www.md5.cz/", |
|||
"184bbe3aece849b721d2d8cc38434600", "Fancy fancy md5!", |
|||
0, 0 |
|||
}; |
|||
|
|||
TEST(md5, test) { |
|||
for (int i = 0; testcases[i]; i += 2) { |
|||
std::string hash = nr::md5(testcases[i + 1]).hexdigest(); |
|||
std::string reference = testcases[i]; |
|||
ASSERT_EQ(hash, reference); |
|||
} |
|||
} |
@ -0,0 +1,132 @@ |
|||
/**
|
|||
* Copyright (c) 2018 Niklas Rosenstein |
|||
* MIT licensed. |
|||
*/ |
|||
|
|||
#include <benchmark/benchmark.h>
|
|||
#include <gtest/gtest.h>
|
|||
#include <NiklasRosenstein/typeid.hpp>
|
|||
|
|||
namespace nr = niklasrosenstein; |
|||
|
|||
|
|||
class InterfaceA { |
|||
NR_TYPEID(InterfaceA, 1000); |
|||
public: |
|||
virtual int method_a() = 0; |
|||
}; |
|||
|
|||
|
|||
class InterfaceB { |
|||
NR_TYPEID(InterfaceB, 1001); |
|||
public: |
|||
virtual int method_b() = 0; |
|||
}; |
|||
|
|||
|
|||
class InterfaceC { |
|||
int member; |
|||
public: |
|||
InterfaceC(int member) : member(member) {} |
|||
virtual int method_c() { return member; } |
|||
}; |
|||
|
|||
|
|||
// Associate a type ID with an external type that you can not add the
|
|||
// #NR_TYPEID() macro to the class defition to. Note that casting FROM
|
|||
// a pointer of such a type is not possible.
|
|||
NR_TYPEID_EX(InterfaceC, 1003); |
|||
|
|||
|
|||
struct Impl : public virtual InterfaceA, virtual InterfaceB, virtual InterfaceC { |
|||
NR_TYPEID(Impl, 3000, InterfaceA, InterfaceB, InterfaceC); |
|||
|
|||
Impl() : InterfaceC(10) { } |
|||
virtual ~Impl() {} |
|||
|
|||
// InterfaceA Overrides
|
|||
virtual int method_a() override { return 99; } |
|||
|
|||
// InterfaceB Overrides
|
|||
virtual int method_b() override { return 42; } |
|||
|
|||
// InterfaceC Overrides
|
|||
virtual int method_c() override { return InterfaceC::method_c() * 2; } |
|||
}; |
|||
|
|||
|
|||
struct Unsupported {}; |
|||
|
|||
|
|||
TEST(type_id, castaround) { |
|||
Impl* i = new Impl; |
|||
|
|||
// Down-cast (just a static_cast)
|
|||
InterfaceA* a = i; |
|||
EXPECT_EQ(a->method_a(), i->method_a()); |
|||
|
|||
// Side-cast (can not be performed with static_cast).
|
|||
InterfaceB* b = nr::type_cast<InterfaceB>(a); |
|||
ASSERT_TRUE(b != nullptr); |
|||
EXPECT_EQ(b, static_cast<InterfaceB*>(i)); |
|||
EXPECT_EQ(b->method_b(), i->method_b()); |
|||
|
|||
InterfaceC* c = nr::type_cast<InterfaceC>(a); |
|||
ASSERT_TRUE(c != nullptr); |
|||
EXPECT_EQ(c, static_cast<InterfaceC*>(i)); |
|||
EXPECT_EQ(c->method_c(), i->method_c()); |
|||
|
|||
// Cast to class that does not provide a type ID always fails.
|
|||
Unsupported* u = nr::type_cast<Unsupported>(a); |
|||
EXPECT_EQ(u, nullptr); |
|||
|
|||
// Back to A from B (can not be performed with static_cast).
|
|||
InterfaceA* a_from_b = nr::type_cast<InterfaceA>(b); |
|||
ASSERT_TRUE(a_from_b != nullptr); |
|||
EXPECT_EQ(a_from_b, a); |
|||
|
|||
// Up-cast (can not be performed with static_cast).
|
|||
Impl* up_i_from_b = nr::type_cast<Impl>(b); |
|||
ASSERT_TRUE(up_i_from_b != nullptr); |
|||
EXPECT_EQ(i, up_i_from_b); |
|||
|
|||
delete i; |
|||
} |
|||
|
|||
|
|||
static void BM_TypeID_SideCast(benchmark::State& state) { |
|||
Impl* i = new Impl; |
|||
InterfaceA* a = i; |
|||
while (state.KeepRunning()) { |
|||
InterfaceB* b = nr::type_cast<InterfaceB>(a); |
|||
if (!b) { |
|||
state.SkipWithError("Sidecast from InterfaceA to InterfaceB failed"); |
|||
break; |
|||
} |
|||
if (b != static_cast<InterfaceB*>(i)) { |
|||
state.SkipWithError("Sidecast from InterfaceA to InterfaceB returned an invalid value"); |
|||
break; |
|||
} |
|||
} |
|||
delete i; |
|||
} |
|||
BENCHMARK(BM_TypeID_SideCast); |
|||
|
|||
|
|||
static void BM_TypeID_UpCast(benchmark::State& state) { |
|||
Impl* i = new Impl; |
|||
InterfaceA* a = i; |
|||
while (state.KeepRunning()) { |
|||
Impl* other_i = nr::type_cast<Impl>(a); |
|||
if (!other_i) { |
|||
state.SkipWithError("Upcast from InterfaceA to Impl failed"); |
|||
break; |
|||
} |
|||
if (other_i != i) { |
|||
state.SkipWithError("Upcast from InterfaceA to Impl returned an invalid value"); |
|||
break; |
|||
} |
|||
} |
|||
delete i; |
|||
} |
|||
BENCHMARK(BM_TypeID_UpCast); |