Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ find_package(GtestGmock)
pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client)
pkg_check_modules(WAYLAND_SERVER REQUIRED wayland-server)
pkg_check_modules(WAYLAND_SCANNER REQUIRED wayland-scanner)
pkg_check_modules(DRM REQUIRED libdrm IMPORTED_TARGET)

include_directories(include)
include_directories(${Boost_INCLUDE_DIRS})
Expand Down Expand Up @@ -137,6 +138,7 @@ GENERATE_PROTOCOL(wlr-virtual-pointer-unstable-v1)
GENERATE_PROTOCOL(xdg-decoration-unstable-v1)
GENERATE_PROTOCOL(viewporter)
GENERATE_PROTOCOL(fractional-scale-v1)
GENERATE_PROTOCOL(linux-drm-syncobj-v1)

option(WLCS_BUILD_ASAN "Build a test runner with AddressSanitizer annotations" ON)
option(WLCS_BUILD_TSAN "Build a test runner with ThreadSanitizer annotations" ON)
Expand Down Expand Up @@ -170,6 +172,7 @@ set(WLCS_TESTS
tests/xdg_decoration_v1.cpp
tests/wp_viewporter.cpp
tests/fractional_scale_v1.cpp
tests/linux_drm_syncobj_v1.cpp
)

set(
Expand All @@ -179,6 +182,7 @@ set(
include/wlcs/pointer.h
include/wlcs/touch.h
include/expect_protocol_error.h
include/gtest_matchers.h
include/helpers.h
include/wl_handle.h
include/in_process_server.h
Expand Down Expand Up @@ -280,6 +284,7 @@ foreach(TARGET IN LISTS EXECUTABLE_TARGETS)

${GMOCK_LIBRARY}
${GTEST_LIBRARY}
PkgConfig::DRM
)
endforeach(TARGET)

Expand Down
1 change: 1 addition & 0 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Build-Depends:
debhelper (>= 9),
cmake,
libboost-dev,
libdrm-dev,
libgtest-dev,
libwayland-dev,
pkg-config,
Expand Down
2 changes: 2 additions & 0 deletions include/expect_protocol_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
} catch (wlcs::ProtocolError const& err) {\
EXPECT_THAT(err.interface(), Eq(iface));\
EXPECT_THAT(err.error_code(), Eq(err_code));\
if (err.interface() != iface || err.error_code() != err_code)\
throw;\
}

#endif // WLCS_EXPECT_PROTOCOL_ERROR_H_
119 changes: 119 additions & 0 deletions include/gtest_matchers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Copyright © 2017-2019 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include "in_process_server.h"

MATCHER_P2(IsSurfaceOfSize, width, height, "")
{
auto& surface = const_cast<wlcs::Surface&>(arg);
auto& client = arg.owner();
auto& server = client.owner();

server.move_surface_to(surface, 100, 100);

auto pointer = server.create_pointer();

// Use a shared ptr to extend the lifetime of the variables until the
// pointer/motion notifications are done with them. Otherwise, we get a
// use-after-free.
auto const pointer_entered = std::make_shared<bool>(false);
auto const motion_received = std::make_shared<bool>(false);
client.add_pointer_enter_notification(
[&surface, pointer_entered](auto entered_surface, auto, auto)
{
*pointer_entered = (entered_surface == surface);
return false;
});

// First ensure we are *not* on the surface...
pointer.move_to(0, 0);
// ...then move onto the surface, so our enter notification fires
pointer.move_to(100, 100);
client.dispatch_until([pointer_entered]() { return *pointer_entered; });

// Should be on the top left of the surface
if (client.window_under_cursor() != surface)
{
*result_listener << "Surface at unexpected location (test harness bug?)";
return false;
}
if (client.pointer_position() != std::make_pair(wl_fixed_from_int(0), wl_fixed_from_int(0)))
{
BOOST_THROW_EXCEPTION((std::runtime_error{"Surface at unexpected location (test harness bug?)"}));
}

client.add_pointer_motion_notification(
[motion_received](auto, auto)
{
*motion_received = true;
return false;
});
client.add_pointer_leave_notification(
[pointer_entered](auto)
{
*pointer_entered = false;
return false;
});

pointer.move_by(width - 1, height - 1);
client.dispatch_until([&]() { return *motion_received || !*pointer_entered; });

// Should now be at bottom corner of surface
if (client.window_under_cursor() != surface)
{
*result_listener << "Surface smaller than (" << width << "×" << height << ")";
ADD_FAILURE() << "Surface size too small";
return false;
}
if (client.pointer_position() != std::make_pair(wl_fixed_from_int(width - 1), wl_fixed_from_int(height - 1)))
{
auto const [x, y] = client.pointer_position();
*result_listener << "Surface coordinate system incorrect; expected (" << width - 1 << ", " << height - 1 << ") got ("
<< wl_fixed_to_double(x) << ", " << wl_fixed_to_double(y) << ")";
return false;
}

// Moving any further should take us out of the surface
*motion_received = false;

client.add_pointer_leave_notification(
[pointer_entered](auto)
{
*pointer_entered = false;
return false;
});

client.add_pointer_motion_notification(
[motion_received](auto, auto)
{
*motion_received = true;
return false;
});

pointer.move_by(1, 1);
client.dispatch_until([&]() { return !*pointer_entered || *motion_received; });

if (client.window_under_cursor() == surface)
{
*result_listener << "Surface too large";
return false;
}

return true;
}
2 changes: 2 additions & 0 deletions include/in_process_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ class Client

// Accessors

Server& owner() const;

operator wl_display*() const;

wl_compositor* compositor() const;
Expand Down
3 changes: 2 additions & 1 deletion spread/build/alpine/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ execute: |
wayland-dev \
cmake \
boost-dev \
gtest-dev
gtest-dev \
libdrm-dev

cd $SPREAD_PATH
cd $(mktemp --directory)
Expand Down
1 change: 1 addition & 0 deletions spread/build/archlinux/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ execute: |
base-devel \
cmake \
boost \
libdrm \
wayland \
wayland-protocols \
gtest
Expand Down
3 changes: 2 additions & 1 deletion spread/build/fedora/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ execute: |
pkg-config \
boost-devel \
gtest-devel \
gmock-devel
gmock-devel \
libdrm-devel

cd $SPREAD_PATH
cd $(mktemp --directory)
Expand Down
1 change: 1 addition & 0 deletions spread/build/ubuntu/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ execute: |
libgtest-dev \
google-mock \
libboost-dev \
libdrm-dev \
mir-test-tools

# Check that we build…
Expand Down
15 changes: 14 additions & 1 deletion src/in_process_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,8 @@ class wlcs::Client::Impl
{
public:
Impl(Server& server)
: supported_extensions{server.supported_extensions()}
: owner_{server},
supported_extensions{server.supported_extensions()}
{
try
{
Expand Down Expand Up @@ -708,6 +709,11 @@ class wlcs::Client::Impl
wl_display_disconnect(display);
}

auto owner() const -> Server&
{
return owner_;
}

struct wl_display* wl_display() const
{
return display;
Expand Down Expand Up @@ -1646,6 +1652,8 @@ class wlcs::Client::Impl
&global_removed
};

Server& owner_;

std::shared_ptr<std::unordered_map<std::string, uint32_t> const> const supported_extensions;

struct wl_display* display;
Expand Down Expand Up @@ -1705,6 +1713,11 @@ wlcs::Client::Client(Server& server)

wlcs::Client::~Client() = default;

auto wlcs::Client::owner() const -> Server&
{
return impl->owner();
}

wlcs::Client::operator wl_display*() const
{
return impl->wl_display();
Expand Down
Loading