~ubuntu-branches/ubuntu/wily/mir/wily-proposed

« back to all changes in this revision

Viewing changes to tests/acceptance-tests/test_client_library_errors.cpp

  • Committer: Package Import Robot
  • Author(s): Alexandros Frantzis
  • Date: 2015-10-08 16:12:19 UTC
  • mto: This revision was merged to the branch mainline in revision 109.
  • Revision ID: package-import@ubuntu.com-20151008161219-emk4a1ys51yy0wjb
Tags: upstream-0.17.0+15.10.20151008.2
ImportĀ upstreamĀ versionĀ 0.17.0+15.10.20151008.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright Ā© 2014 Canonical Ltd.
3
 
 *
4
 
 * This program is free software: you can redistribute it and/or modify
5
 
 * it under the terms of the GNU General Public License version 3 as
6
 
 * 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: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
17
 
 */
18
 
 
19
 
#include "mir_toolkit/mir_client_library.h"
20
 
#include "mir_toolkit/debug/surface.h"
21
 
 
22
 
#include "src/include/client/mir/client_platform_factory.h"
23
 
#include "src/include/client/mir/client_platform.h"
24
 
#include "src/include/client/mir/client_buffer_factory.h"
25
 
 
26
 
#include "mir/test/validity_matchers.h"
27
 
 
28
 
#include "mir_test_framework/headless_in_process_server.h"
29
 
#include "mir_test_framework/using_stub_client_platform.h"
30
 
#include "mir_test_framework/stub_client_connection_configuration.h"
31
 
#include "mir_test_framework/any_surface.h"
32
 
#include "mir/test/doubles/stub_client_buffer_factory.h"
33
 
 
34
 
#include <gtest/gtest.h>
35
 
#include <gmock/gmock.h>
36
 
 
37
 
#include <stdexcept>
38
 
#include <boost/throw_exception.hpp>
39
 
#include <cstring>
40
 
 
41
 
namespace mcl = mir::client;
42
 
namespace mtf = mir_test_framework;
43
 
namespace mtd = mir::test::doubles;
44
 
 
45
 
namespace
46
 
