Browse Source

add tests/ directory with a Craftr build script

master
Niklas Rosenstein 3 years ago
parent
commit
f3edc4f53a
Signed by: NiklasRosenstein GPG Key ID: 06D269B33D25F6C6
6 changed files with 304 additions and 0 deletions
  1. + 2
    - 0
      .gitignore
  2. + 20
    - 0
      tests/BUILD.cr.py
  3. + 36
    - 0
      tests/main.cpp
  4. + 87
    - 0
      tests/test_iterator.cpp
  5. + 27
    - 0
      tests/test_md5.cpp
  6. + 132
    - 0
      tests/test_typeid.cpp

+ 2
- 0
.gitignore

@ -0,0 +1,2 @@
.nodepy
build

+ 20
- 0
tests/BUILD.cr.py

@ -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')

+ 36
- 0
tests/main.cpp

@ -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;
}

+ 87
- 0
tests/test_iterator.cpp

@ -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);
}

+ 27
- 0
tests/test_md5.cpp

@ -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);
}
}

+ 132
- 0
tests/test_typeid.cpp

@ -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);

Loading…
Cancel
Save