Skip to content

Commit 65a4e10

Browse files
committed
Added tests for weak_ptr and fixed issues found
1 parent 53d02a2 commit 65a4e10

File tree

3 files changed

+212
-8
lines changed

3 files changed

+212
-8
lines changed

include/oup/observable_unique_ptr.hpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -288,25 +288,30 @@ bool operator!= (const observable_unique_ptr<T,Deleter>& first,
288288
*/
289289
template<typename T>
290290
class weak_ptr : private std::weak_ptr<T> {
291+
private:
292+
// Friendship is required for conversions.
293+
template<typename U>
294+
friend class weak_ptr;
295+
291296
public:
292297
// Import members from std::shared_ptr
293298
using typename std::weak_ptr<T>::element_type;
294299

295300
using std::weak_ptr<T>::reset;
296-
using std::weak_ptr<T>::swap;
301+
using std::weak_ptr<T>::expired;
297302

298303
/// Default constructor (null pointer).
299304
weak_ptr() = default;
300305

301306
/// Create a weak pointer from an owning pointer.
302-
weak_ptr(const observable_unique_ptr<T>& owner) : std::weak_ptr<T>(owner) {}
307+
weak_ptr(const observable_unique_ptr<T>& owner) noexcept : std::weak_ptr<T>(owner) {}
303308

304309
/// Copy an existing weak_ptr instance
305310
/** \param value The existing weak pointer to copy
306311
*/
307312
template<typename U>
308313
weak_ptr(const weak_ptr<U>& value) noexcept :
309-
std::weak_ptr<T>(static_cast<std::weak_ptr<U>&>(value)) {}
314+
std::weak_ptr<T>(static_cast<const std::weak_ptr<U>&>(value)) {}
310315

311316
/// Move from an existing weak_ptr instance
312317
/** \param value The existing weak pointer to move from
@@ -318,7 +323,7 @@ class weak_ptr : private std::weak_ptr<T> {
318323
std::weak_ptr<T>(std::move(static_cast<std::weak_ptr<U>&>(value))) {}
319324

320325
/// Point to another owning pointer.
321-
weak_ptr& operator=(const observable_unique_ptr<T>& owner) {
326+
weak_ptr& operator=(const observable_unique_ptr<T>& owner) noexcept {
322327
std::weak_ptr<T>::operator=(owner);
323328
return *this;
324329
}
@@ -354,12 +359,19 @@ class weak_ptr : private std::weak_ptr<T> {
354359
return std::weak_ptr<T>::lock().get();
355360
}
356361

362+
/// Swap the content of this pointer with that of another pointer.
363+
/** \param other The other pointer to swap with
364+
*/
365+
void swap(weak_ptr& other) noexcept {
366+
std::weak_ptr<T>::swap(other);
367+
}
368+
357369
// Copiable
358-
weak_ptr(const weak_ptr&) = default;
359-
weak_ptr& operator=(const weak_ptr&) = default;
370+
weak_ptr(const weak_ptr&) noexcept = default;
371+
weak_ptr& operator=(const weak_ptr&) noexcept = default;
360372
// Movable
361-
weak_ptr(weak_ptr&&) = default;
362-
weak_ptr& operator=(weak_ptr&&) = default;
373+
weak_ptr(weak_ptr&&) noexcept = default;
374+
weak_ptr& operator=(weak_ptr&&) noexcept = default;
363375
};
364376

365377

tests/runtime_tests.cpp

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,3 +416,192 @@ TEST_CASE("make observable", "[make_observable_unique]") {
416416

417417
REQUIRE(instances == 0);
418418
}
419+
420+
TEST_CASE("observer default constructor", "[observer_construction]") {
421+
{
422+
test_wptr ptr{};
423+
REQUIRE(instances == 0);
424+
REQUIRE(ptr.lock() == nullptr);
425+
REQUIRE(ptr.expired() == true);
426+
}
427+
428+
REQUIRE(instances == 0);
429+
}
430+
431+
TEST_CASE("observer nullptr constructor", "[observer_construction]") {
432+
{
433+
test_wptr ptr{nullptr};
434+
REQUIRE(instances == 0);
435+
REQUIRE(ptr.lock() == nullptr);
436+
REQUIRE(ptr.expired() == true);
437+
}
438+
439+
REQUIRE(instances == 0);
440+
}
441+
442+
TEST_CASE("observer move constructor", "[observer_construction]") {
443+
{
444+
test_ptr ptr_owner{new test_object};
445+
test_wptr ptr_orig{ptr_owner};
446+
{
447+
test_wptr ptr(std::move(ptr_orig));
448+
REQUIRE(instances == 1);
449+
REQUIRE(ptr.lock() != nullptr);
450+
REQUIRE(ptr.expired() == false);
451+
}
452+
453+
REQUIRE(instances == 1);
454+
}
455+
456+
REQUIRE(instances == 0);
457+
}
458+
459+
TEST_CASE("observer acquiring constructor", "[observer_construction]") {
460+
{
461+
test_ptr ptr_owner{new test_object};
462+
test_wptr ptr{ptr_owner};
463+
REQUIRE(instances == 1);
464+
REQUIRE(ptr.lock() != nullptr);
465+
REQUIRE(ptr.expired() == false);
466+
}
467+
468+
REQUIRE(instances == 0);
469+
}
470+
471+
TEST_CASE("observer implicit copy conversion constructor", "[observer_construction]") {
472+
{
473+
test_ptr_derived ptr_owner{new test_object_derived};
474+
test_wptr_derived ptr_orig{ptr_owner};
475+
{
476+
test_wptr ptr(ptr_orig);
477+
REQUIRE(instances == 1);
478+
REQUIRE(instances_derived == 1);
479+
REQUIRE(ptr.lock() != nullptr);
480+
REQUIRE(ptr.expired() == false);
481+
}
482+
483+
REQUIRE(instances == 1);
484+
REQUIRE(instances_derived == 1);
485+
REQUIRE(ptr_orig.lock() != nullptr);
486+
REQUIRE(ptr_orig.expired() == false);
487+
}
488+
489+
REQUIRE(instances == 0);
490+
REQUIRE(instances_derived == 0);
491+
}
492+
493+
TEST_CASE("observer implicit move conversion constructor", "[observer_construction]") {
494+
{
495+
test_ptr_derived ptr_owner{new test_object_derived};
496+
test_wptr_derived ptr_orig{ptr_owner};
497+
{
498+
test_wptr ptr(std::move(ptr_orig));
499+
REQUIRE(instances == 1);
500+
REQUIRE(instances_derived == 1);
501+
REQUIRE(ptr.lock() != nullptr);
502+
REQUIRE(ptr.expired() == false);
503+
}
504+
505+
REQUIRE(instances == 1);
506+
REQUIRE(instances_derived == 1);
507+
REQUIRE(ptr_orig.lock() == nullptr);
508+
REQUIRE(ptr_orig.expired() == true);
509+
}
510+
511+
REQUIRE(instances == 0);
512+
REQUIRE(instances_derived == 0);
513+
}
514+
515+
TEST_CASE("observer expiring", "[observer_utility]") {
516+
test_wptr ptr;
517+
518+
{
519+
test_ptr ptr_owner{new test_object};
520+
ptr = ptr_owner;
521+
REQUIRE(instances == 1);
522+
REQUIRE(ptr.lock() != nullptr);
523+
REQUIRE(ptr.expired() == false);
524+
}
525+
526+
REQUIRE(instances == 0);
527+
REQUIRE(ptr.lock() == nullptr);
528+
REQUIRE(ptr.expired() == true);
529+
}
530+
531+
TEST_CASE("observer reset to null", "[observer_utility]") {
532+
{
533+
test_ptr ptr_owner(new test_object);
534+
test_wptr ptr(ptr_owner);
535+
ptr.reset();
536+
REQUIRE(instances == 1);
537+
REQUIRE(ptr.lock() == nullptr);
538+
REQUIRE(ptr.expired() == true);
539+
}
540+
541+
REQUIRE(instances == 0);
542+
}
543+
544+
545+
TEST_CASE("observer swap no instance", "[observer_utility]") {
546+
{
547+
test_wptr ptr_orig;
548+
test_wptr ptr;
549+
ptr.swap(ptr_orig);
550+
REQUIRE(instances == 0);
551+
REQUIRE(ptr_orig.lock() == nullptr);
552+
REQUIRE(ptr.lock() == nullptr);
553+
REQUIRE(ptr_orig.expired() == true);
554+
REQUIRE(ptr.expired() == true);
555+
}
556+
557+
REQUIRE(instances == 0);
558+
}
559+
560+
TEST_CASE("observer swap one instance", "[observer_utility]") {
561+
{
562+
test_ptr ptr_owner(new test_object);
563+
test_wptr ptr_orig(ptr_owner);
564+
test_wptr ptr;
565+
ptr.swap(ptr_orig);
566+
REQUIRE(instances == 1);
567+
REQUIRE(ptr_orig.lock() == nullptr);
568+
REQUIRE(ptr.lock() != nullptr);
569+
REQUIRE(ptr_orig.expired() == true);
570+
REQUIRE(ptr.expired() == false);
571+
}
572+
573+
REQUIRE(instances == 0);
574+
}
575+
576+
TEST_CASE("observer swap two same instance", "[observer_utility]") {
577+
{
578+
test_ptr ptr_owner(new test_object);
579+
test_wptr ptr_orig(ptr_owner);
580+
test_wptr ptr(ptr_owner);
581+
ptr.swap(ptr_orig);
582+
REQUIRE(instances == 1);
583+
REQUIRE(ptr_orig.lock() == ptr_owner.get());
584+
REQUIRE(ptr.lock() == ptr_owner.get());
585+
REQUIRE(ptr_orig.expired() == false);
586+
REQUIRE(ptr.expired() == false);
587+
}
588+
589+
REQUIRE(instances == 0);
590+
}
591+
592+
TEST_CASE("observer swap two different instances", "[observer_utility]") {
593+
{
594+
test_ptr ptr_owner1(new test_object);
595+
test_ptr ptr_owner2(new test_object);
596+
test_wptr ptr_orig(ptr_owner1);
597+
test_wptr ptr(ptr_owner2);
598+
ptr.swap(ptr_orig);
599+
REQUIRE(instances == 2);
600+
REQUIRE(ptr_orig.lock() == ptr_owner2.get());
601+
REQUIRE(ptr.lock() == ptr_owner1.get());
602+
REQUIRE(ptr_orig.expired() == false);
603+
REQUIRE(ptr.expired() == false);
604+
}
605+
606+
REQUIRE(instances == 0);
607+
}

tests/tests_common.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,6 @@ using test_ptr_with_deleter = oup::observable_unique_ptr<test_object,test_delete
6262
using test_ptr_derived_with_deleter = oup::observable_unique_ptr<test_object_derived,test_deleter>;
6363
using test_ptr_thrower = oup::observable_unique_ptr<test_object_thrower>;
6464
using test_ptr_thrower_with_deleter = oup::observable_unique_ptr<test_object_thrower,test_deleter>;
65+
66+
using test_wptr = oup::weak_ptr<test_object>;
67+
using test_wptr_derived = oup::weak_ptr<test_object_derived>;

0 commit comments

Comments
 (0)