From c10fc7bc71d683030b9159fdd56f66b873ecc411 Mon Sep 17 00:00:00 2001 From: Alexander Dunaev Date: Tue, 22 Jan 2019 12:26:37 +0100 Subject: [PATCH] More mock classes are introduced. --- ui/ozone/platform/wayland/BUILD.gn | 1 + ui/ozone/platform/wayland/fake_server.cc | 50 +++++++++---- ui/ozone/platform/wayland/fake_server.h | 16 ++++ .../platform/wayland/wayland_buffer_fuzzer.cc | 73 +++++++++++++++---- .../wayland/wayland_buffer_manager.cc | 3 + 5 files changed, 117 insertions(+), 26 deletions(-) diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn index 1c88f1ac9978c..26b42279098d8 100644 --- a/ui/ozone/platform/wayland/BUILD.gn +++ b/ui/ozone/platform/wayland/BUILD.gn @@ -211,6 +211,7 @@ fuzzer_test("wayland_buffer_fuzzer") { "//third_party/wayland-protocols:linux_dmabuf_protocol", "//third_party/wayland-protocols:text_input_protocol", "//third_party/wayland-protocols:xdg_shell_protocol", + "//ui/gfx:test_support", "//ui/ozone/common/linux:drm", "//ui/ozone:platform", ] diff --git a/ui/ozone/platform/wayland/fake_server.cc b/ui/ozone/platform/wayland/fake_server.cc index 3a9e966990f7b..f89737302b6aa 100644 --- a/ui/ozone/platform/wayland/fake_server.cc +++ b/ui/ozone/platform/wayland/fake_server.cc @@ -111,6 +111,12 @@ void CreatePipe(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe) { write_pipe->reset(raw_pipe[1]); } +// wl_buffer + +const struct wl_buffer_interface wl_buffer_impl = {&DestroyResource}; + +// wl_zwp_linux_buffer_params_v1 + void MockZwpLinuxBufferParamsV1_Add(wl_client* client, wl_resource* resource, int32_t fd, @@ -119,9 +125,11 @@ void MockZwpLinuxBufferParamsV1_Add(wl_client* client, uint32_t stride, uint32_t modifier_hi, uint32_t modifier_lo) { - static_cast(wl_resource_get_user_data(resource)) - ->Add(client, resource, fd, plane_idx, offset, stride, modifier_hi, - modifier_lo); + auto* buffer_params = GetUserDataAs(resource); + + buffer_params->fds_.emplace_back(fd); + buffer_params->Add(client, resource, fd, plane_idx, offset, stride, + modifier_hi, modifier_lo); } void MockZwpLinuxBufferParamsV1_Create(wl_client* client, @@ -130,6 +138,17 @@ void MockZwpLinuxBufferParamsV1_Create(wl_client* client, int32_t height, uint32_t format, uint32_t flags) { + auto* buffer_params = GetUserDataAs(resource); + + wl_resource* buffer_resource = + wl_resource_create(client, &wl_buffer_interface, 1, 0); + + SetImplementation(buffer_resource, &wl_buffer_impl, + std::make_unique( + buffer_resource, std::move(buffer_params->fds_))); + + zwp_linux_buffer_params_v1_send_created(resource, buffer_resource); + static_cast(wl_resource_get_user_data(resource)) ->Create(client, resource, width, height, format, flags); } @@ -598,21 +617,16 @@ const struct zwp_text_input_manager_v1_interface void CreateParams(wl_client* client, wl_resource* resource, - uint32_t params_id) { + uint32_t id) { wl_resource* buffer_params_resource = wl_resource_create(client, &zwp_linux_buffer_params_v1_interface, - wl_resource_get_version(resource), params_id); - if (!buffer_params_resource) { - wl_client_post_no_memory(client); - return; - } - + wl_resource_get_version(resource), id); SetImplementation( buffer_params_resource, &zwp_linux_buffer_params_v1_impl, std::make_unique(buffer_params_resource)); - static_cast(wl_resource_get_user_data(resource)) - ->CreateParams(client, resource, params_id); + GetUserDataAs(resource)->CreateParams( + client, resource, id); } const struct zwp_linux_dmabuf_v1_interface zwp_linux_dmabuf_v1_impl = { @@ -1096,6 +1110,16 @@ MockZwpLinuxBufferParamsV1::MockZwpLinuxBufferParamsV1(wl_resource* resource) MockZwpLinuxBufferParamsV1::~MockZwpLinuxBufferParamsV1() {} +MockBuffer::MockBuffer(wl_resource* resource, std::vector&& fds) + : ServerObject(resource), fds_(std::move(fds)) {} + +MockBuffer::~MockBuffer() { + for (auto& fd : fds_) { + LOG(WARNING) << "Will close FD: " << fd.get(); + fd.reset(); + } +} + void GlobalDeleter::operator()(wl_global* global) { wl_global_destroy(global); } @@ -1296,7 +1320,7 @@ void FakeServer::DoPause() { } std::unique_ptr FakeServer::CreateMessagePump() { - auto pump = base::WrapUnique(new base::MessagePumpLibevent); + auto pump = std::make_unique(); pump->WatchFileDescriptor(wl_event_loop_get_fd(event_loop_), true, base::MessagePumpLibevent::WATCH_READ, &controller_, this); diff --git a/ui/ozone/platform/wayland/fake_server.h b/ui/ozone/platform/wayland/fake_server.h index a4972b8648871..99ded42a376c7 100644 --- a/ui/ozone/platform/wayland/fake_server.h +++ b/ui/ozone/platform/wayland/fake_server.h @@ -294,10 +294,26 @@ class MockZwpLinuxBufferParamsV1 : public ServerObject { uint32_t format, uint32_t flags)); + std::vector fds_; + private: DISALLOW_COPY_AND_ASSIGN(MockZwpLinuxBufferParamsV1); }; +// Manage wl_buffer object. +class MockBuffer : public ServerObject { + public: + MockBuffer(wl_resource* resource, std::vector&& fds); + ~MockBuffer() override; + + MOCK_METHOD2(Destroy, void(wl_client* client, wl_resource* resource)); + + private: + std::vector fds_; + + DISALLOW_COPY_AND_ASSIGN(MockBuffer); +}; + struct GlobalDeleter { void operator()(wl_global* global); }; diff --git a/ui/ozone/platform/wayland/wayland_buffer_fuzzer.cc b/ui/ozone/platform/wayland/wayland_buffer_fuzzer.cc index 2954140f829bc..956db5cac35c0 100644 --- a/ui/ozone/platform/wayland/wayland_buffer_fuzzer.cc +++ b/ui/ozone/platform/wayland/wayland_buffer_fuzzer.cc @@ -17,9 +17,50 @@ #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/test/fuzzed_data_provider.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/gfx/geometry/rect.h" #include "ui/ozone/common/linux/drm_util_linux.h" #include "ui/ozone/platform/wayland/fake_server.h" #include "ui/ozone/platform/wayland/wayland_connection.h" +#include "ui/ozone/platform/wayland/wayland_window.h" +#include "ui/platform_window/platform_window_delegate.h" +#include "ui/platform_window/platform_window_init_properties.h" + +namespace { + +// Off-class equivalent of WaylandTest::Sync. +void Sync(wl::FakeServer* server) { + DCHECK(server); + + server->Resume(); + base::RunLoop().RunUntilIdle(); + server->Pause(); +} + +// Copied from ui/ozone/test/mock_platform_window_delegate.h to avoid +// dependency from the whole library (it causes link problems). +class MockPlatformWindowDelegate : public ui::PlatformWindowDelegate { + public: + MockPlatformWindowDelegate() = default; + ~MockPlatformWindowDelegate() = default; + + MOCK_METHOD1(OnBoundsChanged, void(const gfx::Rect& new_bounds)); + MOCK_METHOD1(OnDamageRect, void(const gfx::Rect& damaged_region)); + MOCK_METHOD1(DispatchEvent, void(ui::Event* event)); + MOCK_METHOD0(OnCloseRequest, void()); + MOCK_METHOD0(OnClosed, void()); + MOCK_METHOD1(OnWindowStateChanged, void(ui::PlatformWindowState new_state)); + MOCK_METHOD0(OnLostCapture, void()); + MOCK_METHOD1(OnAcceleratedWidgetAvailable, + void(gfx::AcceleratedWidget widget)); + MOCK_METHOD0(OnAcceleratedWidgetDestroyed, void()); + MOCK_METHOD1(OnActivationChanged, void(bool active)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockPlatformWindowDelegate); +}; + +} // namespace extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { base::FuzzedDataProvider data_provider(data, size); @@ -32,17 +73,31 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { base::MessageLoopForUI message_loop; - wl::FakeServer server; + MockPlatformWindowDelegate delegate; std::unique_ptr connection = std::make_unique(); + std::unique_ptr window = + std::make_unique(&delegate, connection.get()); + gfx::AcceleratedWidget widget = gfx::kNullAcceleratedWidget; + + wl::FakeServer server; CHECK(server.Start(6)); CHECK(connection->Initialize()); + EXPECT_CALL(delegate, OnAcceleratedWidgetAvailable(testing::_)) + .WillOnce(testing::SaveArg<0>(&widget)); + ui::PlatformWindowInitProperties properties; + properties.bounds = gfx::Rect(0, 0, 800, 600); + properties.type = ui::PlatformWindowType::kWindow; + CHECK(window->Initialize(std::move(properties))); + CHECK_NE(widget, gfx::kNullAcceleratedWidget); + base::RunLoop().RunUntilIdle(); server.Pause(); base::FilePath temp_path; EXPECT_TRUE(base::CreateTemporaryFile(&temp_path)); + LOG(WARNING) << temp_path; base::File temp(temp_path, base::File::FLAG_WRITE | base::File::FLAG_CREATE_ALWAYS); @@ -70,21 +125,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { offsets, format, modifiers, planes_count, kBufferId); - server.Resume(); - // Wait for the client to finish processing events, if any. - base::RunLoop().RunUntilIdle(); - server.Pause(); + Sync(&server); + Sync(&server); connection->DestroyZwpLinuxDmabuf(kBufferId); - server.Resume(); - // Wait for the client to finish processing events, if any. - base::RunLoop().RunUntilIdle(); - server.Pause(); - - // Pause the server, after it has finished processing any follow-up requests - // from the client. - // server.Pause(); + Sync(&server); + Sync(&server); return 0; } diff --git a/ui/ozone/platform/wayland/wayland_buffer_manager.cc b/ui/ozone/platform/wayland/wayland_buffer_manager.cc index 368aa6e5ad433..e8c188d70cdee 100644 --- a/ui/ozone/platform/wayland/wayland_buffer_manager.cc +++ b/ui/ozone/platform/wayland/wayland_buffer_manager.cc @@ -110,6 +110,7 @@ bool WaylandBufferManager::CreateBuffer(base::File file, uint32_t fd = file.TakePlatformFile(); LOG(WARNING) << "File descriptor " << fd; for (size_t i = 0; i < planes_count; i++) { + LOG(WARNING) << "Adding params for plane " << i; zwp_linux_buffer_params_v1_add(params, fd, i /* plane id */, offsets[i], strides[i], modifiers[i] >> 32, modifiers[i] & UINT32_MAX); @@ -159,6 +160,7 @@ bool WaylandBufferManager::ScheduleBufferSwap(gfx::AcceleratedWidget widget, bool WaylandBufferManager::DestroyBuffer(uint32_t buffer_id) { TRACE_EVENT1("wayland", "WaylandBufferManager::DestroyZwpLinuxDmabuf", "Buffer id", buffer_id); + LOG(WARNING) << __FUNCTION__ << ": " << buffer_id; auto it = buffers_.find(buffer_id); if (it == buffers_.end()) { @@ -174,6 +176,7 @@ bool WaylandBufferManager::DestroyBuffer(uint32_t buffer_id) { gfx::PresentationFeedback(base::TimeTicks::Now(), base::TimeDelta(), 0)); } + LOG(WARNING) << "Erasing"; buffers_.erase(it); connection_->ScheduleFlush();