#include #include #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]") { Vector 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") { Vector 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") { Vector v1; Vector 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") { Vector v1; Vector 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") { Vector v1; Vector 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") { Vector v1; Vector 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") { Vector 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") { Vector v1; Vector 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") { Vector 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") { Vector 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") { Vector v; v.push_back(1); v.push_back(2); v.push_back(3); Vector 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") { Vector 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") { Vector 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") { Vector 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") { Vector 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") { Vector v2 = std::move(v); THEN("The reference count should have remained the same") { REQUIRE(count == 3); } } } }