mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-06-04 11:14:17 +08:00
199 lines
5.7 KiB
C++
199 lines
5.7 KiB
C++
#include <catch2/catch_test_macros.hpp>
|
|
|
|
#include <libslic3r/libslic3r.h>
|
|
#include <libslic3r/AnyPtr.hpp>
|
|
#include <test_utils.hpp>
|
|
|
|
class Foo
|
|
{
|
|
public:
|
|
virtual ~Foo() = default;
|
|
|
|
virtual void set_foo(int) = 0;
|
|
virtual int get_foo() const = 0;
|
|
};
|
|
|
|
class Bar: public Foo
|
|
{
|
|
int m_i = 0;
|
|
|
|
public:
|
|
virtual void set_foo(int i) { m_i = i; }
|
|
virtual int get_foo() const { return m_i; };
|
|
};
|
|
|
|
class BarPlus: public Foo {
|
|
int m_i = 0;
|
|
|
|
public:
|
|
virtual void set_foo(int i) { m_i = i + 1; }
|
|
virtual int get_foo() const { return m_i; };
|
|
};
|
|
|
|
TEST_CASE("Testing AnyPtr", "[anyptr]") {
|
|
using Slic3r::AnyPtr;
|
|
|
|
SECTION("Construction with various valid arguments using operator=")
|
|
{
|
|
auto args = std::make_tuple(nullptr,
|
|
AnyPtr<Foo>{nullptr},
|
|
AnyPtr{static_cast<Foo *>(nullptr)},
|
|
AnyPtr{static_cast<Bar *>(nullptr)},
|
|
AnyPtr{static_cast<BarPlus *>(nullptr)},
|
|
AnyPtr<Foo>{},
|
|
AnyPtr<Bar>{},
|
|
AnyPtr<BarPlus>{},
|
|
static_cast<Foo *>(nullptr),
|
|
static_cast<Bar *>(nullptr),
|
|
static_cast<BarPlus *>(nullptr));
|
|
|
|
auto check_ptr = [](auto &ptr) {
|
|
REQUIRE(!ptr);
|
|
REQUIRE(!ptr.is_owned());
|
|
|
|
auto shp = ptr.get_shared_cpy();
|
|
REQUIRE(!shp);
|
|
};
|
|
|
|
SECTION("operator =") {
|
|
Slic3r::for_each_in_tuple([&check_ptr](auto &arg){
|
|
AnyPtr<const Foo> ptr = std::move(arg);
|
|
|
|
check_ptr(ptr);
|
|
}, args);
|
|
}
|
|
|
|
SECTION("move construction")
|
|
{
|
|
Slic3r::for_each_in_tuple([&check_ptr](auto &arg){
|
|
AnyPtr<const Foo> ptr{std::move(arg)};
|
|
|
|
check_ptr(ptr);
|
|
}, args);
|
|
}
|
|
}
|
|
|
|
GIVEN("A polymorphic base class type Foo") {
|
|
WHEN("Creating a subclass on the stack") {
|
|
Bar bar;
|
|
auto val = random_value(-100, 100);
|
|
bar.set_foo(val);
|
|
|
|
THEN("Storing a raw pointer in an AnyPtr<Foo> should be valid "
|
|
"until the object is not destroyed")
|
|
{
|
|
AnyPtr<Foo> ptr = &bar;
|
|
auto val2 = random_value(-100, 100);
|
|
ptr->set_foo(val2);
|
|
|
|
REQUIRE(ptr->get_foo() == val2);
|
|
}
|
|
|
|
THEN("Storing a raw pointer in an AnyPtr<const Foo> should be "
|
|
"valid until the object is not destroyed")
|
|
{
|
|
AnyPtr<const Foo> ptr{&bar};
|
|
|
|
REQUIRE(ptr->get_foo() == val);
|
|
}
|
|
}
|
|
}
|
|
|
|
GIVEN("An empty AnyPtr of type Foo")
|
|
{
|
|
AnyPtr<Foo> ptr;
|
|
|
|
WHEN("Re-assigning a new unique_ptr of object of type Bar to ptr")
|
|
{
|
|
auto bar = std::make_unique<Bar>();
|
|
auto val = random_value(-100, 100);
|
|
|
|
bar->set_foo(val);
|
|
|
|
ptr = std::move(bar);
|
|
|
|
THEN("the ptr should contain the new object and should own it")
|
|
{
|
|
REQUIRE(ptr->get_foo() == val);
|
|
REQUIRE(ptr.is_owned());
|
|
}
|
|
}
|
|
|
|
WHEN("Re-assigning a new unique_ptr of object of type BarPlus to ptr")
|
|
{
|
|
auto barplus = std::make_unique<BarPlus>();
|
|
auto val = random_value(-100, 100);
|
|
|
|
barplus->set_foo(val);
|
|
|
|
ptr = std::move(barplus);
|
|
|
|
THEN("the ptr should contain the new object and should own it")
|
|
{
|
|
REQUIRE(ptr->get_foo() == val + 1);
|
|
REQUIRE(ptr.is_owned());
|
|
}
|
|
|
|
THEN("copying the stored object into a shared_ptr should be invalid")
|
|
{
|
|
std::shared_ptr<Foo> shptr = ptr.get_shared_cpy();
|
|
|
|
REQUIRE(!shptr);
|
|
}
|
|
|
|
THEN("copying the stored object into a shared_ptr after calling "
|
|
"convert_unique_to_shared should be valid")
|
|
{
|
|
ptr.convert_unique_to_shared();
|
|
std::shared_ptr<Foo> shptr = ptr.get_shared_cpy();
|
|
|
|
REQUIRE(shptr);
|
|
REQUIRE(shptr->get_foo() == val + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
GIVEN("A vector of AnyPtr<Foo> pointer to random Bar or BarPlus objects")
|
|
{
|
|
std::vector<AnyPtr<Foo>> ptrs;
|
|
|
|
auto N = random_value(size_t(1), size_t(10));
|
|
INFO("N = " << N);
|
|
|
|
std::generate_n(std::back_inserter(ptrs), N, []{
|
|
auto v = random_value(0, 1);
|
|
|
|
std::unique_ptr<Foo> ret;
|
|
|
|
if (v)
|
|
ret = std::make_unique<Bar>();
|
|
else
|
|
ret = std::make_unique<BarPlus>();
|
|
|
|
return ret;
|
|
});
|
|
|
|
WHEN("moving the whole array into a vector of AnyPtr<const Foo>")
|
|
{
|
|
THEN("the move should be valid")
|
|
{
|
|
std::vector<AnyPtr<const Foo>> constptrs;
|
|
std::vector<int> vals;
|
|
std::transform(ptrs.begin(), ptrs.end(),
|
|
std::back_inserter(vals),
|
|
[](auto &p) { return p->get_foo(); });
|
|
|
|
std::move(ptrs.begin(), ptrs.end(), std::back_inserter(constptrs));
|
|
|
|
REQUIRE(constptrs.size() == N);
|
|
REQUIRE(ptrs.size() == N);
|
|
REQUIRE(std::all_of(ptrs.begin(), ptrs.end(), [](auto &p) { return !p; }));
|
|
|
|
for (size_t i = 0; i < N; ++i) {
|
|
REQUIRE(vals[i] == constptrs[i]->get_foo());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|