Coverage Report

Created: 2024-07-18 11:41

test/zserio/AllocatorPropagatingCopyTest.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <algorithm>
2
3
#include "gtest/gtest.h"
4
#include "zserio/AllocatorPropagatingCopy.h"
5
#include "zserio/AnyHolder.h"
6
#include "zserio/NoInit.h"
7
#include "zserio/OptionalHolder.h"
8
9
#include "TrackingAllocator.h"
10
11
namespace zserio
12
{
13
14
namespace
15
{
16
17
class RegularType
18
{};
19
20
class RegularTypeWithStdAllocator
21
{
22
public:
23
    using allocator_type = std::allocator<RegularTypeWithStdAllocator>;
24
25
    allocator_type get_allocator() const
26
1
    {
27
1
        return m_allocator;
28
1
    }
29
30
    explicit RegularTypeWithStdAllocator(const allocator_type& allocator = allocator_type()) :
31
            m_allocator(allocator)
32
1
    {}
33
34
    RegularTypeWithStdAllocator(const RegularTypeWithStdAllocator&, const allocator_type& allocator) :
35
            m_allocator(allocator)
36
1
    {}
37
38
private:
39
    allocator_type m_allocator;
40
};
41
42
class RegularWithAllocatorSupport
43
{
44
public:
45
    using allocator_type = TrackingAllocatorNonProp<RegularWithAllocatorSupport>;
46
    using AllocTraits = std::allocator_traits<allocator_type>;
47
48
    allocator_type get_allocator() const
49
13
    {
50
13
        return m_allocator;
51
13
    }
52
53
    explicit RegularWithAllocatorSupport(const allocator_type& allocator = allocator_type()) :
54
            m_allocator(allocator)
55
6
    {}
56
57
22
    ~RegularWithAllocatorSupport() = default;
58
59
    RegularWithAllocatorSupport(const RegularWithAllocatorSupport& other) :
60
            m_allocator(AllocTraits::select_on_container_copy_construction(other.m_allocator))
61
1
    {}
62
63
    RegularWithAllocatorSupport& operator=(const RegularWithAllocatorSupport&) = delete;
64
65
9
    RegularWithAllocatorSupport(RegularWithAllocatorSupport&&) = default;
66
67
    RegularWithAllocatorSupport& operator=(RegularWithAllocatorSupport&&) = delete;
68
69
    RegularWithAllocatorSupport(
70
            PropagateAllocatorT, const RegularWithAllocatorSupport&, const allocator_type& allocator) :
71
            m_allocator(allocator)
72
6
    {}
73
74
private:
75
    allocator_type m_allocator;
76
};
77
78
class RegularWithAllocatorSupportNoInit
79
{
80
public:
81
    using allocator_type = TrackingAllocatorNonProp<RegularWithAllocatorSupportNoInit>;
82
    using AllocTraits = std::allocator_traits<allocator_type>;
83
84
    allocator_type get_allocator() const
85
8
    {
86
8
        return m_allocator;
87
8
    }
88
89
    explicit RegularWithAllocatorSupportNoInit(const allocator_type& allocator = allocator_type()) :
90
            m_allocator(allocator)
91
4
    {}
92
93
17
    ~RegularWithAllocatorSupportNoInit() = default;
94
95
    RegularWithAllocatorSupportNoInit(const RegularWithAllocatorSupportNoInit&)
96
0
    {
97
        // must be present for proper compilation
98
0
        EXPECT_TRUE(false);
99
0
    }
100
101
    RegularWithAllocatorSupportNoInit(NoInitT, const RegularWithAllocatorSupportNoInit& other) :
102
            m_allocator(AllocTraits::select_on_container_copy_construction(other.m_allocator))
103
1
    {}
104
105
    RegularWithAllocatorSupportNoInit& operator=(const RegularWithAllocatorSupportNoInit&) = delete;
106
107
    RegularWithAllocatorSupportNoInit(RegularWithAllocatorSupportNoInit&&)
108
0
    {
109
        // must be present for proper compilation
110
0
        EXPECT_TRUE(false);
111
0
    }
112
113
    RegularWithAllocatorSupportNoInit(NoInitT, RegularWithAllocatorSupportNoInit&& other) :
114
            m_allocator(other.m_allocator)
115
8
    {}
116
117
    RegularWithAllocatorSupportNoInit& operator=(RegularWithAllocatorSupportNoInit&&) = delete;
118
119
    RegularWithAllocatorSupportNoInit(PropagateAllocatorT, NoInitT, const RegularWithAllocatorSupportNoInit&,
120
            const allocator_type& allocator) :
121
            m_allocator(allocator)
122
4
    {}
123
124
private:
125
    allocator_type m_allocator;
126
};
127
128
} // namespace
129
130
TEST(AllocatorPropagatingCopyTest, copyDefault)
131
1
{
132
    // not much things to be tested here - just make sure that it compiles
133
1
    std::allocator<RegularType> allocator;
134
1
    const RegularType thing;
135
1
    RegularType thingCopy(allocatorPropagatingCopy(thing, allocator));
136
1
    static_cast<void>(thingCopy);
137
1
}
138
139
TEST(AllocatorPropagatingCopyTest, copyDefaultStdAllocator)
140
1
{
141
1
    RegularTypeWithStdAllocator::allocator_type allocator;
142
1
    const RegularTypeWithStdAllocator thing(allocator);
143
1
    RegularTypeWithStdAllocator thingCopy(allocatorPropagatingCopy(thing, allocator));
144
1
    ASSERT_EQ(allocator, thingCopy.get_allocator());
145
1
}
146
147
TEST(AllocatorPropagatingCopyTest, copyDefaultAllocator)
148
1
{
149
1
    RegularWithAllocatorSupport::allocator_type allocator;
150
1
    const RegularWithAllocatorSupport thing(allocator);
151
1
    RegularWithAllocatorSupport thingCopy(allocatorPropagatingCopy(thing, allocator));
152
1
    ASSERT_EQ(allocator, thingCopy.get_allocator());
153
1
    RegularWithAllocatorSupport thingCopy2(thingCopy);
154
1
    ASSERT_NE(thingCopy.get_allocator(), thingCopy2.get_allocator());
155
1
}
156
157
TEST(AllocatorPropagatingCopyTest, copyDefaultAllocatorNoInit)
158
1
{
159
1
    RegularWithAllocatorSupportNoInit::allocator_type allocator;
160
1
    const RegularWithAllocatorSupportNoInit thing(allocator);
161
1
    RegularWithAllocatorSupportNoInit thingCopy(NoInit, allocatorPropagatingCopy(NoInit, thing, allocator));
162
1
    ASSERT_EQ(allocator, thingCopy.get_allocator());
163
1
    RegularWithAllocatorSupportNoInit thingCopy2(NoInit, thing);
164
1
    ASSERT_NE(allocator, thingCopy2.get_allocator());
165
1
}
166
167
TEST(AllocatorPropagatingCopyTest, copyHeapOptional)
168
1
{
169
1
    RegularWithAllocatorSupport::allocator_type allocator;
170
171
1
    const HeapOptionalHolder<RegularWithAllocatorSupport, RegularWithAllocatorSupport::allocator_type>
172
1
            emptyOptional(allocator);
173
1
    HeapOptionalHolder<RegularWithAllocatorSupport, RegularWithAllocatorSupport::allocator_type>
174
1
            emptyOptionalCopy(allocatorPropagatingCopy(emptyOptional, allocator));
175
1
    ASSERT_EQ(emptyOptional.get_allocator(), emptyOptionalCopy.get_allocator());
176
177
1
    const HeapOptionalHolder<RegularWithAllocatorSupport, RegularWithAllocatorSupport::allocator_type> optional(
178
1
            RegularWithAllocatorSupport(allocator), allocator);
179
1
    HeapOptionalHolder<RegularWithAllocatorSupport, RegularWithAllocatorSupport::allocator_type> optionalCopy(
180
1
            allocatorPropagatingCopy(optional, allocator));
181
1
    ASSERT_EQ(optional.get_allocator(), optionalCopy.get_allocator());
182
1
    ASSERT_TRUE(optionalCopy.hasValue());
183
1
    ASSERT_EQ(optional->get_allocator(), optionalCopy->get_allocator());
184
1
}
185
186
TEST(AllocatorPropagatingCopyTest, copyHeapOptionalNoInit)
187
1
{
188
1
    RegularWithAllocatorSupportNoInit::allocator_type allocator;
189
190
1
    const HeapOptionalHolder<RegularWithAllocatorSupportNoInit,
191
1
            RegularWithAllocatorSupportNoInit::allocator_type>
192
1
            emptyOptional(allocator);
193
1
    HeapOptionalHolder<RegularWithAllocatorSupportNoInit, RegularWithAllocatorSupportNoInit::allocator_type>
194
1
            emptyOptionalCopy(NoInit, allocatorPropagatingCopy(NoInit, emptyOptional, allocator));
195
1
    ASSERT_EQ(emptyOptional.get_allocator(), emptyOptionalCopy.get_allocator());
196
197
1
    const HeapOptionalHolder<RegularWithAllocatorSupportNoInit,
198
1
            RegularWithAllocatorSupportNoInit::allocator_type>
199
1
            optional(allocator, allocator);
200
1
    HeapOptionalHolder<RegularWithAllocatorSupportNoInit, RegularWithAllocatorSupportNoInit::allocator_type>
201
1
            optionalCopy(NoInit, allocatorPropagatingCopy(NoInit, optional, allocator));
202
1
    ASSERT_EQ(optional.get_allocator(), optionalCopy.get_allocator());
203
1
    ASSERT_TRUE(optionalCopy.hasValue());
204
1
    ASSERT_EQ(optional->get_allocator(), optionalCopy->get_allocator());
205
1
}
206
207
TEST(AllocatorPropagatingCopyTest, copyInplaceOptional)
208
1
{
209
1
    RegularWithAllocatorSupport::allocator_type allocator;
210
211
1
    const InplaceOptionalHolder<RegularWithAllocatorSupport> emptyOptional{};
212
1
    InplaceOptionalHolder<RegularWithAllocatorSupport> emptyOptionalCopy(
213
1
            allocatorPropagatingCopy(emptyOptional, allocator));
214
215
1
    const InplaceOptionalHolder<RegularWithAllocatorSupport> optional{RegularWithAllocatorSupport(allocator)};
216
1
    InplaceOptionalHolder<RegularWithAllocatorSupport> optionalCopy(
217
1
            allocatorPropagatingCopy(optional, allocator));
218
1
    ASSERT_TRUE(optionalCopy.hasValue());
219
1
    ASSERT_EQ(optional->get_allocator(), optionalCopy->get_allocator());
220
1
}
221
222
TEST(AllocatorPropagatingCopyTest, copyInplaceOptionalNoInit)
223
1
{
224
1
    RegularWithAllocatorSupportNoInit::allocator_type allocator;
225
226
1
    const InplaceOptionalHolder<RegularWithAllocatorSupportNoInit> emptyOptional{};
227
1
    InplaceOptionalHolder<RegularWithAllocatorSupportNoInit> emptyOptionalCopy(
228
1
            NoInit, allocatorPropagatingCopy(NoInit, emptyOptional, allocator));
229
230
1
    const InplaceOptionalHolder<RegularWithAllocatorSupportNoInit> optional{InPlace, allocator};
231
1
    InplaceOptionalHolder<RegularWithAllocatorSupportNoInit> optionalCopy(
232
1
            NoInit, allocatorPropagatingCopy(NoInit, optional, allocator));
233
1
    ASSERT_TRUE(optionalCopy.hasValue());
234
1
    ASSERT_EQ(optional->get_allocator(), optionalCopy->get_allocator());
235
1
}
236
237
TEST(AllocatorPropagatingCopyTest, copyAny)
238
1
{
239
1
    const TrackingAllocatorNonProp<uint8_t> allocator;
240
241
1
    const AnyHolder<TrackingAllocatorNonProp<uint8_t>> emptyAny(allocator);
242
1
    AnyHolder<TrackingAllocatorNonProp<uint8_t>> emptyAnyCopy(
243
1
            allocatorPropagatingCopy<RegularWithAllocatorSupport>(emptyAny, allocator));
244
245
1
    const AnyHolder<TrackingAllocatorNonProp<uint8_t>> any(RegularWithAllocatorSupport(allocator), allocator);
246
1
    AnyHolder<TrackingAllocatorNonProp<uint8_t>> anyCopy(
247
1
            allocatorPropagatingCopy<RegularWithAllocatorSupport>(any, allocator));
248
1
    ASSERT_EQ(any.get_allocator(), anyCopy.get_allocator());
249
1
    ASSERT_TRUE(anyCopy.hasValue());
250
1
    ASSERT_TRUE(anyCopy.isType<RegularWithAllocatorSupport>());
251
1
    ASSERT_EQ(any.get<RegularWithAllocatorSupport>().get_allocator(),
252
1
            anyCopy.get<RegularWithAllocatorSupport>().get_allocator());
253
1
}
254
255
TEST(AllocatorPropagatingCopyTest, copyAnyNoInit)
256
1
{
257
1
    const TrackingAllocatorNonProp<uint8_t> allocator;
258
259
1
    const AnyHolder<TrackingAllocatorNonProp<uint8_t>> emptyAny(allocator);
260
261
1
    AnyHolder<TrackingAllocatorNonProp<uint8_t>> emptyAnyCopy(
262
1
            NoInit, allocatorPropagatingCopy<RegularWithAllocatorSupportNoInit>(NoInit, emptyAny, allocator));
263
264
1
    const AnyHolder<TrackingAllocatorNonProp<uint8_t>> any(
265
1
            NoInit, RegularWithAllocatorSupportNoInit(allocator), allocator);
266
1
    AnyHolder<TrackingAllocatorNonProp<uint8_t>> anyCopy(
267
1
            NoInit, allocatorPropagatingCopy<RegularWithAllocatorSupportNoInit>(NoInit, any, allocator));
268
1
    ASSERT_EQ(any.get_allocator(), anyCopy.get_allocator());
269
1
    ASSERT_TRUE(anyCopy.hasValue());
270
1
    ASSERT_TRUE(anyCopy.isType<RegularWithAllocatorSupportNoInit>());
271
1
    ASSERT_EQ(any.get<RegularWithAllocatorSupportNoInit>().get_allocator(),
272
1
            anyCopy.get<RegularWithAllocatorSupportNoInit>().get_allocator());
273
1
}
274
275
TEST(AllocatorPropagatingCopyTest, copyVector)
276
1
{
277
1
    RegularWithAllocatorSupport::allocator_type allocator;
278
279
1
    const std::vector<RegularWithAllocatorSupport, RegularWithAllocatorSupport::allocator_type> emptyVec(
280
1
            allocator);
281
1
    std::vector<RegularWithAllocatorSupport, RegularWithAllocatorSupport::allocator_type> emptyVecCopy(
282
1
            allocatorPropagatingCopy(emptyVec, allocator));
283
1
    ASSERT_EQ(emptyVec.get_allocator(), emptyVecCopy.get_allocator());
284
285
1
    std::vector<RegularWithAllocatorSupport, RegularWithAllocatorSupport::allocator_type> vec(allocator);
286
1
    vec.emplace_back(allocator);
287
1
    vec.emplace_back(allocator);
288
1
    std::vector<RegularWithAllocatorSupport, RegularWithAllocatorSupport::allocator_type> vecCopy(
289
1
            allocatorPropagatingCopy(vec, allocator));
290
1
    ASSERT_EQ(vec.get_allocator(), vecCopy.get_allocator());
291
1
    ASSERT_EQ(vec.size(), vecCopy.size());
292
1
    ASSERT_TRUE(std::equal(vec.begin(), vec.end(), vecCopy.begin(),
293
1
            [](const RegularWithAllocatorSupport& lhs, const RegularWithAllocatorSupport& rhs) {
294
1
                return lhs.get_allocator() == rhs.get_allocator();
295
1
            }));
296
1
}
297
298
TEST(AllocatorPropagatingCopyTest, copyVectorRegular)
299
1
{
300
1
    std::allocator<RegularType> allocator;
301
302
1
    const std::vector<RegularType> emptyVec(allocator);
303
1
    std::vector<RegularType> emptyVecCopy(allocatorPropagatingCopy(emptyVec, allocator));
304
1
    ASSERT_EQ(emptyVec.get_allocator(), emptyVecCopy.get_allocator());
305
1
}
306
307
TEST(AllocatorPropagatingCopyTest, copyString)
308
1
{
309
1
    TrackingAllocatorNonProp<char> allocator;
310
311
1
    const std::basic_string<char, std::char_traits<char>, TrackingAllocatorNonProp<char>> emptyString(
312
1
            allocator);
313
1
    std::basic_string<char, std::char_traits<char>, TrackingAllocatorNonProp<char>> emptyStringCopy(
314
1
            allocatorPropagatingCopy(emptyString, allocator));
315
1
    ASSERT_EQ(emptyString.get_allocator(), emptyStringCopy.get_allocator());
316
1
}
317
318
} // namespace zserio