Skip to content
Snippets Groups Projects
PtrVectorTest.cpp 4.52 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include <catch2/catch.hpp>
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    #include <alib/ptr_vector>
    #include <alib/algorithm>
    
    
    namespace {
    	enum class Type {
    		CHILD1,
    		CHILD2
    	};
    
    	class Base {
    		public:
    			virtual ~Base ( ) {
    			}
    
    			virtual Base * clone ( ) const = 0;
    			virtual Base * plunder ( ) && = 0;
    
    			virtual Type type ( ) const = 0;
    
    			bool operator == ( const Base & other ) const {
    				return this->type ( ) == other.type ( );
    			}
    
    	};
    
    	class Child1 : public Base {
    		public:
    
    			virtual Base * clone ( ) const override {
    
    				return new Child1 ( * this );
    			}
    
    
    			virtual Base * plunder ( ) && override {
    
    				return new Child1 ( * this );
    			}
    
    
    			virtual Type type ( ) const override {
    
    				return Type::CHILD1;
    			}
    	};
    
    	class Child2 : public Base {
    		public:
    
    			virtual Base * clone ( ) const override {
    
    				return new Child2 ( * this );
    			}
    
    
    			virtual Base * plunder ( ) && override {
    
    				return new Child2 ( * this );
    			}
    
    
    			virtual Type type ( ) const override {
    
    				return Type::CHILD2;
    			}
    	};
    
    	class Moveable {
    		int& m_moves;
    		int& m_copies;
    
    		public:
    		Moveable(int& moves, int& copies) : m_moves(moves), m_copies(copies) {
    			m_moves = 0;
    			m_copies = 0;
    		}
    
    		Moveable(const Moveable& src) : m_moves(src.m_moves), m_copies(src.m_copies) {
    			m_copies++;
    		}
    
    		Moveable(Moveable&& src) : m_moves(src.m_moves), m_copies(src.m_copies) {
    			m_moves++;
    		}
    
    		Moveable & operator = ( const Moveable & ) {
    			m_copies ++;
    			return * this;
    		}
    
    		Moveable & operator = ( Moveable && ) {
    			m_moves ++;
    			return * this;
    		}
    
    		bool operator<(const Moveable&) const {
    			return false;
    		}
    	};
    
    TEST_CASE ( "PtrVector", "[unit][std][container]" ) {
    	SECTION ( "Test Properties" ) {
    		ext::ptr_vector < int > data = {1, 2, 3, 4};
    
    		CHECK ( data [ 0 ] == 1 );
    		CHECK ( data.size ( ) == 4 );
    		CHECK ( data [ 3 ] == 4 );
    
    		int i = 1;
    		for ( int & content : data ) {
    			CHECK ( content == i ++ );
    		}
    		const ext::ptr_vector < int > & cdata = data;
    
    		i = 1;
    		for ( const int & content : cdata ) {
    			CHECK ( content == i ++ );
    		}
    
    
    		data.push_back ( 1 );
    		CHECK ( data.size ( ) == 5 );
    		CHECK ( data [ 4 ] == 1 );
    
    		data.insert ( data.cbegin ( ) + 1, 2 );
    		CHECK ( data.size ( ) == 6 );
    
    		CHECK ( data [ 0 ] == 1 );
    
    		CHECK ( data [ 1 ] == 2 );
    		CHECK ( data [ 2 ] == 2 );
    		CHECK ( data [ 3 ] == 3 );
    
    
    		auto iter1 = data.erase ( data.rbegin ( ) );
    		CHECK ( iter1 == data.rbegin ( ) );
    		auto iter2 = data.insert ( data.rbegin ( ), 2 );
    		CHECK ( iter2 == data.rbegin ( ) );
    
    	SECTION ( "Test Polymorphism" ) {
    		ext::ptr_vector < Base > data = { Child2 ( ) };
    
    		CHECK ( data [ 0 ].type ( ) == Type::CHILD2 );
    		CHECK ( data.size ( ) == 1 );
    
    		data.push_back ( Child1 ( ) );
    		CHECK ( data.size ( ) == 2 );
    		CHECK ( data [ 1 ].type ( ) == Type::CHILD1 );
    
    		ext::ptr_vector < Base >::const_iterator iter = data.cbegin ( );
    		CHECK ( iter->type ( ) == Type::CHILD2 );
    		++ iter;
    		CHECK ( iter->type ( ) == Type::CHILD1 );
    		++ iter;
    		CHECK ( iter == data.cend ( ) );
    
    		data.insert ( data.cbegin ( ) + 1, Child1 ( ) );
    		CHECK ( data.size ( ) == 3 );
    		CHECK ( data [ 0 ].type ( ) == Type::CHILD2 );
    		CHECK ( data [ 1 ].type ( ) == Type::CHILD1 );
    		CHECK ( data [ 2 ].type ( ) == Type::CHILD1 );
    
    		data.resize < Child2 > ( 4 );
    		CHECK ( data.at ( 3 ) == Child2 ( ) );
    		data.shrink ( 3 );
    
    		ext::ptr_vector < Base > data2 = data;
    
    		CHECK ( data2 [ 0 ].type ( ) == Type::CHILD2 );
    		CHECK ( data2 [ 1 ].type ( ) == Type::CHILD1 );
    		CHECK ( data2 [ 2 ].type ( ) == Type::CHILD1 );
    
    		auto iter2 = data2.insert ( data2.cbegin ( ) + 1, data.begin ( ), data.end ( ) );
    
    		CHECK ( iter2 == data2.begin ( ) + 1 );
    
    		CHECK ( data2 [ 0 ].type ( ) == Type::CHILD2 );
    		CHECK ( data2 [ 1 ].type ( ) == Type::CHILD2 );
    		CHECK ( data2 [ 2 ].type ( ) == Type::CHILD1 );
    		CHECK ( data2 [ 3 ].type ( ) == Type::CHILD1 );
    		CHECK ( data2 [ 4 ].type ( ) == Type::CHILD1 );
    		CHECK ( data2 [ 5 ].type ( ) == Type::CHILD1 );
    
    		data2.erase ( ext::dereferencer ( ext::unique ( data2.begin ( ).base ( ), data2.end ( ).base ( ), [ ] ( const Base * a, const Base * b ) { return * a == * b; } ) ), data2.end ( ) );
    	}
    
    	SECTION ( "Test Range" ) {
    		ext::ptr_vector < int > data { 1, 2, 3, 4 };
    		ext::ptr_vector < int > data2 ( data.range ( ) );
    
    		CHECK ( data == data2 );
    
    		int moves;
    		int copies;
    
    		ext::ptr_vector < Moveable > vec;
    		vec.push_back ( Moveable ( moves, copies ) );
    		vec.push_back ( Moveable ( moves, copies ) );
    		vec.push_back ( Moveable ( moves, copies ) );
    		vec.push_back ( Moveable ( moves, copies ) );
    
    		ext::ptr_vector < Moveable > vec2 ( ext::range ( std::move ( vec ) ) );
    
    		CHECK ( copies == 0 );
    	}