File: test_anyptr.cpp

package info (click to toggle)
slic3r-prusa 2.9.2%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 196,524 kB
  • sloc: cpp: 534,736; ansic: 71,269; yacc: 1,311; makefile: 256; lex: 241; sh: 113
file content (198 lines) | stat: -rw-r--r-- 5,823 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#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());
                }
            }
        }
    }
}