Mir

Merge lp:~alan-griffiths/mir/some-acceptance-tests-use-mir-Server-API into lp:mir

Proposed by Alan Griffiths
Status: Merged
Approved by: Alan Griffiths
Approved revision: no longer in the source branch.
Merged at revision: 2009
Proposed branch: lp:~alan-griffiths/mir/some-acceptance-tests-use-mir-Server-API
Merge into: lp:mir
Prerequisite: lp:~alan-griffiths/mir/Migrate-ServerConfigurationWrapping-to-Server-API
Diff against target: 678 lines (+387/-84)
12 files modified
include/server/mir/server.h (+21/-1)
server-ABI-sha1sums (+1/-1)
src/server/server.cpp (+63/-0)
src/server/symbols.map (+1/-0)
tests/acceptance-tests/server_configuration_wrapping.cpp (+3/-41)
tests/acceptance-tests/test_client_library.cpp (+21/-6)
tests/include/mir_test_framework/headless_test.h (+71/-0)
tests/include/mir_test_framework/temporary_environment_value.h (+41/-0)
tests/mir_test_framework/CMakeLists.txt (+2/-0)
tests/mir_test_framework/headless_test.cpp (+113/-0)
tests/mir_test_framework/temporary_environment_value.cpp (+42/-0)
tests/unit-tests/graphics/mesa/test_anonymous_shm_file.cpp (+8/-35)
To merge this branch: bzr merge lp:~alan-griffiths/mir/some-acceptance-tests-use-mir-Server-API
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Kevin DuBois (community) Approve
Alberto Aguirre (community) Approve
Andreas Pokorny (community) Approve
Alexandros Frantzis (community) Needs Fixing
Review via email: mp+239406@code.launchpad.net

Commit message

test: Move another of the acceptance test suites [ClientLibrary.*] to the mir::Server based API

Description of the change

test: Move another of the acceptance test suites [ClientLibrary.*] to the mir::Server based API

It cleans up the "AcceptanceTest" fixture from the prerequisite branch and introduces "HeadlessTest".

There's a similar "debt" with a new HeadlessInProcessServer fixtures and some ugly code in mir::Server that should evolve as the requirements of additional tests are addressed.

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
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> typedef std::function<void(std::shared_ptr<frontend::Session> const& session)> ConnectHandler;

using ConnectHandler = ... , it's more consistent with other type definitions in the class.

> auto open_client_socket() -> int;

Although testing is a valid driver of the API, I am a bit skeptical of exposing functionality for tests only, since doing so may occasionally compromise the focus of the API, expose internals etc. This particular change seems OK, though, and if we want to provide such functionality we should also provide the same stability guarantees as we do for the "normal" public API (and stability should be an important factor in deciding whether we want a test-only method appear in the public API).

Needs fixing for the typedef.

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

> > typedef std::function<void(std::shared_ptr<frontend::Session> const&
> session)> ConnectHandler;
>
> using ConnectHandler = ... , it's more consistent with other type definitions
> in the class.

Fixed

> > auto open_client_socket() -> int;
>
> Although testing is a valid driver of the API, I am a bit skeptical of
> exposing functionality for tests only, since doing so may occasionally
> compromise the focus of the API, expose internals etc.

I totally agree. Although in the case of acceptance tests these should ideally be written in terms of the API.

Where acceptance tests need something other than the API exposes there should a clear distinction in the way such features are invoked.

> This particular change
> seems OK, though, and if we want to provide such functionality we should also
> provide the same stability guarantees as we do for the "normal" public API
> (and stability should be an important factor in deciding whether we want a
> test-only method appear in the public API).

I gave some thought to this and concluded supporting the test this way gives a potentially useful API: we don't always want to expose an endpoint on the filesystem for clients to use (doing so is a long standing issue with unity-system-compositor). It also allows a server to start in process "clients" using the normal client API.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote :

27 + auto open_client_socket() -> int;
Given the api, I'd assume that I own the returned fd after calling this function, but it would be a bit more clear if it returned a mir::Fd.