{
47
 
enum Method : uint64_t
48
 
{
49
 
    none = 0,
50
 
    the_client_platform_factory = 1<<0,
51
 
    create_client_platform      = 1<<1,
52
 
    create_egl_native_window    = 1<<2,
53
 
    create_buffer_factory       = 1<<3
54
 
};
55
 
 
56
 
std::string const exception_text{"Ducks!"};
57
 
 
58
 
template<Method name, Method failure_set>
59
 
bool should_fail()
60
 
{
61
 
    return (name & failure_set);
62
 
}
63
 
 
64
 
template<Method failure_set>
65
 
class ConfigurableFailurePlatform : public mir::client::ClientPlatform
66
 
{
67
 
    std::shared_ptr<EGLNativeWindowType> create_egl_native_window(mir::client::EGLNativeSurface *)
68
 
    {
69
 
        if (should_fail<Method::create_egl_native_window, failure_set>())
70
 
        {
71
 
            BOOST_THROW_EXCEPTION(std::runtime_error{exception_text});
72
 
        }
73
 
        return std::shared_ptr<EGLNativeWindowType>{};
74
 
    }
75
 
 
76
 
    void populate(MirPlatformPackage&) const override
77
 
    {
78
 
    }
79
 
 
80
 
    MirPlatformMessage* platform_operation(MirPlatformMessage const*) override
81
 
    {
82
 
        return nullptr;
83
 
    }
84
 
 
85
 
    MirPlatformType platform_type() const
86
 
    {
87
 
        BOOST_THROW_EXCEPTION(std::runtime_error{exception_text});
88
 
        return MirPlatformType::mir_platform_type_gbm;
89
 
    }
90
 
    std::shared_ptr<mir::client::ClientBufferFactory> create_buffer_factory()
91
 
    {
92
 
        if (should_fail<Method::create_buffer_factory, failure_set>())
93
 
        {
94
 
            BOOST_THROW_EXCEPTION(std::runtime_error{exception_text});
95
 
        }
96
 
        return std::make_shared<mtd::StubClientBufferFactory>();
97
 
    }
98
 
    std::shared_ptr<EGLNativeDisplayType> create_egl_native_display()
99
 
    {
100
 
        return std::shared_ptr<EGLNativeDisplayType>{};
101
 
    }
102
 
    MirNativeBuffer *convert_native_buffer(mir::graphics::NativeBuffer*) const
103
 
    {
104
 
        BOOST_THROW_EXCEPTION(std::runtime_error{exception_text});
105
 
        return nullptr;
106
 
    }
107
 
    MirPixelFormat get_egl_pixel_format(EGLDisplay, EGLConfig) const override
108
 
    {
109
 
        return mir_pixel_format_invalid;
110
 
    }
111
 
};
112
 
 
113
 
template<Method failure_set>
114
 
class ConfigurableFailureFactory: public mir::client::ClientPlatformFactory
115
 
{
116
 
    std::shared_ptr<mir::client::ClientPlatform>
117
 
    create_client_platform(mir::client::ClientContext* /*context*/) override
118
 
    {
119
 
        if (should_fail<Method::create_client_platform, failure_set>())
120
 
        {
121
 
            BOOST_THROW_EXCEPTION(std::runtime_error{exception_text});
122
 
        }
123
 
        return std::make_shared<ConfigurableFailurePlatform<failure_set>>();
124
 
    }
125
 
};
126
 
 
127
 
template<Method failure_set>
128
 
class ConfigurableFailureConfiguration : public mtf::StubConnectionConfiguration
129
 
{
130
 
    using mtf::StubConnectionConfiguration::StubConnectionConfiguration;
131
 
 
132
 
    std::shared_ptr<mir::client::ClientPlatformFactory> the_client_platform_factory() override
133
 
    {
134
 
        if (should_fail<Method::the_client_platform_factory, failure_set>())
135
 
        {
136
 
            BOOST_THROW_EXCEPTION(std::runtime_error{exception_text});
137
 
        }
138
 
        return std::make_shared<ConfigurableFailureFactory<failure_set>>();
139
 
    }
140
 
};
141
 
 
142
 
struct ClientLibraryErrors : mtf::HeadlessInProcessServer
143
 
{
144
 
    ClientLibraryErrors() { add_to_environment("MIR_SERVER_ENABLE_INPUT","off"); }
145
 
};
146
 
}
147
 
 
148
 
 
149
 
TEST_F(ClientLibraryErrors, exception_in_client_configuration_constructor_generates_error)
150
 
{
151
 
    mtf::UsingClientPlatform<ConfigurableFailureConfiguration<Method::the_client_platform_factory>> stubby;
152
 
 
153
 
    auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
154
 
 
155
 
    EXPECT_FALSE(mir_connection_is_valid(connection));
156
 
    EXPECT_THAT(mir_connection_get_error_message(connection), testing::HasSubstr(exception_text));
157
 
    mir_connection_release(connection);
158
 
}
159
 
 
160
 
TEST_F(ClientLibraryErrors, exception_in_platform_construction_generates_error)
161
 
{
162
 
    mtf::UsingClientPlatform<ConfigurableFailureConfiguration<Method::create_client_platform>> stubby;
163
 
 
164
 
    auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
165
 
 
166
 
    EXPECT_FALSE(mir_connection_is_valid(connection));
167
 
    EXPECT_THAT(mir_connection_get_error_message(connection), testing::HasSubstr(exception_text));
168
 
    mir_connection_release(connection);
169
 
}
170
 
 
171
 
TEST_F(ClientLibraryErrors, connecting_to_garbage_socket_returns_appropriate_error)
172
 
