Mir

Merge lp:~afrantzis/mir/variable-length-serialization-buffers-1320187 into lp:mir

Proposed by Alexandros Frantzis
Status: Merged
Approved by: Alexandros Frantzis
Approved revision: no longer in the source branch.
Merged at revision: 1640
Proposed branch: lp:~afrantzis/mir/variable-length-serialization-buffers-1320187
Merge into: lp:mir
Diff against target: 511 lines (+311/-37)
11 files modified
include/shared/mir/variable_length_array.h (+64/-0)
src/client/rpc/mir_basic_rpc_channel.cpp (+6/-8)
src/server/frontend/event_sender.cpp (+9/-6)
src/server/frontend/protobuf_responder.cpp (+12/-8)
src/server/frontend/protobuf_responder.h (+0/-1)
src/server/frontend/socket_messenger.cpp (+8/-12)
src/server/frontend/socket_messenger.h (+0/-2)
tests/acceptance-tests/CMakeLists.txt (+1/-0)
tests/acceptance-tests/test_large_messages.cpp (+103/-0)
tests/unit-tests/CMakeLists.txt (+1/-0)
tests/unit-tests/test_variable_length_array.cpp (+107/-0)
To merge this branch: bzr merge lp:~afrantzis/mir/variable-length-serialization-buffers-1320187
Reviewer Review Type Date Requested Status
Alberto Aguirre (community) Approve
Robert Carr (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Andreas Pokorny (community) Approve
Alan Griffiths Approve
Review via email: mp+219878@code.launchpad.net

Commit message

frontend,rpc: Ensure serialization buffers are always capable of fitting sent/received messages

Description of the change

frontend,rpc: Ensure serialization buffers are always capable of fitting sent/received messages

... while keeping the amount of heap allocations low.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

What is the purpose of connection_to_server_with_large_display_configuration_succeeds in test_large_messages.cpp?

review: Needs Information
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> What is the purpose of
> connection_to_server_with_large_display_configuration_succeeds in
> test_large_messages.cpp?

Clarified purpose of test in new comment:

370 +// Regression test for lp:1320187. Without a fix for that bug, connecting
371 +// to a server with a lot of information in the display configuration hangs
372 +// the client, because the server reply message is incomplete/corrupted.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

59 + static void heap_deleter(unsigned char* b) { if (b != nullptr) delete[] b; }

It is safe to call delete[] with nullptr (and doing so avoids the test here as well as in the library)

~~~~

345 +struct LargeMessages : mir_test_framework::InProcessServer
346 +{
347 + LargeMessagesServerConfiguration large_messages_server_config;
348 +
349 + mir::DefaultServerConfiguration& server_config() override
350 + {
351 + return large_messages_server_config;
352 + }
353 +};
354
355 +struct ConnectionContext
356 +{
357 + mt::WaitObject connected;
358 + MirConnection* connection{nullptr};
359 +};
360 +
361 +void connection_callback(MirConnection* connection, void* context)
362 +{
363 + auto connection_context = static_cast<ConnectionContext*>(context);
364 + connection_context->connection = connection;
365 + connection_context->connected.notify_ready();
366 +}

You could avoid this (and some related code in the test body) by:

using LargeMessages = mir_test_framework::BasicClientServerFixture<LargeMessagesServerConfiguration>;

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

> > What is the purpose of
> > connection_to_server_with_large_display_configuration_succeeds in
> > test_large_messages.cpp?
>
> Clarified purpose of test in new comment:
>
> 370 +// Regression test for lp:1320187. Without a fix for that bug,
> connecting
> 371 +// to a server with a lot of information in the display configuration
> hangs
> 372 +// the client, because the server reply message is
> incomplete/corrupted.

oh, ok.

review: Approve
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> It is safe to call delete[] with nullptr (and doing so avoids the test here as well as in the library)

Fixed.

> You could avoid this (and some related code in the test body) by:
> using LargeMessages = mir_test_framework::BasicClientServerFixture<LargeMessagesServerConfiguration>;

Without the fix, the client hangs indefinitely in mir_connect, so I need to make the connect call async to be able to make the test fail after a reasonable amount of time.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> > You could avoid this (and some related code in the test body) by:
> > using LargeMessages = mir_test_framework::BasicClientServerFixture<LargeMess
> agesServerConfiguration>;
>
> Without the fix, the client hangs indefinitely in mir_connect, so I need to
> make the connect call async to be able to make the test fail after a
> reasonable amount of time.

I see. I guess this is too "clever"...

template<>
void BasicClientServerFixture<LargeMessagesServerConfiguration>::SetUp()
{
    InProcessServer::SetUp();
    // async connect with timeout
}

...OTOH maybe changing BasicClientServerFixture to timeout & fail instead of hang is a good idea for the general case.

Anyway I'm still approving as is. ;)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) :
review: Approve
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'include/shared/mir/variable_length_array.h'
2--- include/shared/mir/variable_length_array.h 1970-01-01 00:00:00 +0000
3+++ include/shared/mir/variable_length_array.h 2014-05-19 12:37:31 +0000
4@@ -0,0 +1,64 @@
5+/*
6+ * Copyright © 2014 Canonical Ltd.
7+ *
8+ * This program is free software: you can redistribute it and/or modify
9+ * it under the terms of the GNU Lesser General Public License version 3 as
10+ * published by the Free Software Foundation.
11+ *
12+ * This program is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ * GNU Lesser General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU Lesser General Public License
18+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19+ *
20+ * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
21+ */
22+
23+#ifndef MIR_VARIABLE_LENGTH_ARRAY_H_
24+#define MIR_VARIABLE_LENGTH_ARRAY_H_
25+
26+#include <sys/types.h>
27+#include <memory>
28+
29+namespace mir
30+{
31+
32+template <size_t BuiltInBufferSize>
33+class VariableLengthArray
34+{
35+public:
36+ explicit VariableLengthArray(size_t size) : size_{size}
37+ {
38+ /* Don't call resize if the initial values of member variables are valid */
39+ if (size > BuiltInBufferSize) resize(size);
40+ }
41+
42+ void resize(size_t size)
43+ {
44+ if (size > BuiltInBufferSize)
45+ effective_buffer = BufferUPtr{new unsigned char[size], heap_deleter};
46+ else
47+ effective_buffer = BufferUPtr{builtin_buffer, null_deleter};
48+
49+ size_ = size;
50+ }
51+
52+ unsigned char* data() const { return effective_buffer.get(); }
53+ size_t size() const { return size_; }
54+
55+private:
56+ typedef std::unique_ptr<unsigned char,void (*)(unsigned char*)> BufferUPtr;
57+
58+ static void null_deleter(unsigned char*) {}
59+ static void heap_deleter(unsigned char* b) { delete[] b; }
60+
61+ unsigned char builtin_buffer[BuiltInBufferSize];
62+ BufferUPtr effective_buffer{builtin_buffer, null_deleter};
63+ size_t size_;
64+};
65+
66+}
67+
68+#endif /* MIR_VARIABLE_LENGTH_ARRAY_H_ */
69
70=== modified file 'src/client/rpc/mir_basic_rpc_channel.cpp'
71--- src/client/rpc/mir_basic_rpc_channel.cpp 2014-03-26 05:48:59 +0000
72+++ src/client/rpc/mir_basic_rpc_channel.cpp 2014-05-19 12:37:31 +0000
73@@ -21,6 +21,7 @@
74
75 #include "mir_protobuf_wire.pb.h"
76 #include "mir/frontend/client_constants.h"
77+#include "mir/variable_length_array.h"
78
79 #include <sstream>
80
81@@ -105,19 +106,16 @@
82 google::protobuf::MethodDescriptor const* method,
83 google::protobuf::Message const* request)
84 {
85- char buffer[mir::frontend::serialization_buffer_size];
86-
87- auto const size = request->ByteSize();
88- // In practice size will be 10s of bytes - but have a test to detect problems
89- assert(size < static_cast<decltype(size)>(sizeof buffer));
90-
91- request->SerializeToArray(buffer, sizeof buffer);
92+ mir::VariableLengthArray<mir::frontend::serialization_buffer_size>
93+ buffer{static_cast<size_t>(request->ByteSize())};
94+
95+ request->SerializeWithCachedSizesToArray(buffer.data());
96
97 mir::protobuf::wire::Invocation invoke;
98
99 invoke.set_id(next_id());
100 invoke.set_method_name(method->name());
101- invoke.set_parameters(buffer, size);
102+ invoke.set_parameters(buffer.data(), buffer.size());
103 invoke.set_protocol_version(1);
104
105 return invoke;
106
107=== modified file 'src/server/frontend/event_sender.cpp'
108--- src/server/frontend/event_sender.cpp 2014-03-26 05:48:59 +0000
109+++ src/server/frontend/event_sender.cpp 2014-05-19 12:37:31 +0000
110@@ -18,6 +18,7 @@
111
112 #include "mir/frontend/client_constants.h"
113 #include "mir/graphics/display_configuration.h"
114+#include "mir/variable_length_array.h"
115 #include "event_sender.h"
116 #include "message_sender.h"
117 #include "protobuf_buffer_packer.h"
118@@ -73,17 +74,19 @@
119
120 void mfd::EventSender::send_event_sequence(mp::EventSequence& seq)
121 {
122- std::string send_buffer;
123- send_buffer.reserve(serialization_buffer_size);
124- seq.SerializeToString(&send_buffer);
125+ mir::VariableLengthArray<frontend::serialization_buffer_size>
126+ send_buffer{static_cast<size_t>(seq.ByteSize())};
127+
128+ seq.SerializeWithCachedSizesToArray(send_buffer.data());
129
130 mir::protobuf::wire::Result result;
131- result.add_events(send_buffer);
132- result.SerializeToString(&send_buffer);
133+ result.add_events(send_buffer.data(), send_buffer.size());
134+ send_buffer.resize(result.ByteSize());
135+ result.SerializeWithCachedSizesToArray(send_buffer.data());
136
137 try
138 {
139- sender->send(send_buffer.data(), send_buffer.length(), {});
140+ sender->send(reinterpret_cast<char*>(send_buffer.data()), send_buffer.size(), {});
141 }
142 catch (std::exception const& error)
143 {
144
145=== modified file 'src/server/frontend/protobuf_responder.cpp'
146--- src/server/frontend/protobuf_responder.cpp 2014-03-26 05:48:59 +0000
147+++ src/server/frontend/protobuf_responder.cpp 2014-05-19 12:37:31 +0000
148@@ -20,6 +20,7 @@
149 #include "resource_cache.h"
150 #include "message_sender.h"
151 #include "mir/frontend/client_constants.h"
152+#include "mir/variable_length_array.h"
153 #include "socket_messenger.h"
154
155 namespace mfd = mir::frontend::detail;
156@@ -28,8 +29,7 @@
157 std::shared_ptr<MessageSender> const& sender,
158 std::shared_ptr<ResourceCache> const& resource_cache) :
159 sender(sender),
160- resource_cache(resource_cache),
161- send_response_buffer(serialization_buffer_size)
162+ resource_cache(resource_cache)
163 {
164 }
165
166@@ -38,13 +38,17 @@
167 google::protobuf::Message* response,
168 FdSets const& fd_sets)
169 {
170- response->SerializeToArray(send_response_buffer.data(), send_response_buffer.size());
171+ mir::VariableLengthArray<serialization_buffer_size>
172+ send_response_buffer{static_cast<size_t>(response->ByteSize())};
173+
174+ response->SerializeWithCachedSizesToArray(send_response_buffer.data());
175
176 send_response_result.set_id(id);
177- send_response_result.set_response(send_response_buffer.data(), response->ByteSize());
178-
179- send_response_result.SerializeToArray(send_response_buffer.data(), send_response_buffer.size());
180-
181- sender->send(send_response_buffer.data(), send_response_result.ByteSize(), fd_sets);
182+ send_response_result.set_response(send_response_buffer.data(), send_response_buffer.size());
183+
184+ send_response_buffer.resize(send_response_result.ByteSize());
185+ send_response_result.SerializeWithCachedSizesToArray(send_response_buffer.data());
186+
187+ sender->send(reinterpret_cast<char*>(send_response_buffer.data()), send_response_buffer.size(), fd_sets);
188 resource_cache->free_resource(response);
189 }
190
191=== modified file 'src/server/frontend/protobuf_responder.h'
192--- src/server/frontend/protobuf_responder.h 2014-03-26 05:48:59 +0000
193+++ src/server/frontend/protobuf_responder.h 2014-05-19 12:37:31 +0000
194@@ -50,7 +50,6 @@
195 std::shared_ptr<MessageSender> const sender;
196 std::shared_ptr<ResourceCache> const resource_cache;
197
198- std::vector<char> send_response_buffer;
199 mir::protobuf::wire::Result send_response_result;
200 };
201 }
202
203=== modified file 'src/server/frontend/socket_messenger.cpp'
204--- src/server/frontend/socket_messenger.cpp 2014-05-14 06:34:25 +0000
205+++ src/server/frontend/socket_messenger.cpp 2014-05-19 12:37:31 +0000
206@@ -19,6 +19,7 @@
207 #include "socket_messenger.h"
208 #include "mir/frontend/client_constants.h"
209 #include "mir/frontend/session_credentials.h"
210+#include "mir/variable_length_array.h"
211
212 #include <errno.h>
213 #include <string.h>
214@@ -33,7 +34,6 @@
215 mfd::SocketMessenger::SocketMessenger(std::shared_ptr<ba::local::stream_protocol::socket> const& socket)
216 : socket(socket)
217 {
218- whole_message.reserve(serialization_buffer_size);
219 }
220
221 mf::SessionCredentials mfd::SocketMessenger::client_creds()
222@@ -43,25 +43,21 @@
223
224 void mfd::SocketMessenger::send(char const* data, size_t length, FdSets const& fd_set)
225 {
226- const unsigned char header_bytes[2] =
227- {
228- static_cast<unsigned char>((length >> 8) & 0xff),
229- static_cast<unsigned char>((length >> 0) & 0xff)
230- };
231+ static size_t const header_size{2};
232+ mir::VariableLengthArray<mf::serialization_buffer_size> whole_message{header_size + length};
233+
234+ whole_message.data()[0] = static_cast<unsigned char>((length >> 8) & 0xff);
235+ whole_message.data()[1] = static_cast<unsigned char>((length >> 0) & 0xff);
236+ std::copy(data, data + length, whole_message.data() + header_size);
237
238 std::unique_lock<std::mutex> lg(message_lock);
239
240- whole_message.resize(sizeof header_bytes + length);
241- std::copy(header_bytes, header_bytes + sizeof header_bytes, whole_message.begin());
242- std::copy(data, data + length, whole_message.begin() + sizeof header_bytes);
243-
244-
245 // TODO: This should be asynchronous, but we are not making sure
246 // that a potential call to send_fds is executed _after_ this
247 // function has completed (if it would be executed asynchronously.
248 // NOTE: we rely on this synchronous behavior as per the comment in
249 // mf::SessionMediator::create_surface
250- ba::write(*socket, ba::buffer(whole_message));
251+ ba::write(*socket, ba::buffer(whole_message.data(), whole_message.size()));
252
253 for (auto const& fds : fd_set)
254 send_fds_locked(lg, fds);
255
256=== modified file 'src/server/frontend/socket_messenger.h'
257--- src/server/frontend/socket_messenger.h 2014-05-05 03:36:45 +0000
258+++ src/server/frontend/socket_messenger.h 2014-05-19 12:37:31 +0000
259@@ -45,8 +45,6 @@
260 std::shared_ptr<boost::asio::local::stream_protocol::socket> socket;
261
262 std::mutex message_lock;
263- std::vector<char> whole_message;
264-
265 void send_fds_locked(std::unique_lock<std::mutex> const& lock, std::vector<int32_t> const& fds);
266 };
267 }
268
269=== modified file 'tests/acceptance-tests/CMakeLists.txt'
270--- tests/acceptance-tests/CMakeLists.txt 2014-05-13 03:57:36 +0000
271+++ tests/acceptance-tests/CMakeLists.txt 2014-05-19 12:37:31 +0000
272@@ -33,6 +33,7 @@
273 test_client_surface_swap_buffers.cpp
274 test_client_cursor_api.cpp
275 test_trust_session_helper.cpp
276+ test_large_messages.cpp
277 ${GENERATED_PROTOBUF_SRCS}
278 ${GENERATED_PROTOBUF_HDRS}
279 )
280
281=== added file 'tests/acceptance-tests/test_large_messages.cpp'
282--- tests/acceptance-tests/test_large_messages.cpp 1970-01-01 00:00:00 +0000
283+++ tests/acceptance-tests/test_large_messages.cpp 2014-05-19 12:37:31 +0000
284@@ -0,0 +1,103 @@
285+/*
286+ * Copyright © 2014 Canonical Ltd.
287+ *
288+ * This program is free software: you can redistribute it and/or modify it
289+ * under the terms of the GNU General Public License version 3,
290+ * as published by the Free Software Foundation.
291+ *
292+ * This program is distributed in the hope that it will be useful,
293+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
294+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
295+ * GNU General Public License for more details.
296+ *
297+ * You should have received a copy of the GNU General Public License
298+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
299+ *
300+ * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
301+ */
302+
303+#include "mir_test_framework/in_process_server.h"
304+#include "mir_test_framework/stubbed_server_configuration.h"
305+#include "mir_test/wait_object.h"
306+#include "mir_test/fake_shared.h"
307+#include "mir_test_doubles/stub_display_configuration.h"
308+#include "mir_test_doubles/null_display_changer.h"
309+
310+#include "mir_toolkit/mir_connection.h"
311+
312+#include <gtest/gtest.h>
313+
314+namespace mtd = mir::test::doubles;
315+namespace mt = mir::test;
316+namespace mg = mir::graphics;
317+namespace mf = mir::frontend;
318+
319+namespace
320+{
321+
322+class LargeDisplayConfigChanger : public mtd::NullDisplayChanger
323+{
324+public:
325+ std::shared_ptr<mg::DisplayConfiguration> active_configuration() override
326+ {
327+ return mt::fake_shared(stub_display_config);
328+ }
329+
330+private:
331+ mtd::StubDisplayConfig stub_display_config{20};
332+};
333+
334+
335+struct LargeMessagesServerConfiguration : mir_test_framework::StubbedServerConfiguration
336+{
337+ std::shared_ptr<mf::DisplayChanger> the_frontend_display_changer() override
338+ {
339+ return mt::fake_shared(large_display_config_changer);
340+ }
341+
342+ LargeDisplayConfigChanger large_display_config_changer;
343+};
344+
345+struct LargeMessages : mir_test_framework::InProcessServer
346+{
347+ LargeMessagesServerConfiguration large_messages_server_config;
348+
349+ mir::DefaultServerConfiguration& server_config() override
350+ {
351+ return large_messages_server_config;
352+ }
353+};
354+
355+struct ConnectionContext
356+{
357+ mt::WaitObject connected;
358+ MirConnection* connection{nullptr};
359+};
360+
361+void connection_callback(MirConnection* connection, void* context)
362+{
363+ auto connection_context = static_cast<ConnectionContext*>(context);
364+ connection_context->connection = connection;
365+ connection_context->connected.notify_ready();
366+}
367+
368+}
369+
370+// Regression test for lp:1320187. Without a fix for that bug, connecting
371+// to a server with a lot of information in the display configuration hangs
372+// the client, because the server reply message is incomplete/corrupted.
373+TEST_F(LargeMessages, connection_to_server_with_large_display_configuration_succeeds)
374+{
375+ using namespace testing;
376+
377+ ConnectionContext connection_context;
378+
379+ mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__,
380+ connection_callback, &connection_context);
381+
382+ connection_context.connected.wait_until_ready(std::chrono::seconds{3});
383+
384+ EXPECT_NE(connection_context.connection, nullptr);
385+
386+ mir_connection_release(connection_context.connection);
387+}
388
389=== modified file 'tests/unit-tests/CMakeLists.txt'
390--- tests/unit-tests/CMakeLists.txt 2014-03-26 05:48:59 +0000
391+++ tests/unit-tests/CMakeLists.txt 2014-05-19 12:37:31 +0000
392@@ -12,6 +12,7 @@
393 shared_library_test.cpp
394 test_raii.cpp
395 test_udev_wrapper.cpp
396+ test_variable_length_array.cpp
397 )
398
399 add_subdirectory(options/)
400
401=== added file 'tests/unit-tests/test_variable_length_array.cpp'
402--- tests/unit-tests/test_variable_length_array.cpp 1970-01-01 00:00:00 +0000
403+++ tests/unit-tests/test_variable_length_array.cpp 2014-05-19 12:37:31 +0000
404@@ -0,0 +1,107 @@
405+/*
406+ * Copyright © 2014 Canonical Ltd.
407+ *
408+ * This program is free software: you can redistribute it and/or modify it
409+ * under the terms of the GNU General Public License version 3,
410+ * as published by the Free Software Foundation.
411+ *
412+ * This program is distributed in the hope that it will be useful,
413+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
414+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
415+ * GNU General Public License for more details.
416+ *
417+ * You should have received a copy of the GNU General Public License
418+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
419+ *
420+ *
421+ * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
422+ */
423+
424+#include "mir/variable_length_array.h"
425+
426+#include <gtest/gtest.h>
427+#include <gmock/gmock.h>
428+
429+TEST(VariableLengthArray, has_correct_size_if_using_builtin)
430+{
431+ using namespace testing;
432+
433+ size_t const builtin_size{100};
434+ size_t const vla_size_builtin{builtin_size - 1};
435+ mir::VariableLengthArray<builtin_size> vla{vla_size_builtin};
436+
437+ EXPECT_THAT(vla.size(), Eq(vla_size_builtin));
438+ memset(vla.data(), 0x55, vla.size());
439+}
440+
441+TEST(VariableLengthArray, has_correct_size_if_using_heap)
442+{
443+ using namespace testing;
444+
445+ size_t const builtin_size{100};
446+ size_t const vla_size_heap{builtin_size + 1};
447+ mir::VariableLengthArray<builtin_size> vla{vla_size_heap};
448+
449+ EXPECT_THAT(vla.size(), Eq(vla_size_heap));
450+ memset(vla.data(), 0x55, vla.size());
451+}
452+
453+TEST(VariableLengthArray, resizes_from_builtin_to_heap)
454+{
455+ using namespace testing;
456+
457+ size_t const builtin_size{100};
458+ size_t const vla_size_builtin{builtin_size - 1};
459+ size_t const vla_size_heap{builtin_size + 1};
460+ mir::VariableLengthArray<builtin_size> vla{vla_size_builtin};
461+
462+ vla.resize(vla_size_heap);
463+
464+ EXPECT_THAT(vla.size(), Eq(vla_size_heap));
465+ memset(vla.data(), 0x55, vla.size());
466+}
467+
468+TEST(VariableLengthArray, resizes_from_builtin_to_builtin)
469+{
470+ using namespace testing;
471+
472+ size_t const builtin_size{100};
473+ size_t const vla_size_builtin1{builtin_size - 1};
474+ size_t const vla_size_builtin2{builtin_size};
475+ mir::VariableLengthArray<builtin_size> vla{vla_size_builtin1};
476+
477+ vla.resize(vla_size_builtin2);
478+
479+ EXPECT_THAT(vla.size(), Eq(vla_size_builtin2));
480+ memset(vla.data(), 0x55, vla.size());
481+}
482+
483+TEST(VariableLengthArray, resizes_from_heap_to_builtin)
484+{
485+ using namespace testing;
486+
487+ size_t const builtin_size{100};
488+ size_t const vla_size_builtin{builtin_size - 1};
489+ size_t const vla_size_heap{builtin_size + 1};
490+ mir::VariableLengthArray<builtin_size> vla{vla_size_heap};
491+
492+ vla.resize(vla_size_builtin);
493+
494+ EXPECT_THAT(vla.size(), Eq(vla_size_builtin));
495+ memset(vla.data(), 0x55, vla.size());
496+}
497+
498+TEST(VariableLengthArray, resizes_from_heap_to_heap)
499+{
500+ using namespace testing;
501+
502+ size_t const builtin_size{100};
503+ size_t const vla_size_heap1{builtin_size + 1};
504+ size_t const vla_size_heap2{builtin_size + 2};
505+ mir::VariableLengthArray<builtin_size> vla{vla_size_heap1};
506+
507+ vla.resize(vla_size_heap2);
508+
509+ EXPECT_THAT(vla.size(), Eq(vla_size_heap2));
510+ memset(vla.data(), 0x55, vla.size());
511+}

Subscribers

People subscribed via source and target branches