Otherwise, I'm persuaded that this can solve help solve the endpoint-on-filesystem and think its useful.

review: Needs Fixing
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

+1 for mir::Fd

looks good otherwise

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

LGTM

review: Approve
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

The "needs fixing" items from the other 2 reviewers have been addressed so TA'ing.

Revision history for this message
Kevin DuBois (kdub) wrote :

looks good to me

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

[ FAILED ] 17 tests, listed below:
[ FAILED ] AvailableSurfaceFormatsTest.surface_pixel_formats_reach_client
[ FAILED ] SurfaceFirstFrameSync.surface_not_rendered_until_buffer_is_pushed
[ FAILED ] SwapIntervalSignalTest.swapinterval_test
[ FAILED ] ServerShutdown.server_can_shut_down_when_clients_are_blocked
[ FAILED ] SessionMediatorReport.session_connect_called
[ FAILED ] SessionMediatorReport.session_create_surface_called
[ FAILED ] SessionMediatorReport.session_next_buffer_called
[ FAILED ] SessionMediatorReport.session_exchange_buffer_called
[ FAILED ] SessionMediatorReport.session_release_surface_called
[ FAILED ] SessionMediatorReport.session_disconnect_called
[ FAILED ] SessionMediatorReport.prompt_session_start_called
[ FAILED ] SessionMediatorReport.prompt_session_stop_called
[ FAILED ] Process.a_main_fn_is_executed
[ FAILED ] Process.a_successful_exit_function_succeeds
[ FAILED ] BespokeDisplayServerTestFixture.starting_display_server_starts_input_manager
[ FAILED ] BespokeDisplayServerTestFixture.client_drm_auth_magic_calls_platform
[ FAILED ] BespokeDisplayServerTestFixture.drm_auth_magic_platform_error_reaches_client