{
173
 
    using namespace testing;
174
 
    mtf::UsingStubClientPlatform stubby;
175
 
 
176
 
    auto connection = mir_connect_sync("garbage", __PRETTY_FUNCTION__);
177
 
    ASSERT_THAT(connection, NotNull());
178
 
 
179
 
    char const* error = mir_connection_get_error_message(connection);
180
 
 
181
 
    if (std::strcmp("connect: No such file or directory", error) &&
182
 
        std::strcmp("Can't find MIR server", error) &&
183
 
        !std::strstr(error, "Failed to connect to server socket"))
184
 
    {
185
 
        FAIL() << error;
186
 
    }
187
 
    mir_connection_release(connection);
188
 
}
189
 
 
190
 
TEST_F(ClientLibraryErrors, create_surface_returns_error_object_on_failure)
191
 
{
192
 
    mtf::UsingClientPlatform<ConfigurableFailureConfiguration<Method::create_buffer_factory>> stubby;
193
 
 
194
 
    auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
195
 
 
196
 
    ASSERT_THAT(connection, IsValid());
197
 
 
198
 
    auto surface = mtf::make_any_surface(connection);
199
 
    ASSERT_NE(surface, nullptr);
200
 
    EXPECT_FALSE(mir_surface_is_valid(surface));
201
 
    EXPECT_THAT(mir_surface_get_error_message(surface), testing::HasSubstr(exception_text));
202
 
 
203
 
    mir_surface_release_sync(surface);
204
 
    mir_connection_release(connection);
205
 
}
206
 
 
207
 
namespace
208
 
{
209
 
void recording_surface_callback(MirSurface*, void* ctx)
210
 
{
211
 
    auto called = static_cast<bool*>(ctx);
212
 
    *called = true;
213
 
}
214
 
}
215
 
 
216
 
TEST_F(ClientLibraryErrors, surface_release_on_error_object_still_calls_callback)
217
 
{
218
 
    mtf::UsingClientPlatform<ConfigurableFailureConfiguration<Method::create_buffer_factory>> stubby;
219
 
 
220
 
    auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
221
 
 
222
 
    ASSERT_THAT(connection, IsValid());
223
 
 
224
 
    auto surface = mtf::make_any_surface(connection);
225
 
 
226
 
    ASSERT_NE(surface, nullptr);
227
 
    EXPECT_FALSE(mir_surface_is_valid(surface));
228
 
    EXPECT_THAT(mir_surface_get_error_message(surface), testing::HasSubstr(exception_text));
229
 
 
230
 
    bool callback_called{false};
231
 
    mir_surface_release(surface, &recording_surface_callback, &callback_called);
232
 
    EXPECT_TRUE(callback_called);
233
 
    mir_connection_release(connection);
234
 
}
235
 
 
236
 
 
237
 
TEST_F(ClientLibraryErrors, create_surface_returns_error_object_on_failure_in_reply_processing)
238
 
{
239
 
    mtf::UsingClientPlatform<ConfigurableFailureConfiguration<Method::create_egl_native_window>> stubby;
240
 
 
241
 
    auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
242
 
 
243
 
    ASSERT_THAT(connection, IsValid());
244
 
 
245
 
    auto surface = mtf::make_any_surface(connection);
246
 
    ASSERT_NE(surface, nullptr);
247
 
    EXPECT_FALSE(mir_surface_is_valid(surface));
248
 
    EXPECT_THAT(mir_surface_get_error_message(surface), testing::HasSubstr(exception_text));
249
 
 
250
 
    mir_surface_release_sync(surface);
251
 
    mir_connection_release(connection);
252
 
}
253
 
 
254
 
TEST_F(ClientLibraryErrors, passing_invalid_parent_id_to_surface_create)
255
 
