Skip to content

Commit

Permalink
Set coverage standard (#3)
Browse files Browse the repository at this point in the history
* Small code cleanup
* Add codecov.yml
* Increase report scope
* Extra test and minor improvements
* Add ASSERT to tests
  • Loading branch information
Bronek authored Jan 3, 2024
1 parent 2c21d98 commit 7e7d91c
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 12 deletions.
6 changes: 6 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
coverage:
status:
project:
default:
target: 96%
threshold: 2%
17 changes: 8 additions & 9 deletions libs/market/book.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@

#pragma once

#include "common/utils.hpp"
#include "market.hpp"
#include <common/utils.hpp>

#include <utility>
#include <cstddef>
#include <cstdint>
#include <stdexcept>
#include <algorithm>

Expand Down Expand Up @@ -189,30 +190,30 @@ namespace market {
for (; i < size_i; ++i) {
freel[i] = i;
}
tail_i = --i;
tail_i = size_i - 1;
side_i[0] = side_i[1] = 0;
ASSERT(side_i[0] + side_i[1] + (size_type)(tail_i + 1) == size_i);
};

void accept() {
ASSERT(freel != nullptr);
size_type i = 0;
for (; i < size_i; ++i) {
for (size_type i = 0; i < size_i; ++i) {
freel[i] = i;
}
// Mark elements in the free list, which are not actually free, with npos
for (i = 0; i < side_i[0] || i < side_i[1]; ++i) {
for (size_type i = 0; i < side_i[0] || i < side_i[1]; ++i) {
if (i < side_i[0]) {
freel[sides[i]] = npos;
}
if (i < side_i[1]) {
freel[sides[capacity + i]] = npos;
}
}
// Note: tail_i will underflow to npos if no space left, by design
tail_i = size_i - (size_type)1 - side_i[0] - side_i[1];
// Shift freel elements marked as taken (i.e. with npos value) to the end of freel
// Note: npos will not be preserved, it has no special meaning outside of accept
auto* const begin = &freel[0];
std::remove_if(begin, begin + size_i, [](size_type n){ return n == npos; } );
ASSERT(side_i[0] + side_i[1] + (size_type)(tail_i + 1) == size_i);
};

public:
Expand Down Expand Up @@ -271,7 +272,6 @@ namespace market {

template <side Side>
void sort() {
ASSERT(freel != nullptr);
auto* const begin = &sides[(size_t)Side * capacity];
std::sort(begin, begin + side_i[(size_t)Side], [this](size_type lh, size_type rh){
return book::compare<Side>(levels[lh], levels[rh]);
Expand All @@ -297,7 +297,6 @@ namespace market {

template <side Side>
level& at(size_type i) {
ASSERT(freel != nullptr);
ASSERT(i < side_i[(size_t)Side]);
const auto l = sides[(size_t)Side * capacity + i];
return levels[l];
Expand Down
99 changes: 98 additions & 1 deletion tests/book.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
// Distributed under the MIT License. See accompanying file LICENSE
// or copy at https://opensource.org/licenses/MIT

#include <market/book.hpp>
struct assert_error {};
#define ASSERT(...) do { if((__VA_ARGS__) == 0) throw assert_error{}; } while(0)

#include "market/book.hpp"

#include <catch2/catch.hpp>

Expand Down Expand Up @@ -427,6 +430,25 @@ namespace {
: book(levels, sides, freel, i, 0, 0, std::forward<Args>(t)...) {
this->accept();
}

template <market::side Side, size_t Size>
size_type populate(Level const (&input)[Size], size_type offset) {
size_type i = 0;
for (auto const &l : input) {
sides[(size_t)Side * capacity + i] = offset + i;
levels[offset + i++] = l; // Note: must post-increment
}
side_i[(size_t)Side] = i;
return i;
}

using market::book<Level>::reset;
using market::book<Level>::accept;

size_type *&base_freel() { return market::book<Level>::freel; }
size_type &base_tail() { return market::book<Level>::tail_i; }
size_type &base_size_bid() { return market::book<Level>::side_i[0]; }
size_type &base_size_ask() { return market::book<Level>::side_i[1]; }
};
}

Expand Down Expand Up @@ -549,6 +571,81 @@ TEST_CASE("AnySizeBook_construction", "[book][capacity][construction][bad_capaci
REQUIRE(ptr->emplace_back<side::bid>() == npos);
REQUIRE(ptr->emplace_back<side::ask>() == npos);
}

SECTION("call accept() on populated book") {
Level bids[2] = {Level{130130, 100}, Level{130140, 10}};
Level offers[3] = {Level{130190, 50}, Level{130180, 40}, Level{130170, 20}};

CHECK_NOTHROW(ptr.reset(new AnySizeBook(10, std::nothrow)));
REQUIRE(ptr->capacity == 10);
auto const offset = ptr->populate<side::bid>(bids, 0);
ptr->accept();
for (std::size_t i = 0; i < 20; ++i) {
CHECK((i >= 18 ? true : ptr->freel[i] == i + 2));
}
CHECK(ptr->size<side::bid>() == 2);
CHECK(ptr->size<side::ask>() == 0);
ptr->populate<side::ask>(offers, offset);
ptr->accept();
for (std::size_t i = 0; i < 20; ++i) {
CHECK((i >= 15 ? true : ptr->freel[i] == i + 5));
}
CHECK(ptr->size<side::bid>() == 2);
CHECK(ptr->size<side::ask>() == 3);
}

SECTION("ASSERT check") {
CHECK_NOTHROW(ptr.reset(new AnySizeBook(10, std::nothrow)));
SECTION("null freel") {
ptr->base_freel() = nullptr;
CHECK_THROWS_AS(ptr->reset(), assert_error);
CHECK_THROWS_AS(ptr->accept(), assert_error);
CHECK_THROWS_AS(ptr->push_back<side::bid>(Level{1, 1}), assert_error);
CHECK_THROWS_AS(ptr->push_back<side::ask>(Level{1, 1}), assert_error);
CHECK_THROWS_AS(ptr->emplace_back<side::bid>(1, 1), assert_error);
CHECK_THROWS_AS(ptr->emplace_back<side::ask>(1, 1), assert_error);
CHECK_THROWS_AS(ptr->remove<side::bid>(0), assert_error);
CHECK_THROWS_AS(ptr->remove<side::ask>(0), assert_error);
}
SECTION("bad bid size") {
ptr->base_size_bid() = 1;
CHECK_THROWS_AS(ptr->push_back<side::bid>(Level{1, 1}), assert_error);
CHECK_THROWS_AS(ptr->push_back<side::ask>(Level{1, 1}), assert_error);
CHECK_THROWS_AS(ptr->emplace_back<side::bid>(1, 1), assert_error);
CHECK_THROWS_AS(ptr->emplace_back<side::ask>(1, 1), assert_error);
CHECK_THROWS_AS(ptr->remove<side::bid>(0), assert_error);
CHECK_THROWS_AS(ptr->remove<side::ask>(0), assert_error);
}

SECTION("bad ask size") {
ptr->base_size_ask() = 1;
CHECK_THROWS_AS(ptr->push_back<side::bid>(Level{1, 1}), assert_error);
CHECK_THROWS_AS(ptr->push_back<side::ask>(Level{1, 1}), assert_error);
CHECK_THROWS_AS(ptr->emplace_back<side::bid>(1, 1), assert_error);
CHECK_THROWS_AS(ptr->emplace_back<side::ask>(1, 1), assert_error);
CHECK_THROWS_AS(ptr->remove<side::bid>(0), assert_error);
CHECK_THROWS_AS(ptr->remove<side::ask>(0), assert_error);
}

SECTION("bad tail") {
ptr->base_tail() = 1;
CHECK_THROWS_AS(ptr->push_back<side::bid>(Level{1, 1}), assert_error);
CHECK_THROWS_AS(ptr->push_back<side::ask>(Level{1, 1}), assert_error);
CHECK_THROWS_AS(ptr->emplace_back<side::bid>(1, 1), assert_error);
CHECK_THROWS_AS(ptr->emplace_back<side::ask>(1, 1), assert_error);
CHECK_THROWS_AS(ptr->remove<side::bid>(0), assert_error);
CHECK_THROWS_AS(ptr->remove<side::ask>(0), assert_error);
}

SECTION("bad index") {
CHECK_THROWS_AS(std::as_const(*ptr).at<side::bid>(0), assert_error);
CHECK_THROWS_AS(std::as_const(*ptr).at<side::ask>(0), assert_error);
CHECK_THROWS_AS(ptr->at<side::bid>(0), assert_error);
CHECK_THROWS_AS(ptr->at<side::ask>(0), assert_error);
CHECK_THROWS_AS(ptr->remove<side::bid>(0), assert_error);
CHECK_THROWS_AS(ptr->remove<side::ask>(0), assert_error);
}
}
}

TEST_CASE("AnySizeBook_binary_search", "[book][binary_search]") {
Expand Down
2 changes: 1 addition & 1 deletion tests/market.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Distributed under the MIT License. See accompanying file LICENSE
// or copy at https://opensource.org/licenses/MIT

#include <market/market.hpp>
#include "market/market.hpp"

#include <catch2/catch.hpp>

Expand Down
2 changes: 1 addition & 1 deletion tests/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Distributed under the MIT License. See accompanying file LICENSE
// or copy at https://opensource.org/licenses/MIT

#include <common/utils.hpp>
#include "common/utils.hpp"

#include <catch2/catch.hpp>

Expand Down

0 comments on commit 7e7d91c

Please sign in to comment.