Merge lp:~afrantzis/mir/variable-length-serialization-buffers-1320187 into lp:mir
- variable-length-serialization-buffers-1320187
- Merge into development-branch
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 |
Related bugs: |
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:
|
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.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andreas Pokorny (andreas-pokorny) wrote : | # |
What is the purpose of connection_
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Alexandros Frantzis (afrantzis) wrote : | # |
> What is the purpose of
> connection_
> test_large_
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/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Alan Griffiths (alan-griffiths) wrote : | # |
59 + static void heap_deleter(
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_
346 +{
347 + LargeMessagesSe
348 +
349 + mir::DefaultSer
350 + {
351 + return large_messages_
352 + }
353 +};
354
355 +struct ConnectionContext
356 +{
357 + mt::WaitObject connected;
358 + MirConnection* connection{
359 +};
360 +
361 +void connection_
362 +{
363 + auto connection_context = static_
364 + connection_
365 + connection_
366 +}
You could avoid this (and some related code in the test body) by:
using LargeMessages = mir_test_
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1638
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andreas Pokorny (andreas-pokorny) wrote : | # |
> > What is the purpose of
> > connection_
> > test_large_
>
> 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/
oh, ok.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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_
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.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Alan Griffiths (alan-griffiths) wrote : | # |
> > You could avoid this (and some related code in the test body) by:
> > using LargeMessages = mir_test_
> agesServerConfi
>
> 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 BasicClientServ
{
InProcessSe
// async connect with timeout
}
...OTOH maybe changing BasicClientServ
Anyway I'm still approving as is. ;)
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1639
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Robert Carr (robertcarr) : | # |
Preview Diff
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 | +} |
PASSED: Continuous integration, rev:1637 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- ci/1653/ jenkins. qa.ubuntu. com/job/ mir-android- utopic- i386-build/ 225 jenkins. qa.ubuntu. com/job/ mir-clang- utopic- amd64-build/ 226 jenkins. qa.ubuntu. com/job/ mir-mediumtests -utopic- touch/226 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- amd64-ci/ 172 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- amd64-ci/ 172/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- armhf-ci/ 171 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- armhf-ci/ 171/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/573 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/573/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-mediumtests -runner- mako/1478 s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 7277
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/mir- team-mir- development- branch- ci/1653/ rebuild
http://