// // copy_ptr.t.h // pointers // // Created by Sam Jaffe on 1/5/17. // #pragma once #include #include #include "value_ptr.hpp" struct copy_me {}; struct copy_me_throw {}; namespace detail { template<> class value_ptr_copy { protected: copy_me_throw * Copy(copy_me_throw const * p) const { if (p == nullptr) { throw std::runtime_error{"NULL"}; } return new copy_me_throw{*p}; } }; } class copy_ptr_TestSuite : public CxxTest::TestSuite { private: class base { public: virtual ~base() {} virtual base* clone() const = 0; virtual int id() const = 0; }; class derived_0 : public base { public: static const constexpr int ID = 0; virtual base * clone() const override { return new derived_0; } virtual int id() const override { return ID; } }; class derived_1 : public base { public: static const constexpr int ID = 1; virtual base * clone() const override { return new derived_1; } virtual int id() const override { return ID; } }; public: void test_copy_new_obj() { value_ptr c1 { new copy_me }; value_ptr c2 { c1 }; TS_ASSERT_DIFFERS( c1.get(), c2.get() ); } void test_copy_with_nullptr() { value_ptr c1 { nullptr }; value_ptr c2 { c1 }; TS_ASSERT_EQUALS( c1.get(), nullptr ); TS_ASSERT_EQUALS( c1.get(), c2.get() ); } void test_copy_custom_func() { using ptr_t = value_ptr; ptr_t c1 { new copy_me_throw }; ptr_t c2 { c1 }; TS_ASSERT_DIFFERS( c1.get(), c2.get() ); } void test_copy_custom_func_with_nullptr() { using ptr_t = value_ptr; ptr_t c1 { nullptr }; TS_ASSERT_THROWS( ptr_t{ c1 }, std::runtime_error ); } void test_copy_object_is_deep_equals() { using vec_t = std::vector; vec_t my_vec = { 1, 3, 5, 3, 6, 1, 2, -1, 0 }; value_ptr c1{ new vec_t{ my_vec } }; TS_ASSERT_EQUALS( *c1, my_vec ); value_ptr c2{ c1 }; TS_ASSERT_EQUALS( *c2, *c1 ); } void test_clone_polymorpic_object() { using ptr_t = value_ptr; ptr_t c0 { new derived_0 }; TS_ASSERT_EQUALS( ptr_t( c0 )->id(), derived_0::ID); ptr_t c1 { new derived_1 }; TS_ASSERT_EQUALS( ptr_t( c1 )->id(), derived_1::ID); } void test_clone_polymorphic_with_nullptr() { using ptr_t = value_ptr; ptr_t c1 { nullptr }; ptr_t c2 { c1 }; TS_ASSERT_EQUALS( c1.get(), nullptr ); TS_ASSERT_EQUALS( c1.get(), c2.get() ); } void test_does_own() const { bool has_delete{false}; struct test_t { ~test_t() { _r = true; } bool & _r; }; test_t * test_struct = new test_t{has_delete}; TS_ASSERT_THROWS_NOTHING(value_ptr{ std::move(test_struct) }); TS_ASSERT_EQUALS(has_delete, true); } void test_does_own_temporary() const { bool has_delete{false}; struct test_t { ~test_t() { _r = true; } bool & _r; }; TS_ASSERT_THROWS_NOTHING(value_ptr{ new test_t{has_delete} }); TS_ASSERT_EQUALS(has_delete, true); } void test_does_copy_on_copy() const { int deleted{0}; struct test_t { ~test_t() { ++(*_r); } int * _r; }; { std::unique_ptr test_struct{new test_t{&deleted}}; TS_ASSERT_THROWS_NOTHING(value_ptr::copy_of( test_struct.get() )); TS_ASSERT_EQUALS(deleted, 1); } TS_ASSERT_EQUALS(deleted, 2); } };