Flutter Engine
The Flutter Engine
focus_delegate_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <fuchsia/ui/views/cpp/fidl.h>
6#include <gtest/gtest.h>
7#include <lib/async-loop/cpp/loop.h>
8#include <lib/async-loop/default.h>
9#include <lib/fidl/cpp/binding_set.h>
10#include <lib/zx/eventpair.h>
11
12#include "focus_delegate.h"
13#include "tests/fakes/focuser.h"
16#include "third_party/rapidjson/include/rapidjson/document.h"
17
18rapidjson::Value ParsePlatformMessage(std::string json) {
19 rapidjson::Document document;
20 document.Parse(json);
21 if (document.HasParseError() || !document.IsObject()) {
22 FML_LOG(ERROR) << "Could not parse document";
23 return rapidjson::Value();
24 }
25 return document.GetObject();
26}
27
29
30class FocusDelegateTest : public ::testing::Test {
31 protected:
32 FocusDelegateTest() : loop_(&kAsyncLoopConfigAttachToCurrentThread) {}
33
34 void RunLoopUntilIdle() { loop_.RunUntilIdle(); }
35
36 void SetUp() override {
37 vrf_ = std::make_unique<FakeViewRefFocused>();
38 focuser_ = std::make_unique<FakeFocuser>();
39 focus_delegate_ = std::make_unique<FocusDelegate>(
40 vrf_bindings.AddBinding(vrf_.get()),
41 focuser_bindings.AddBinding(focuser_.get()));
42 }
43
44 void TearDown() override {
45 vrf_bindings.CloseAll();
46 focuser_bindings.CloseAll();
47 loop_.Quit();
48 loop_.ResetQuit();
49 }
50
51 std::unique_ptr<FakeViewRefFocused> vrf_;
52 std::unique_ptr<FakeFocuser> focuser_;
53 std::unique_ptr<FocusDelegate> focus_delegate_;
54
55 private:
56 async::Loop loop_;
57 fidl::BindingSet<ViewRefFocused> vrf_bindings;
58 fidl::BindingSet<Focuser> focuser_bindings;
59
60 FML_DISALLOW_COPY_AND_ASSIGN(FocusDelegateTest);
61};
62
63// Tests that WatchLoop() should callback and complete PlatformMessageResponses
64// correctly, given a series of vrf invocations.
65TEST_F(FocusDelegateTest, WatchCallbackSeries) {
66 std::vector<bool> vrf_states{false, true, true, false,
67 true, false, true, true};
68 std::size_t vrf_index = 0;
69 std::size_t callback_index = 0;
70 focus_delegate_->WatchLoop([&](bool focus_state) {
71 // Make sure the focus state that FocusDelegate gives us is consistent with
72 // what was fired from the vrf.
73 EXPECT_EQ(vrf_states[callback_index], focus_state);
74
75 // View.focus.getCurrent should complete with the current (up to date) focus
76 // state.
78 EXPECT_TRUE(focus_delegate_->HandlePlatformMessage(
79 ParsePlatformMessage("{\"method\":\"View.focus.getCurrent\"}"),
80 response));
81 response->ExpectCompleted(focus_state ? "[true]" : "[false]");
82
83 // Ensure this callback always happens in lockstep with
84 // vrf_->ScheduleCallback.
85 EXPECT_EQ(vrf_index, callback_index++);
86 });
87
88 // Subsequent WatchLoop calls should not be respected.
89 focus_delegate_->WatchLoop([](bool _) {
90 ADD_FAILURE() << "Subsequent WatchLoops should not be respected!";
91 });
92
93 do {
94 // Ensure the next focus state is handled correctly.
95 auto response1 = FakePlatformMessageResponse::Create();
96 EXPECT_TRUE(focus_delegate_->HandlePlatformMessage(
97 ParsePlatformMessage("{\"method\":\"View.focus.getNext\"}"),
98 response1));
99
100 // Since there's already an outstanding PlatformMessageResponse, this one
101 // should be completed null.
102 auto response2 = FakePlatformMessageResponse::Create();
103 EXPECT_TRUE(focus_delegate_->HandlePlatformMessage(
104 ParsePlatformMessage("{\"method\":\"View.focus.getNext\"}"),
105 response2));
106 response2->ExpectCompleted("[null]");
107
108 // Post watch events and trigger the next vrf event.
109 RunLoopUntilIdle();
110 vrf_->ScheduleCallback(vrf_states[vrf_index]);
111 RunLoopUntilIdle();
112
113 // Next focus state should be completed by now.
114 response1->ExpectCompleted(vrf_states[vrf_index] ? "[true]" : "[false]");
115
116 // Check View.focus.getCurrent again, and increment vrf_index since we move
117 // on to the next focus state.
118 auto response3 = FakePlatformMessageResponse::Create();
119 EXPECT_TRUE(focus_delegate_->HandlePlatformMessage(
120 ParsePlatformMessage("{\"method\":\"View.focus.getCurrent\"}"),
121 response3));
122 response3->ExpectCompleted(vrf_states[vrf_index++] ? "[true]" : "[false]");
123
124 // vrf_->times_watched should always be 1 more than the amount of vrf events
125 // emitted.
126 EXPECT_EQ(vrf_index + 1, vrf_->times_watched);
127 } while (vrf_index < vrf_states.size());
128}
129
130// Tests that HandlePlatformMessage() completes a "View.focus.request" response
131// with a non-error status code.
132TEST_F(FocusDelegateTest, RequestFocusTest) {
133 // This "Mock" ViewRef serves as the target for the RequestFocus operation.
134 fuchsia::ui::views::ViewRefControl view_ref_control;
135 fuchsia::ui::views::ViewRef view_ref;
136 auto status = zx::eventpair::create(
137 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
138 ZX_ASSERT(status == ZX_OK);
139 view_ref_control.reference.replace(
140 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
141 &view_ref_control.reference);
142 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
143
144 // Create the platform message request.
145 std::ostringstream message;
146 message << "{" << " \"method\":\"View.focus.request\","
147 << " \"args\": {"
148 << " \"viewRef\":" << view_ref.reference.get() << " }"
149 << "}";
150
151 // Dispatch the plaform message request with an expected completion response.
152 auto response = FakePlatformMessageResponse::Create();
153 EXPECT_TRUE(focus_delegate_->HandlePlatformMessage(
154 ParsePlatformMessage(message.str()), response));
155 RunLoopUntilIdle();
156
157 response->ExpectCompleted("[0]");
158 EXPECT_TRUE(focuser_->request_focus_called());
159}
160
161// Tests that HandlePlatformMessage() completes a "View.focus.request" response
162// with a Error::DENIED status code.
163TEST_F(FocusDelegateTest, RequestFocusFailTest) {
164 // This "Mock" ViewRef serves as the target for the RequestFocus operation.
165 fuchsia::ui::views::ViewRefControl view_ref_control;
166 fuchsia::ui::views::ViewRef view_ref;
167 auto status = zx::eventpair::create(
168 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
169 ZX_ASSERT(status == ZX_OK);
170 view_ref_control.reference.replace(
171 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
172 &view_ref_control.reference);
173 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
174 // We're testing the focus failure case.
175 focuser_->fail_request_focus();
176 // Create the platform message request.
177 std::ostringstream message;
178 message << "{" << " \"method\":\"View.focus.request\","
179 << " \"args\": {"
180 << " \"viewRef\":" << view_ref.reference.get() << " }"
181 << "}";
182
183 // Dispatch the plaform message request with an expected completion response.
184 auto response = FakePlatformMessageResponse::Create();
185 EXPECT_TRUE(focus_delegate_->HandlePlatformMessage(
186 ParsePlatformMessage(message.str()), response));
187 RunLoopUntilIdle();
188
189 response->ExpectCompleted(
190 "[" +
192 static_cast<std::underlying_type_t<fuchsia::ui::views::Error>>(
193 fuchsia::ui::views::Error::DENIED)) +
194 "]");
195 EXPECT_TRUE(focuser_->request_focus_called());
196}
197
198} // namespace flutter_runner::testing
static fml::RefPtr< FakePlatformMessageResponse > Create()
std::unique_ptr< FocusDelegate > focus_delegate_
std::unique_ptr< FakeViewRefFocused > vrf_
#define FML_LOG(severity)
Definition: logging.h:82
rapidjson::Value ParsePlatformMessage(std::string json)
Win32Message message
TEST_F(FocusDelegateTest, WatchCallbackSeries)
static SkString to_string(int n)
Definition: nanobench.cpp:119
int_closure create
#define ERROR(message)
Definition: elf_loader.cc:260
#define EXPECT_TRUE(handle)
Definition: unit_test.h:678