{
256
 
    using namespace testing;
257
 
 
258
 
    auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
259
 
 
260
 
    ASSERT_THAT(connection, IsValid());
261
 
 
262
 
    // An ID that parses as valid, but doesn't correspond to any
263
 
    auto invalid_id = mir_persistent_id_from_string("05f223a2-39e5-48b9-9416-b0ce837351b6");
264
 
 
265
 
    auto spec = mir_connection_create_spec_for_input_method(connection,
266
 
                                                            200, 200,
267
 
                                                            mir_pixel_format_argb_8888);
268
 
    MirRectangle rect{
269
 
        100,
270
 
        100,
271
 
        10,
272
 
        10
273
 
    };
274
 
    mir_surface_spec_attach_to_foreign_parent(spec, invalid_id, &rect, mir_edge_attachment_any);
275
 
 
276
 
    auto surface = mir_surface_create_sync(spec);
277
 
    EXPECT_THAT(surface, Not(IsValid()));
278
 
    EXPECT_THAT(mir_surface_get_error_message(surface), MatchesRegex(".*Lookup.*failed.*"));
279
 
 
280
 
    mir_persistent_id_release(invalid_id);
281
 
    mir_surface_spec_release(spec);
282
 
    mir_surface_release_sync(surface);
283
 
    mir_connection_release(connection);
284
 
}
285
 
 
286
 
using ClientLibraryErrorsDeathTest = ClientLibraryErrors;
287
 
 
288
 
 
289
 
TEST_F(ClientLibraryErrorsDeathTest, creating_surface_on_garbage_connection_is_fatal)
290
 
{
291
 
    mtf::UsingStubClientPlatform stubby;
292
 
 
293
 
    auto connection = mir_connect_sync("garbage", __PRETTY_FUNCTION__);
294
 
 
295
 
    ASSERT_FALSE(mir_connection_is_valid(connection));
296
 
    EXPECT_DEATH(
297
 
        mtf::make_any_surface(connection), "");
298
 
 
299
 
    mir_connection_release(connection);
300
 
}
301
 
 
302
 
 
303
 
TEST_F(ClientLibraryErrorsDeathTest, creating_surface_synchronosly_on_malconstructed_connection_is_fatal)
304
 
{
305
 
    mtf::UsingClientPlatform<ConfigurableFailureConfiguration<Method::the_client_platform_factory>> stubby;
306
 
 
307
 
    auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
308
 
 
309
 
    ASSERT_FALSE(mir_connection_is_valid(connection));
310
 
    EXPECT_DEATH(mtf::make_any_surface(connection), "");
311
 
 
312
 
    mir_connection_release(connection);
313
 
}
314
 
 
315
 
TEST_F(ClientLibraryErrorsDeathTest, creating_surface_synchronosly_on_invalid_connection_is_fatal)
316
 
{
317
 
    mtf::UsingClientPlatform<ConfigurableFailureConfiguration<Method::create_client_platform>> stubby;
318
 
 
319
 
    auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
320
 
 
321
 
    ASSERT_FALSE(mir_connection_is_valid(connection));
322
 
    EXPECT_DEATH(mtf::make_any_surface(connection), "");
323
 
 
324
 
    mir_connection_release(connection);
325
 
}
326
 
 
327
 
TEST_F(ClientLibraryErrorsDeathTest, surface_spec_attaching_invalid_parent_id)
328
 
{
329
 
    auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
330
 
 
331
 
    auto spec = mir_connection_create_spec_for_input_method(connection, 100, 100, mir_pixel_format_argb_8888);
332
 
 
333
 
    MirRectangle rect{
334
 
        100,
335
 
        100,
336
 
        10,
337
 
        10
338
 
    };
339
 
    EXPECT_DEATH(mir_surface_spec_attach_to_foreign_parent(spec, nullptr, &rect, mir_edge_attachment_any), "");
340
 
 
341
 
    mir_connection_release(connection);
342
 
}
343
 
 
344
 
TEST_F(ClientLibraryErrorsDeathTest, surface_spec_attaching_invalid_rectangle)
345
 
{
346
 
    auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
347
 
 
348
 
    auto spec = mir_connection_create_spec_for_input_method(connection, 100, 100, mir_pixel_format_argb_8888);
349
 
 
350
 
    auto id = mir_persistent_id_from_string("fa69b2e9-d507-4005-be61-5068f40a5aec");
351
 
 
352
 
    EXPECT_DEATH(mir_surface_spec_attach_to_foreign_parent(spec, id, nullptr, mir_edge_attachment_any), "");
353
 
 
354
 
    mir_persistent_id_release(id);
355
 
    mir_connection_release(connection);
356
 
}