WOW! (Not related AFAICS - those are integration tests I've not touched)

Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/server/mir/server.h'
--- include/server/mir/server.h 2014-10-24 13:39:38 +0000
+++ include/server/mir/server.h 2014-10-28 09:41:16 +0000
@@ -19,13 +19,15 @@
19#ifndef MIR_SERVER_H_19#ifndef MIR_SERVER_H_
20#define MIR_SERVER_H_20#define MIR_SERVER_H_
2121
22#include "mir/fd.h"
23
22#include <functional>24#include <functional>
23#include <memory>25#include <memory>
2426
25namespace mir27namespace mir
26{28{
27namespace compositor { class Compositor; class DisplayBufferCompositorFactory; }29namespace compositor { class Compositor; class DisplayBufferCompositorFactory; }
28namespace frontend { class SessionAuthorizer; }30namespace frontend { class SessionAuthorizer; class Session; }
29namespace graphics { class Platform; class Display; class GLConfig; class DisplayConfigurationPolicy; }31namespace graphics { class Platform; class Display; class GLConfig; class DisplayConfigurationPolicy; }
30namespace input { class CompositeEventFilter; class InputDispatcher; class CursorListener; }32namespace input { class CompositeEventFilter; class InputDispatcher; class CursorListener; }
31namespace options { class Option; }33namespace options { class Option; }
@@ -234,6 +236,24 @@
234 auto the_surface_coordinator() const -> std::shared_ptr<scene::SurfaceCoordinator>;236 auto the_surface_coordinator() const -> std::shared_ptr<scene::SurfaceCoordinator>;
235/** @} */237/** @} */
236238
239/** @name Client side support
240 * These facilitate use of the server through the client API.
241 * They should be called while the server is running (i.e. run() has been called and
242 * not exited) otherwise they throw a std::logic_error.
243 * @{ */
244 using ConnectHandler = std::function<void(std::shared_ptr<frontend::Session> const& session)>;
245
246 /// Get a file descriptor that can be used to connect a client
247 /// It can be passed to another process, or used directly with mir_connect()
248 /// using the format "fd://%d".
249 auto open_client_socket() -> Fd;
250
251 /// Get a file descriptor that can be used to connect a client
252 /// It can be passed to another process, or used directly with mir_connect()
253 /// using the format "fd://%d".
254 /// \param connect_handler callback to be invoked when the client connects
255 auto open_client_socket(ConnectHandler const& connect_handler) -> Fd;
256/** @} */
237private:257private:
238 void apply_settings() const;258 void apply_settings() const;
239 struct ServerConfiguration;259 struct ServerConfiguration;
240260
=== modified file 'server-ABI-sha1sums'
--- server-ABI-sha1sums 2014-10-27 22:31:16 +0000
+++ server-ABI-sha1sums 2014-10-28 09:41:16 +0000
@@ -98,7 +98,7 @@
98993e9f458ffc4288d304413f3fa0b1dcc95a093d include/server/mir/scene/surface_observer.h98993e9f458ffc4288d304413f3fa0b1dcc95a093d include/server/mir/scene/surface_observer.h
997ef3e99901168cda296d74d05a979f47bf9c3ff1 include/server/mir/server_action_queue.h997ef3e99901168cda296d74d05a979f47bf9c3ff1 include/server/mir/server_action_queue.h
1008d83a51c278b8b71866d2178d9b6387c1f91a7d0 include/server/mir/server_configuration.h1008d83a51c278b8b71866d2178d9b6387c1f91a7d0 include/server/mir/server_configuration.h
101a42b26d4796c66706c65be963468645620024820 include/server/mir/server.h101320c467bdd757c71d02a904cc6a30cba67e27030 include/server/mir/server.h
10286098b500339bfccd07a9bed8298f75a68b18f5c include/server/mir/server_status_listener.h10286098b500339bfccd07a9bed8298f75a68b18f5c include/server/mir/server_status_listener.h
103860c04f32b60e680140148dc9dc2295de145b9c1 include/server/mir/shell/display_layout.h103860c04f32b60e680140148dc9dc2295de145b9c1 include/server/mir/shell/display_layout.h
1046a2107b01feae13060d5c305804906e53c52e0be include/server/mir/shell/focus_controller.h1046a2107b01feae13060d5c305804906e53c52e0be include/server/mir/shell/focus_controller.h
105105
=== modified file 'src/server/server.cpp'
--- src/server/server.cpp 2014-10-24 13:39:38 +0000
+++ src/server/server.cpp 2014-10-28 09:41:16 +0000
@@ -18,12 +18,18 @@
1818
19#include "mir/server.h"19#include "mir/server.h"
2020
21#include "mir/frontend/connector.h"
21#include "mir/options/default_configuration.h"22#include "mir/options/default_configuration.h"
22#include "mir/default_server_configuration.h"23#include "mir/default_server_configuration.h"
23#include "mir/main_loop.h"24#include "mir/main_loop.h"
24#include "mir/report_exception.h"25#include "mir/report_exception.h"
25#include "mir/run_mir.h"26#include "mir/run_mir.h"
2627
28// TODO these are used to frig a stub renderer when running headless
29#include "mir/compositor/renderer.h"
30#include "mir/graphics/renderable.h"
31#include "mir/compositor/renderer_factory.h"
32
27#include <iostream>33#include <iostream>
2834
29namespace mo = mir::options;35namespace mo = mir::options;
@@ -118,6 +124,36 @@
118 return mir::DefaultServerConfiguration::wrap_##name(wrapped);\124 return mir::DefaultServerConfiguration::wrap_##name(wrapped);\
119}125}
120126
127// TODO these are used to frig a stub renderer when running headless
128namespace
129{
130class StubRenderer : public mir::compositor::Renderer
131{
132public:
133 void set_viewport(mir::geometry::Rectangle const&) override {}
134
135 void set_rotation(float) override {}
136
137 void render(mir::graphics::RenderableList const& renderables) const override
138 {
139 for (auto const& r : renderables)
140 r->buffer(); // We need to consume a buffer to unblock client tests
141 }
142
143 void suspend() override {}
144};
145
146class StubRendererFactory : public mir::compositor::RendererFactory
147{
148public:
149 auto create_renderer_for(mir::geometry::Rectangle const&, mir::compositor::DestinationAlpha)
150 -> std::unique_ptr<mir::compositor::Renderer>
151 {
152 return std::unique_ptr<mir::compositor::Renderer>(new StubRenderer());
153 }
154};
155}
156
121struct mir::Server::ServerConfiguration : mir::DefaultServerConfiguration157struct mir::Server::ServerConfiguration : mir::DefaultServerConfiguration
122{158{
123 ServerConfiguration(159 ServerConfiguration(
@@ -128,6 +164,17 @@
128 {164 {
129 }165 }
130166
167 // TODO this is an ugly frig to avoid exposing the render factory to end users and tests running headless
168 auto the_renderer_factory() -> std::shared_ptr<compositor::RendererFactory> override
169 {
170 auto const graphics_lib = the_options()->get<std::string>(options::platform_graphics_lib);
171
172 if (graphics_lib != "libmirplatformstub.so")
173 return mir::DefaultServerConfiguration::the_renderer_factory();
174 else
175 return std::make_shared<StubRendererFactory>();
176 }
177
131 using mir::DefaultServerConfiguration::the_options;178 using mir::DefaultServerConfiguration::the_options;
132179
133 // TODO the MIR_SERVER_CONFIG_OVERRIDE macro expects a CachePtr named180 // TODO the MIR_SERVER_CONFIG_OVERRIDE macro expects a CachePtr named
@@ -256,6 +303,22 @@
256 return self->exit_status;303 return self->exit_status;
257}304}
258305
306auto mir::Server::open_client_socket() -> Fd
307{
308 if (auto const config = self->server_config)
309 return Fd{config->the_connector()->client_socket_fd()};
310
311 BOOST_THROW_EXCEPTION(std::logic_error("Cannot open connection when not running"));
312}
313
314auto mir::Server::open_client_socket(ConnectHandler const& connect_handler) -> Fd
315{
316 if (auto const config = self->server_config)
317 return Fd{config->the_connector()->client_socket_fd(connect_handler)};
318
319 BOOST_THROW_EXCEPTION(std::logic_error("Cannot open connection when not running"));
320}
321
259#define MIR_SERVER_ACCESSOR(name)\322#define MIR_SERVER_ACCESSOR(name)\
260auto mir::Server::name() const -> decltype(self->server_config->name())\323auto mir::Server::name() const -> decltype(self->server_config->name())\
261{\324{\
262325
=== modified file 'src/server/symbols.map'
--- src/server/symbols.map 2014-10-27 22:31:16 +0000
+++ src/server/symbols.map 2014-10-28 09:41:16 +0000
@@ -397,6 +397,7 @@
397 mir::ServerConfiguration::the_server_status_listener*;397 mir::ServerConfiguration::the_server_status_listener*;
398 mir::Server::exited_normally*;398 mir::Server::exited_normally*;
399 mir::Server::get_options*;399 mir::Server::get_options*;
400 mir::Server::open_client_socket*;
400 mir::Server::override_the_compositor*;401 mir::Server::override_the_compositor*;
401 mir::Server::override_the_display_buffer_compositor_factory*;402 mir::Server::override_the_display_buffer_compositor_factory*;
402 mir::Server::override_the_cursor_listener*;403 mir::Server::override_the_cursor_listener*;
403404
=== modified file 'tests/acceptance-tests/server_configuration_wrapping.cpp'
--- tests/acceptance-tests/server_configuration_wrapping.cpp 2014-10-22 02:50:44 +0000
+++ tests/acceptance-tests/server_configuration_wrapping.cpp 2014-10-28 09:41:16 +0000
@@ -19,7 +19,7 @@
19#include "mir/shell/session_coordinator_wrapper.h"19#include "mir/shell/session_coordinator_wrapper.h"
20#include "mir/shell/surface_coordinator_wrapper.h"20#include "mir/shell/surface_coordinator_wrapper.h"
2121
22#include "mir/server.h"22#include "mir_test_framework/headless_test.h"
2323
24#include <gtest/gtest.h>24#include <gtest/gtest.h>
25#include <gmock/gmock.h>25#include <gmock/gmock.h>
@@ -44,46 +44,8 @@
44 MOCK_METHOD0(focus_next, void());44 MOCK_METHOD0(focus_next, void());
45};45};
4646
47class TemporaryEnvironmentValue47struct ServerConfigurationWrapping : mir_test_framework::HeadlessTest
48{48{
49public:
50 TemporaryEnvironmentValue(char const* name, char const* value)
51 : name{name},
52 has_old_value{getenv(name) != nullptr},
53 old_value{has_old_value ? getenv(name) : ""}
54 {
55 if (value)
56 setenv(name, value, overwrite);
57 else
58 unsetenv(name);
59 }
60
61 ~TemporaryEnvironmentValue()
62 {
63 if (has_old_value)
64 setenv(name.c_str(), old_value.c_str(), overwrite);
65 else
66 unsetenv(name.c_str());
67 }
68
69private:
70 static int const overwrite = 1;
71 std::string const name;
72 bool const has_old_value;
73 std::string const old_value;
74};
75
76struct AcceptanceTest : Test
77{
78 AcceptanceTest() : platform("MIR_SERVER_PLATFORM_GRAPHICS_LIB", "libmirplatformstub.so") {}
79
80 TemporaryEnvironmentValue platform;
81};
82
83struct ServerConfigurationWrapping : AcceptanceTest
84{
85 mir::Server server;
86
87 void SetUp() override49 void SetUp() override
88 {50 {
89 server.wrap_surface_coordinator([]51 server.wrap_surface_coordinator([]
9052
=== modified file 'tests/acceptance-tests/test_client_library.cpp'
--- tests/acceptance-tests/test_client_library.cpp 2014-10-27 22:31:16 +0000
+++ tests/acceptance-tests/test_client_library.cpp 2014-10-28 09:41:16 +0000
@@ -18,8 +18,7 @@
1818
19#include "mir_toolkit/mir_client_library.h"19#include "mir_toolkit/mir_client_library.h"
2020
21#include "mir_test_framework/stubbed_server_configuration.h"21#include "mir_test_framework/headless_test.h"
22#include "mir_test_framework/in_process_server.h"
23#include "mir_test_framework/using_stub_client_platform.h"22#include "mir_test_framework/using_stub_client_platform.h"
2423
25#include "src/client/client_buffer.h"24#include "src/client/client_buffer.h"
@@ -53,10 +52,26 @@
5352
54namespace53namespace
55{54{
56struct ClientLibrary : mir_test_framework::InProcessServer55struct HeadlessInProcessServer : mir_test_framework::HeadlessTest
57{56{
58 mtf::StubbedServerConfiguration server_configuration;57 HeadlessInProcessServer()
59 mir::DefaultServerConfiguration& server_config() override { return server_configuration; }58 {
59 add_to_environment("MIR_SERVER_NO_FILE", "");
60 }
61
62 void SetUp() override
63 {
64 start_server();
65 }
66
67 void TearDown() override
68 {
69 stop_server();
70 }
71};
72
73struct ClientLibrary : HeadlessInProcessServer
74{
60 mtf::UsingStubClientPlatform using_stub_client_platform;75 mtf::UsingStubClientPlatform using_stub_client_platform;
6176
62 std::set<MirSurface*> surfaces;77 std::set<MirSurface*> surfaces;
6378
=== added file 'tests/include/mir_test_framework/headless_test.h'
--- tests/include/mir_test_framework/headless_test.h 1970-01-01 00:00:00 +0000
+++ tests/include/mir_test_framework/headless_test.h 2014-10-28 09:41:16 +0000
@@ -0,0 +1,71 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored By: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#ifndef MIR_TEST_FRAMEWORK_HEADLESS_TEST_H_
20#define MIR_TEST_FRAMEWORK_HEADLESS_TEST_H_
21
22#include "mir_test_framework/temporary_environment_value.h"
23
24#include "mir/server.h"
25
26#include <gtest/gtest.h>
27
28#include <condition_variable>
29#include <list>
30#include <mutex>
31#include <thread>
32
33namespace mir_test_framework
34{
35/** Basic fixture for tests that don't use graphics hardware.
36 * This provides a mechanism for temporarily setting environment variables.
37 * It automatically sets "MIR_SERVER_PLATFORM_GRAPHICS_LIB" to "libmirplatformstub.so"
38 * as the tests do not hit the graphics hardware.
39 */
40class HeadlessTest : public ::testing::Test
41{
42public:
43 HeadlessTest();
44 ~HeadlessTest() noexcept;
45
46 void add_to_environment(char const* key, char const* value);
47
48 /// Starts the server on a new thread
49 void start_server();
50
51 /// Stops the server and joins thread
52 void stop_server();
53
54 /// \return a connection string for a new client to connect to the server
55 auto new_connection() -> std::string;
56
57 mir::Server server;
58
59private:
60 std::list<TemporaryEnvironmentValue> env;
61 std::thread server_thread;
62
63 std::list<mir::Fd> connections;
64
65 std::mutex mutex;
66 std::condition_variable started;
67 bool server_running{false};
68};
69}
70
71#endif /* MIR_TEST_FRAMEWORK_HEADLESS_TEST_H_ */
072
=== added file 'tests/include/mir_test_framework/temporary_environment_value.h'
--- tests/include/mir_test_framework/temporary_environment_value.h 1970-01-01 00:00:00 +0000
+++ tests/include/mir_test_framework/temporary_environment_value.h 2014-10-28 09:41:16 +0000
@@ -0,0 +1,41 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored By: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#ifndef MIR_TEST_FRAMEWORK_ENVIRONMENT_VALUE_H_
20#define MIR_TEST_FRAMEWORK_ENVIRONMENT_VALUE_H_
21
22#include <string>
23
24namespace mir_test_framework
25{
26class TemporaryEnvironmentValue
27{
28public:
29 TemporaryEnvironmentValue(char const* name, char const* value);
30
31 ~TemporaryEnvironmentValue();
32
33private:
34 static int const overwrite = 1;
35 std::string const name;
36 bool const has_old_value;
37 std::string const old_value;
38};
39}
40
41#endif /* MIR_TEST_FRAMEWORK_ENVIRONMENT_VALUE_H_ */
042
=== modified file 'tests/mir_test_framework/CMakeLists.txt'
--- tests/mir_test_framework/CMakeLists.txt 2014-10-23 02:30:50 +0000
+++ tests/mir_test_framework/CMakeLists.txt 2014-10-28 09:41:16 +0000
@@ -15,7 +15,9 @@
15 executable_path.cpp15 executable_path.cpp
16 command_line_server_configuration.cpp16 command_line_server_configuration.cpp
17 cross_process_sync.cpp17 cross_process_sync.cpp
18 headless_test.cpp
18 server_runner.cpp19 server_runner.cpp
20 temporary_environment_value.cpp
19 testing_server_options.cpp21 testing_server_options.cpp
20 input_testing_server_options.cpp22 input_testing_server_options.cpp
21 stubbed_server_configuration.cpp23 stubbed_server_configuration.cpp
2224
=== added file 'tests/mir_test_framework/headless_test.cpp'
--- tests/mir_test_framework/headless_test.cpp 1970-01-01 00:00:00 +0000
+++ tests/mir_test_framework/headless_test.cpp 2014-10-28 09:41:16 +0000
@@ -0,0 +1,113 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored By: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#include "mir_test_framework/headless_test.h"
20
21#include "mir/main_loop.h"
22
23#include <boost/throw_exception.hpp>
24
25namespace mtf = mir_test_framework;
26
27namespace
28{
29std::chrono::seconds const timeout{10};
30}
31
32mtf::HeadlessTest::HeadlessTest()
33{
34 add_to_environment("MIR_SERVER_PLATFORM_GRAPHICS_LIB", "libmirplatformstub.so");
35}
36
37void mtf::HeadlessTest::add_to_environment(char const* key, char const* value)
38{
39 env.emplace_back(key, value);
40}
41
42void mtf::HeadlessTest::start_server()
43{
44 server.add_init_callback([&]
45 {
46 auto const main_loop = server.the_main_loop();
47 // By enqueuing the notification code in the main loop, we are
48 // ensuring that the server has really and fully started before
49 // leaving start_mir_server().
50 main_loop->enqueue(
51 this,
52 [&]
53 {
54 std::lock_guard<std::mutex> lock(mutex);
55 server_running = true;
56 started.notify_one();
57 });
58 });
59
60 server_thread = std::thread([&]
61 {
62 try
63 {
64 server.run();
65 }
66 catch (std::exception const& e)
67 {
68 FAIL() << e.what();
69 }
70 std::lock_guard<std::mutex> lock(mutex);
71 server_running = false;
72 started.notify_one();
73 });
74
75 std::unique_lock<std::mutex> lock(mutex);
76 started.wait_for(lock, timeout, [&] { return server_running; });
77
78 if (!server_running)
79 {
80 BOOST_THROW_EXCEPTION(std::runtime_error{"Failed to start server thread"});
81 }
82}
83
84void mtf::HeadlessTest::stop_server()
85{
86 connections.clear();
87
88 std::unique_lock<std::mutex> lock(mutex);
89 if (server_running)
90 {
91 server.stop();
92 started.wait_for(lock, timeout, [&] { return !server_running; });
93 }
94
95 if (server_running)
96 {
97 BOOST_THROW_EXCEPTION(std::logic_error{"stop_server() failed to stop server"});
98 }
99}
100
101mtf::HeadlessTest::~HeadlessTest() noexcept
102{
103 if (server_thread.joinable()) server_thread.join();
104}
105
106auto mtf::HeadlessTest::new_connection() -> std::string
107{
108 char connect_string[64] = {0};
109 auto const client_socket = server.open_client_socket();
110 connections.push_back(client_socket);
111 sprintf(connect_string, "fd://%d", client_socket.operator int());
112 return connect_string;
113}
0114
=== added file 'tests/mir_test_framework/temporary_environment_value.cpp'
--- tests/mir_test_framework/temporary_environment_value.cpp 1970-01-01 00:00:00 +0000
+++ tests/mir_test_framework/temporary_environment_value.cpp 2014-10-28 09:41:16 +0000
@@ -0,0 +1,42 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored By: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#include "mir_test_framework/temporary_environment_value.h"
20
21#include <cstdlib>
22
23namespace mtf = mir_test_framework;
24
25mtf::TemporaryEnvironmentValue::TemporaryEnvironmentValue(char const* name, char const* value) :
26 name{name},
27 has_old_value{getenv(name) != nullptr},
28 old_value{has_old_value ? getenv(name) : ""}
29{
30 if (value)
31 setenv(name, value, overwrite);
32 else
33 unsetenv(name);
34}
35
36mtf::TemporaryEnvironmentValue::~TemporaryEnvironmentValue()
37{
38 if (has_old_value)
39 setenv(name.c_str(), old_value.c_str(), overwrite);
40 else
41 unsetenv(name.c_str());
42}
043
=== modified file 'tests/unit-tests/graphics/mesa/test_anonymous_shm_file.cpp'
--- tests/unit-tests/graphics/mesa/test_anonymous_shm_file.cpp 2014-10-21 16:21:14 +0000
+++ tests/unit-tests/graphics/mesa/test_anonymous_shm_file.cpp 2014-10-28 09:41:16 +0000
@@ -18,6 +18,8 @@
1818
19#include "src/platform/graphics/mesa/anonymous_shm_file.h"19#include "src/platform/graphics/mesa/anonymous_shm_file.h"
2020
21#include "mir_test_framework/temporary_environment_value.h"
22
21#include <gtest/gtest.h>23#include <gtest/gtest.h>
22#include <gmock/gmock.h>24#include <gmock/gmock.h>
2325
@@ -33,39 +35,10 @@
3335
34namespace mg = mir::graphics;36namespace mg = mir::graphics;
35namespace mgm = mir::graphics::mesa;37namespace mgm = mir::graphics::mesa;
38namespace mtf = mir_test_framework;
3639
37namespace40namespace
38{41{
39
40class TemporaryEnvironmentValue
41{
42public:
43 TemporaryEnvironmentValue(char const* name, char const* value)
44 : name{name},
45 has_old_value{getenv(name) != nullptr},
46 old_value{has_old_value ? getenv(name) : ""}
47 {
48 if (value)
49 setenv(name, value, overwrite);
50 else
51 unsetenv(name);
52 }
53
54 ~TemporaryEnvironmentValue()
55 {
56 if (has_old_value)
57 setenv(name.c_str(), old_value.c_str(), overwrite);
58 else
59 unsetenv(name.c_str());
60 }
61
62private:
63 static int const overwrite = 1;
64 std::string const name;
65 bool const has_old_value;
66 std::string const old_value;
67};
68
69class TemporaryDirectory42class TemporaryDirectory
70{43{
71public:44public:
@@ -185,7 +158,7 @@
185 using namespace testing;158 using namespace testing;
186159
187 TemporaryDirectory const temp_dir;160 TemporaryDirectory const temp_dir;
188 TemporaryEnvironmentValue const env{"XDG_RUNTIME_DIR", temp_dir.path()};161 mtf::TemporaryEnvironmentValue const env{"XDG_RUNTIME_DIR", temp_dir.path()};
189 PathWatcher const path_watcher{temp_dir.path()};162 PathWatcher const path_watcher{temp_dir.path()};
190 size_t const file_size{100};163 size_t const file_size{100};
191164
@@ -202,7 +175,7 @@
202{175{
203 using namespace testing;176 using namespace testing;
204177
205 TemporaryEnvironmentValue const env{"XDG_RUNTIME_DIR", nullptr};178 mtf::TemporaryEnvironmentValue const env{"XDG_RUNTIME_DIR", nullptr};
206 PathWatcher const path_watcher{"/tmp"};179 PathWatcher const path_watcher{"/tmp"};
207 size_t const file_size{100};180 size_t const file_size{100};
208181
@@ -219,7 +192,7 @@
219{192{
220 using namespace testing;193 using namespace testing;
221194
222 TemporaryEnvironmentValue const env{"XDG_RUNTIME_DIR", "/non-existent-dir"};195 mtf::TemporaryEnvironmentValue const env{"XDG_RUNTIME_DIR", "/non-existent-dir"};
223 PathWatcher const path_watcher{"/tmp"};196 PathWatcher const path_watcher{"/tmp"};
224 size_t const file_size{100};197 size_t const file_size{100};
225198
@@ -237,7 +210,7 @@
237 using namespace testing;210 using namespace testing;
238211
239 TemporaryDirectory const temp_dir;212 TemporaryDirectory const temp_dir;
240 TemporaryEnvironmentValue const env{"XDG_RUNTIME_DIR", temp_dir.path()};213 mtf::TemporaryEnvironmentValue const env{"XDG_RUNTIME_DIR", temp_dir.path()};
241 size_t const file_size{100};214 size_t const file_size{100};
242215
243 mgm::AnonymousShmFile shm_file{file_size};216 mgm::AnonymousShmFile shm_file{file_size};
@@ -253,7 +226,7 @@
253 using namespace testing;226 using namespace testing;
254227
255 TemporaryDirectory const temp_dir;228 TemporaryDirectory const temp_dir;
256 TemporaryEnvironmentValue const env{"XDG_RUNTIME_DIR", temp_dir.path()};229 mtf::TemporaryEnvironmentValue const env{"XDG_RUNTIME_DIR", temp_dir.path()};
257 size_t const file_size{100};230 size_t const file_size{100};
258231
259 mgm::AnonymousShmFile shm_file{file_size};232 mgm::AnonymousShmFile shm_file{file_size};

Subscribers

People subscribed via source and target branches