381 lines
8.9 KiB
C++
381 lines
8.9 KiB
C++
#include <Gedeng.h>
|
|
#include <iostream>
|
|
|
|
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this
|
|
// in one cpp file
|
|
#include "catch_amalgamated.hpp"
|
|
|
|
SCENARIO("Vector size and length are correct", "[vector]") {
|
|
Gedeng::Vector<int> v(20);
|
|
v.push_back(1);
|
|
|
|
REQUIRE(v.size() == 1);
|
|
REQUIRE(v.length() == 20);
|
|
}
|
|
|
|
SCENARIO("The bracket operator returns the correct element", "[vector]") {
|
|
GIVEN("A vector with some elements") {
|
|
Gedeng::Vector<int> v(20);
|
|
v.push_back(1);
|
|
v.push_back(2);
|
|
v.push_back(3);
|
|
|
|
THEN("The element in the middle must have the expected value") {
|
|
REQUIRE(v[1] == 2);
|
|
}
|
|
|
|
THEN("The same value must be accessible using as_array") {
|
|
REQUIRE(v.as_array()[1] == 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
SCENARIO("Equality is returned correctly", "[vector]") {
|
|
GIVEN("Two vectors with the same items") {
|
|
Gedeng::Vector<int> v1;
|
|
Gedeng::Vector<int> v2;
|
|
|
|
v1.push_back(1);
|
|
v2.push_back(1);
|
|
|
|
v1.push_back(5);
|
|
v2.push_back(5);
|
|
|
|
REQUIRE(v1.size() == 2);
|
|
REQUIRE(v2.size() == 2);
|
|
|
|
WHEN("Comparing them") {
|
|
bool equals = v1 == v2;
|
|
|
|
THEN("The result should be true") {
|
|
REQUIRE(equals);
|
|
}
|
|
}
|
|
}
|
|
|
|
GIVEN("Two vectors with different items") {
|
|
Gedeng::Vector<int> v1;
|
|
Gedeng::Vector<int> v2;
|
|
|
|
v1.push_back(1);
|
|
v2.push_back(2);
|
|
|
|
v1.push_back(5);
|
|
v2.push_back(5);
|
|
|
|
REQUIRE(v1.size() == 2);
|
|
REQUIRE(v2.size() == 2);
|
|
|
|
WHEN("Comparing them") {
|
|
bool equals = v1 == v2;
|
|
|
|
THEN("The result should be false") {
|
|
REQUIRE_FALSE(equals);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SCENARIO("Erasing an item removes it and moves the following ones forward",
|
|
"[vector]") {
|
|
GIVEN("Two vectors with almost identical items") {
|
|
Gedeng::Vector<int> v1;
|
|
Gedeng::Vector<int> v2;
|
|
|
|
v1.push_back(1);
|
|
v2.push_back(1);
|
|
|
|
v1.push_back(2);
|
|
v2.push_back(5);
|
|
|
|
v1.push_back(5);
|
|
|
|
v1.push_back(10);
|
|
v2.push_back(10);
|
|
|
|
REQUIRE(v1.size() == 4);
|
|
REQUIRE(v2.size() == 3);
|
|
|
|
WHEN("Comparing them") {
|
|
bool equals = v1 == v2;
|
|
|
|
THEN("The result should be false") {
|
|
REQUIRE_FALSE(equals);
|
|
}
|
|
}
|
|
|
|
WHEN("Erasing the different item") {
|
|
v1.erase(1);
|
|
bool equals = v1 == v2;
|
|
|
|
THEN("The result should be true") {
|
|
REQUIRE(equals);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SCENARIO("Copy Assignment", "[vector]") {
|
|
GIVEN("Two vectors with identical items") {
|
|
Gedeng::Vector<int> v1;
|
|
Gedeng::Vector<int> v2;
|
|
|
|
v1.push_back(1);
|
|
v2.push_back(1);
|
|
|
|
v1.push_back(5);
|
|
v2.push_back(5);
|
|
|
|
REQUIRE(v1.size() == 2);
|
|
REQUIRE(v2.size() == 2);
|
|
|
|
WHEN("Copy assigning the second vector to a third vector") {
|
|
Gedeng::Vector<int> v3;
|
|
v3 = v2;
|
|
|
|
THEN("All vectors should be identical") {
|
|
bool equals = v1 == v2 && v2 == v3 && v1 == v3;
|
|
REQUIRE(equals);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SCENARIO("Move Assignment", "[vector]") {
|
|
GIVEN("Two vectors with identical items") {
|
|
Gedeng::Vector<int> v1;
|
|
Gedeng::Vector<int> v2;
|
|
|
|
v1.push_back(1);
|
|
v2.push_back(1);
|
|
|
|
v1.push_back(5);
|
|
v2.push_back(5);
|
|
|
|
REQUIRE(v1.size() == 2);
|
|
REQUIRE(v2.size() == 2);
|
|
|
|
WHEN("Move assigning the second vector to a third vector") {
|
|
Gedeng::Vector<int> v3;
|
|
v3 = std::move(v2);
|
|
|
|
THEN("The first and third vector should be identical") {
|
|
bool equals = v1 == v3;
|
|
REQUIRE(equals);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SCENARIO("Reserve additional space", "[vector]") {
|
|
GIVEN("A vector with a given length") {
|
|
Gedeng::Vector<int> v(5);
|
|
|
|
REQUIRE(v.length() == 5);
|
|
|
|
WHEN("Reserving additional space") {
|
|
v.reserve(10);
|
|
|
|
THEN("The length has increased accordingly") {
|
|
REQUIRE(v.length() == 15);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SCENARIO("Resizing a vector", "[vector]") {
|
|
GIVEN("A vector with 3 items") {
|
|
Gedeng::Vector<int> v;
|
|
|
|
v.push_back(1);
|
|
v.push_back(2);
|
|
v.push_back(3);
|
|
|
|
Gedeng::Vector<int> target;
|
|
|
|
target.push_back(1);
|
|
target.push_back(2);
|
|
target.push_back(3);
|
|
target.push_back(0);
|
|
target.push_back(0);
|
|
|
|
WHEN("Resizing to 5") {
|
|
v.resize(5);
|
|
|
|
THEN("The size should be 5") {
|
|
REQUIRE(v.size() == 5);
|
|
}
|
|
|
|
THEN("2 new default items should've been added") {
|
|
bool equals = v == target;
|
|
REQUIRE(equals);
|
|
}
|
|
}
|
|
|
|
WHEN("Resizing to 1") {
|
|
v.resize(1);
|
|
|
|
THEN("The size should be 1") {
|
|
REQUIRE(v.size() == 1);
|
|
}
|
|
|
|
THEN("The remaining element should be correct") {
|
|
REQUIRE(v[0] == 1);
|
|
}
|
|
|
|
THEN("Adding the elements again produces the same result again") {
|
|
v.push_back(2);
|
|
v.push_back(3);
|
|
v.push_back(0);
|
|
v.push_back(0);
|
|
|
|
bool equals = v == target;
|
|
REQUIRE(equals);
|
|
}
|
|
}
|
|
|
|
WHEN("Resizing to 100") {
|
|
v.resize(100);
|
|
|
|
THEN("All 100 items should be accessible and modifyable") {
|
|
REQUIRE_NOTHROW(v[0] = 10.0);
|
|
REQUIRE_NOTHROW(v[99] = 10.0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SCENARIO("Non-default constructor", "[vector]") {
|
|
GIVEN("A class object with a non-default constructor") {
|
|
class NonDefault {
|
|
public:
|
|
NonDefault(int a) : a(a) {
|
|
}
|
|
|
|
int a;
|
|
};
|
|
|
|
WHEN("Creating a vector and adding an element") {
|
|
Gedeng::Vector<NonDefault> non_default_vector;
|
|
|
|
non_default_vector.push_back(NonDefault(1));
|
|
|
|
THEN("The element should be accessible as usual") {
|
|
REQUIRE(non_default_vector[0].a == 1);
|
|
}
|
|
}
|
|
|
|
WHEN("Creating a vector and resizing it") {
|
|
Gedeng::Vector<NonDefault> non_default_vector;
|
|
|
|
non_default_vector.resize(50, NonDefault(42));
|
|
|
|
THEN("The new elements should correspond to the passed padder") {
|
|
REQUIRE(non_default_vector[49].a == 42);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SCENARIO("Erase by swap", "[vector]") {
|
|
GIVEN("A vector with some elements") {
|
|
Gedeng::Vector<int> v(3);
|
|
v.push_back(1);
|
|
v.push_back(2);
|
|
v.push_back(3);
|
|
|
|
WHEN("Erasing-by-swap the first element") {
|
|
v.erase_by_swap(0);
|
|
|
|
THEN("The size should have decrease by one") {
|
|
REQUIRE(v.size() == 2);
|
|
}
|
|
|
|
THEN("The previously last element should now be the first") {
|
|
REQUIRE(v[0] == 3);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned int count = 0;
|
|
|
|
class ReferenceCounter {
|
|
public:
|
|
ReferenceCounter() {
|
|
count++;
|
|
}
|
|
|
|
ReferenceCounter(const ReferenceCounter &) {
|
|
count++;
|
|
}
|
|
|
|
ReferenceCounter(ReferenceCounter &&) {
|
|
count++;
|
|
}
|
|
|
|
ReferenceCounter &operator=(const ReferenceCounter &) {
|
|
return *this;
|
|
}
|
|
|
|
ReferenceCounter &operator=(ReferenceCounter &&) {
|
|
return *this;
|
|
}
|
|
|
|
~ReferenceCounter() {
|
|
count--;
|
|
}
|
|
};
|
|
|
|
SCENARIO("Constructors and Destructors are called as expected", "[vector]") {
|
|
GIVEN("A vector with a custom reference-counting class") {
|
|
|
|
Gedeng::Vector<ReferenceCounter> v(3);
|
|
v.push_back(ReferenceCounter());
|
|
v.push_back(ReferenceCounter());
|
|
v.push_back(ReferenceCounter());
|
|
|
|
REQUIRE(count == 3);
|
|
|
|
WHEN("Erasing the first element") {
|
|
v.erase(0);
|
|
|
|
THEN("The reference count should have decreased") {
|
|
REQUIRE(count == 2);
|
|
}
|
|
}
|
|
|
|
WHEN("Erasing by swap") {
|
|
v.erase_by_swap(0);
|
|
|
|
THEN("The reference count should have decreased") {
|
|
REQUIRE(count == 2);
|
|
}
|
|
}
|
|
|
|
WHEN("Resizing to 1") {
|
|
v.resize(1);
|
|
|
|
THEN("The reference count should be 1") {
|
|
REQUIRE(count == 1);
|
|
}
|
|
}
|
|
|
|
WHEN("Resizing to 10") {
|
|
v.resize(10);
|
|
|
|
THEN("The reference count should be 10") {
|
|
REQUIRE(count == 10);
|
|
}
|
|
}
|
|
|
|
WHEN("Move-constructing another vector") {
|
|
Gedeng::Vector<ReferenceCounter> v2 = std::move(v);
|
|
|
|
THEN("The reference count should have remained the same") {
|
|
REQUIRE(count == 3);
|
|
}
|
|
}
|
|
}
|
|
}
|