Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Typedefs | Functions | Variables
flutter_runner::testing Namespace Reference

Classes

struct  BufferCollectionTokenPair
 
class  ExternalViewEmbedderTest
 
class  FakeFlatland
 
class  FakeFlatlandTest
 
class  FakeFocuser
 
struct  FakeGraph
 
struct  FakeImage
 
class  FakeImeService
 
class  FakeKeyboardService
 
class  FakeMouseSource
 
class  FakePlatformMessageResponse
 
class  FakeTouchSource
 
struct  FakeTransform
 
struct  FakeView
 
struct  FakeViewport
 
class  FakeViewRefFocused
 
class  FlatlandConnectionTest
 
class  FocusDelegateTest
 
class  MockInjectorRegistry
 
class  MouseEventBuilder
 
class  PlatformViewTests
 
class  PointerDelegateTest
 
class  PointerInjectorDelegateTest
 
class  TextDelegateTest
 
class  TouchEventBuilder
 
struct  ViewTokenPair
 

Typedefs

using fup_EventPhase = fuchsia::ui::pointer::EventPhase
 
using fup_TouchEvent = fuchsia::ui::pointer::TouchEvent
 
using fup_TouchIxnId = fuchsia::ui::pointer::TouchInteractionId
 
using fup_TouchIxnResult = fuchsia::ui::pointer::TouchInteractionResult
 
using fup_TouchIxnStatus = fuchsia::ui::pointer::TouchInteractionStatus
 
using fup_TouchPointerSample = fuchsia::ui::pointer::TouchPointerSample
 
using fup_TouchResponse = fuchsia::ui::pointer::TouchResponse
 
using fup_TouchResponseType = fuchsia::ui::pointer::TouchResponseType
 
using fup_ViewParameters = fuchsia::ui::pointer::ViewParameters
 
using fup_MouseEvent = fuchsia::ui::pointer::MouseEvent
 
using fup_DeviceType = fuchsia::ui::pointerinjector::DeviceType
 
using fup_DispatchPolicy = fuchsia::ui::pointerinjector::DispatchPolicy
 
using fup_RegistryHandle = fuchsia::ui::pointerinjector::RegistryHandle
 
using fuv_ViewRef = fuchsia::ui::views::ViewRef
 
using FakeContent = std::variant< FakeViewport, FakeImage >
 
using fup_MousePointerSample = fuchsia::ui::pointer::MousePointerSample
 
using fup_MouseDeviceInfo = fuchsia::ui::pointer::MouseDeviceInfo
 

Functions

 TEST_F (FocusDelegateTest, WatchCallbackSeries)
 
 TEST_F (FocusDelegateTest, RequestFocusTest)
 
 TEST_F (FocusDelegateTest, RequestFocusFailTest)
 
 TEST_F (PointerDelegateTest, Data_FuchsiaTimeVersusFlutterTime)
 
 TEST_F (PointerDelegateTest, Phase_FlutterPhasesAreSynthesized)
 
 TEST_F (PointerDelegateTest, Phase_FuchsiaCancelBecomesFlutterCancel)
 
 TEST_F (PointerDelegateTest, Coordinates_CorrectMapping)
 
 TEST_F (PointerDelegateTest, Coordinates_DownEventClampedToView)
 
 TEST_F (PointerDelegateTest, Protocol_FirstResponseIsEmpty)
 
 TEST_F (PointerDelegateTest, Protocol_ResponseMatchesEarlierEvents)
 
 TEST_F (PointerDelegateTest, Protocol_LateGrant)
 
 TEST_F (PointerDelegateTest, Protocol_LateGrantCombo)
 
 TEST_F (PointerDelegateTest, Protocol_EarlyGrant)
 
 TEST_F (PointerDelegateTest, Protocol_LateDeny)
 
 TEST_F (PointerDelegateTest, Protocol_LateDenyCombo)
 
 TEST_F (PointerDelegateTest, Protocol_PointersAreIndependent)
 
 TEST_F (PointerDelegateTest, MouseWheel_TickBased)
 
 TEST_F (PointerDelegateTest, MouseWheel_PixelBased)
 
 TEST_F (PointerDelegateTest, MouseWheel_TouchpadPixelBased)
 
 TEST_P (PointerInjectorDelegateTest, IncorrectPlatformMessage_ShouldFail)
 
 TEST_P (PointerInjectorDelegateTest, ViewsReceiveInjectedEvents)
 
 TEST_P (PointerInjectorDelegateTest, ViewsDontReceivePointerEventsBeforeCreation)
 
 TEST_P (PointerInjectorDelegateTest, ValidRegistrationConfigTest)
 
 TEST_P (PointerInjectorDelegateTest, ValidPointerEventTest)
 
 TEST_P (PointerInjectorDelegateTest, DestroyedViewsDontGetPointerEvents)
 
 TEST_P (PointerInjectorDelegateTest, ViewsGetPointerEventsInFIFO)
 
 TEST_P (PointerInjectorDelegateTest, DeviceRetriesRegisterWhenClosed)
 
 INSTANTIATE_TEST_SUITE_P (PointerInjectorDelegateParameterizedTest, PointerInjectorDelegateTest, ::testing::Bool())
 
 TEST (EngineTest, ThreadNames)
 
 TEST_F (ExternalViewEmbedderTest, RootScene)
 
 TEST_F (ExternalViewEmbedderTest, SimpleScene)
 
 TEST_F (ExternalViewEmbedderTest, SceneWithOneView)
 
 TEST_F (ExternalViewEmbedderTest, SceneWithOneClippedView)
 
 TEST_F (ExternalViewEmbedderTest, SceneWithOneView_NoOverlay)
 
 TEST_F (ExternalViewEmbedderTest, SceneWithOneView_DestroyBeforeDrawing)
 
 TEST_F (ExternalViewEmbedderTest, SimpleScene_DisjointHitRegions)
 
 TEST_F (ExternalViewEmbedderTest, SimpleScene_OverlappingHitRegions)
 
 TEST_F (ExternalViewEmbedderTest, ViewportCoveredWithInputInterceptor)
 
 TEST_F (FakeFlatlandTest, Initialization)
 
 TEST_F (FakeFlatlandTest, DebugLabel)
 
 TEST_F (FakeFlatlandTest, Present)
 
template<typename ZX >
std::pair< zx_koid_t, zx_koid_t > GetKoids (const ZX &kobj)
 
template<typename F >
std::pair< zx_koid_t, zx_koid_t > GetKoids (const fidl::InterfaceHandle< F > &interface_handle)
 
template<typename F >
std::pair< zx_koid_t, zx_koid_t > GetKoids (const fidl::InterfaceRequest< F > &interface_request)
 
template<typename F >
std::pair< zx_koid_t, zx_koid_t > GetKoids (const fidl::InterfacePtr< F > &interface_ptr)
 
template<typename F >
std::pair< zx_koid_t, zx_koid_t > GetKoids (const fidl::Binding< F > &interface_binding)
 
std::pair< zx_koid_t, zx_koid_t > GetKoids (const fuchsia::ui::views::ViewCreationToken &view_token)
 
std::pair< zx_koid_t, zx_koid_t > GetKoids (const fuchsia::ui::views::ViewportCreationToken &viewport_token)
 
std::pair< zx_koid_t, zx_koid_t > GetKoids (const fuchsia::ui::views::ViewRef &view_ref)
 
std::pair< zx_koid_t, zx_koid_t > GetKoids (const fuchsia::ui::views::ViewRefControl &view_ref_control)
 
std::pair< zx_koid_t, zx_koid_t > GetKoids (const fuchsia::ui::composition::BufferCollectionExportToken &buffer_collection_token)
 
std::pair< zx_koid_t, zx_koid_t > GetKoids (const fuchsia::ui::composition::BufferCollectionImportToken &buffer_collection_token)
 
 TEST_F (FlatlandConnectionTest, Initialization)
 
 TEST_F (FlatlandConnectionTest, FlatlandDisconnect)
 
 TEST_F (FlatlandConnectionTest, BasicPresent)
 
 TEST_F (FlatlandConnectionTest, AwaitVsyncsBeforeOnNextFrameBegin)
 
 TEST_F (FlatlandConnectionTest, RunsOutOfFuturePresentationInfos)
 
 TEST_F (FlatlandConnectionTest, PresentCreditExhaustion)
 
 TEST_F (PlatformViewTests, InvalidPlatformMessageRequest)
 
 TEST_F (PlatformViewTests, CreateSurfaceTest)
 
 TEST_F (PlatformViewTests, SetViewportMetrics)
 
 TEST_F (PlatformViewTests, ChangesAccessibilitySettings)
 
 TEST_F (PlatformViewTests, EnableWireframeTest)
 
 TEST_F (PlatformViewTests, CreateViewTest)
 
 TEST_F (PlatformViewTests, UpdateViewTest)
 
 TEST_F (PlatformViewTests, DestroyViewTest)
 
 TEST_F (PlatformViewTests, GetFocusStatesTest)
 
 TEST_F (PlatformViewTests, RequestFocusTest)
 
 TEST_F (PlatformViewTests, RequestFocusNeverCreatedTest)
 
 TEST_F (PlatformViewTests, RequestFocusDisposedTest)
 
 TEST_F (PlatformViewTests, OnKeyEvent)
 
 TEST_F (PlatformViewTests, OnShaderWarmup)
 
 TEST_F (PlatformViewTests, TouchSourceLogicalToPhysicalConversion)
 
static std::string MessageToString (PlatformMessage &message)
 
 TEST_F (TextDelegateTest, ActivateIme)
 
 TEST_F (TextDelegateTest, OnAction)
 

Variables

constexpr std::array< std::array< float, 2 >, 2 > kRect = {{{0, 0}, {20, 20}}}
 
constexpr std::array< float, 9 > kIdentity = {1, 0, 0, 0, 1, 0, 0, 0, 1}
 
constexpr fup_TouchIxnId kIxnOne
 
constexpr uint32_t kMouseDeviceId = 123
 
constexpr std::array< int64_t, 2 > kNoScrollInPhysicalPixelDelta = {0, 0}
 
const bool kNotPrecisionScroll = false
 
const bool kPrecisionScroll = true
 
static constexpr fuchsia::ui::composition::TransformId kInvalidTransformId {0}
 
static constexpr fuchsia::ui::composition::ContentId kInvalidContentId {0}
 
static constexpr fuchsia::ui::composition::HitRegion kInfiniteHitRegion
 

Typedef Documentation

◆ FakeContent

Definition at line 223 of file fake_flatland_types.h.

◆ fup_DeviceType

using flutter_runner::testing::fup_DeviceType = typedef fuchsia::ui::pointerinjector::DeviceType

Definition at line 22 of file pointer_injector_delegate_unittest.cc.

◆ fup_DispatchPolicy

using flutter_runner::testing::fup_DispatchPolicy = typedef fuchsia::ui::pointerinjector::DispatchPolicy

Definition at line 23 of file pointer_injector_delegate_unittest.cc.

◆ fup_EventPhase

typedef fuchsia::ui::pointer::EventPhase flutter_runner::testing::fup_EventPhase

Definition at line 24 of file pointer_delegate_unittests.cc.

◆ fup_MouseDeviceInfo

using flutter_runner::testing::fup_MouseDeviceInfo = typedef fuchsia::ui::pointer::MouseDeviceInfo

Definition at line 17 of file pointer_event_utility.cc.

◆ fup_MouseEvent

typedef fuchsia::ui::pointer::MouseEvent flutter_runner::testing::fup_MouseEvent

Definition at line 33 of file pointer_delegate_unittests.cc.

◆ fup_MousePointerSample

using flutter_runner::testing::fup_MousePointerSample = typedef fuchsia::ui::pointer::MousePointerSample

Definition at line 16 of file pointer_event_utility.cc.

◆ fup_RegistryHandle

using flutter_runner::testing::fup_RegistryHandle = typedef fuchsia::ui::pointerinjector::RegistryHandle

Definition at line 25 of file pointer_injector_delegate_unittest.cc.

◆ fup_TouchEvent

typedef fuchsia::ui::pointer::TouchEvent flutter_runner::testing::fup_TouchEvent

Definition at line 25 of file pointer_delegate_unittests.cc.

◆ fup_TouchIxnId

typedef fuchsia::ui::pointer::TouchInteractionId flutter_runner::testing::fup_TouchIxnId

Definition at line 26 of file pointer_delegate_unittests.cc.

◆ fup_TouchIxnResult

typedef fuchsia::ui::pointer::TouchInteractionResult flutter_runner::testing::fup_TouchIxnResult

Definition at line 27 of file pointer_delegate_unittests.cc.

◆ fup_TouchIxnStatus

using flutter_runner::testing::fup_TouchIxnStatus = typedef fuchsia::ui::pointer::TouchInteractionStatus

Definition at line 28 of file pointer_delegate_unittests.cc.

◆ fup_TouchPointerSample

typedef fuchsia::ui::pointer::TouchPointerSample flutter_runner::testing::fup_TouchPointerSample

Definition at line 29 of file pointer_delegate_unittests.cc.

◆ fup_TouchResponse

using flutter_runner::testing::fup_TouchResponse = typedef fuchsia::ui::pointer::TouchResponse

Definition at line 30 of file pointer_delegate_unittests.cc.

◆ fup_TouchResponseType

using flutter_runner::testing::fup_TouchResponseType = typedef fuchsia::ui::pointer::TouchResponseType

Definition at line 31 of file pointer_delegate_unittests.cc.

◆ fup_ViewParameters

typedef fuchsia::ui::pointer::ViewParameters flutter_runner::testing::fup_ViewParameters

Definition at line 32 of file pointer_delegate_unittests.cc.

◆ fuv_ViewRef

using flutter_runner::testing::fuv_ViewRef = typedef fuchsia::ui::views::ViewRef

Definition at line 26 of file pointer_injector_delegate_unittest.cc.

Function Documentation

◆ GetKoids() [1/11]

template<typename F >
std::pair< zx_koid_t, zx_koid_t > flutter_runner::testing::GetKoids ( const fidl::Binding< F > &  interface_binding)

Definition at line 294 of file fake_flatland_types.h.

295 {
296 return GetKoids(interface_binding.channel());
297}
std::pair< zx_koid_t, zx_koid_t > GetKoids(const ZX &kobj)

◆ GetKoids() [2/11]

template<typename F >
std::pair< zx_koid_t, zx_koid_t > flutter_runner::testing::GetKoids ( const fidl::InterfaceHandle< F > &  interface_handle)

Definition at line 276 of file fake_flatland_types.h.

277 {
278 return GetKoids(interface_handle.channel());
279}

◆ GetKoids() [3/11]

template<typename F >
std::pair< zx_koid_t, zx_koid_t > flutter_runner::testing::GetKoids ( const fidl::InterfacePtr< F > &  interface_ptr)

Definition at line 288 of file fake_flatland_types.h.

289 {
290 return GetKoids(interface_ptr.channel());
291}

◆ GetKoids() [4/11]

template<typename F >
std::pair< zx_koid_t, zx_koid_t > flutter_runner::testing::GetKoids ( const fidl::InterfaceRequest< F > &  interface_request)

Definition at line 282 of file fake_flatland_types.h.

283 {
284 return GetKoids(interface_request.channel());
285}

◆ GetKoids() [5/11]

std::pair< zx_koid_t, zx_koid_t > flutter_runner::testing::GetKoids ( const fuchsia::ui::composition::BufferCollectionExportToken &  buffer_collection_token)
inline

Definition at line 319 of file fake_flatland_types.h.

321 {
322 return GetKoids(buffer_collection_token.value);
323}

◆ GetKoids() [6/11]

std::pair< zx_koid_t, zx_koid_t > flutter_runner::testing::GetKoids ( const fuchsia::ui::composition::BufferCollectionImportToken &  buffer_collection_token)
inline

Definition at line 325 of file fake_flatland_types.h.

327 {
328 return GetKoids(buffer_collection_token.value);
329}

◆ GetKoids() [7/11]

std::pair< zx_koid_t, zx_koid_t > flutter_runner::testing::GetKoids ( const fuchsia::ui::views::ViewCreationToken &  view_token)
inline

Definition at line 299 of file fake_flatland_types.h.

300 {
301 return GetKoids(view_token.value);
302}

◆ GetKoids() [8/11]

std::pair< zx_koid_t, zx_koid_t > flutter_runner::testing::GetKoids ( const fuchsia::ui::views::ViewportCreationToken &  viewport_token)
inline

Definition at line 304 of file fake_flatland_types.h.

305 {
306 return GetKoids(viewport_token.value);
307}

◆ GetKoids() [9/11]

std::pair< zx_koid_t, zx_koid_t > flutter_runner::testing::GetKoids ( const fuchsia::ui::views::ViewRef &  view_ref)
inline

Definition at line 309 of file fake_flatland_types.h.

310 {
311 return GetKoids(view_ref.reference);
312}

◆ GetKoids() [10/11]

std::pair< zx_koid_t, zx_koid_t > flutter_runner::testing::GetKoids ( const fuchsia::ui::views::ViewRefControl &  view_ref_control)
inline

Definition at line 314 of file fake_flatland_types.h.

315 {
316 return GetKoids(view_ref_control.reference);
317}

◆ GetKoids() [11/11]

template<typename ZX >
std::pair< zx_koid_t, zx_koid_t > flutter_runner::testing::GetKoids ( const ZX &  kobj)

Definition at line 266 of file fake_flatland_types.h.

266 {
267 zx_info_handle_basic_t info;
268 zx_status_t status =
269 kobj.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info),
270 /*actual_records*/ nullptr, /*avail_records*/ nullptr);
271 return status == ZX_OK ? std::make_pair(info.koid, info.related_koid)
272 : std::make_pair(zx_koid_t{}, zx_koid_t{});
273}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
Definition ref_ptr.h:256

◆ INSTANTIATE_TEST_SUITE_P()

flutter_runner::testing::INSTANTIATE_TEST_SUITE_P ( PointerInjectorDelegateParameterizedTest  ,
PointerInjectorDelegateTest  ,
::testing::Bool()   
)

◆ MessageToString()

static std::string flutter_runner::testing::MessageToString ( PlatformMessage message)
static

Definition at line 26 of file text_delegate_unittests.cc.

26 {
27 const char* data = reinterpret_cast<const char*>(message.data().GetMapping());
28 return std::string(data, message.data().GetSize());
29}
Win32Message message

◆ TEST()

flutter_runner::testing::TEST ( EngineTest  ,
ThreadNames   
)

Definition at line 23 of file engine_unittests.cc.

23 {
24 std::string prefix = GetCurrentTestName();
25 flutter::ThreadHost engine_thread_host = Engine::CreateThreadHost(prefix);
26
27 char thread_name[ZX_MAX_NAME_LEN];
28 zx::thread::self()->get_property(ZX_PROP_NAME, thread_name,
29 sizeof(thread_name));
30 EXPECT_EQ(std::string(thread_name), prefix + std::string(".platform"));
31 EXPECT_EQ(engine_thread_host.platform_thread, nullptr);
32
33 engine_thread_host.raster_thread->GetTaskRunner()->PostTask([&prefix]() {
34 char thread_name[ZX_MAX_NAME_LEN];
35 zx::thread::self()->get_property(ZX_PROP_NAME, thread_name,
36 sizeof(thread_name));
37 EXPECT_EQ(std::string(thread_name), prefix + std::string(".raster"));
38 });
39 engine_thread_host.raster_thread->Join();
40
41 engine_thread_host.ui_thread->GetTaskRunner()->PostTask([&prefix]() {
42 char thread_name[ZX_MAX_NAME_LEN];
43 zx::thread::self()->get_property(ZX_PROP_NAME, thread_name,
44 sizeof(thread_name));
45 EXPECT_EQ(std::string(thread_name), prefix + std::string(".ui"));
46 });
47 engine_thread_host.ui_thread->Join();
48
49 engine_thread_host.io_thread->GetTaskRunner()->PostTask([&prefix]() {
50 char thread_name[ZX_MAX_NAME_LEN];
51 zx::thread::self()->get_property(ZX_PROP_NAME, thread_name,
52 sizeof(thread_name));
53 EXPECT_EQ(std::string(thread_name), prefix + std::string(".io"));
54 });
55 engine_thread_host.io_thread->Join();
56}
The collection of all the threads used by the engine.
Definition thread_host.h:21
std::unique_ptr< fml::Thread > io_thread
Definition thread_host.h:86
std::unique_ptr< fml::Thread > platform_thread
Definition thread_host.h:83
std::unique_ptr< fml::Thread > raster_thread
Definition thread_host.h:85
std::unique_ptr< fml::Thread > ui_thread
Definition thread_host.h:84

◆ TEST_F() [1/54]

flutter_runner::testing::TEST_F ( ExternalViewEmbedderTest  ,
RootScene   
)

Definition at line 439 of file external_view_embedder_unittests.cc.

439 {
440 fuchsia::ui::composition::ParentViewportWatcherPtr parent_viewport_watcher;
441 fuchsia::ui::views::ViewportCreationToken viewport_creation_token;
442 fuchsia::ui::views::ViewCreationToken view_creation_token;
443 fuchsia::ui::views::ViewRef view_ref_clone;
444 auto view_creation_token_status = zx::channel::create(
445 0u, &viewport_creation_token.value, &view_creation_token.value);
446 ASSERT_EQ(view_creation_token_status, ZX_OK);
447
448 fuchsia::ui::views::ViewRefControl view_ref_control;
449 fuchsia::ui::views::ViewRef view_ref;
450 auto status = zx::eventpair::create(
451 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
452 ASSERT_EQ(status, ZX_OK);
453 view_ref_control.reference.replace(
454 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
455 &view_ref_control.reference);
456 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
457 view_ref.Clone(&view_ref_clone);
458
459 ExternalViewEmbedder external_view_embedder(
460 std::move(view_creation_token),
461 fuchsia::ui::views::ViewIdentityOnCreation{
462 .view_ref = std::move(view_ref),
463 .view_ref_control = std::move(view_ref_control),
464 },
465 fuchsia::ui::composition::ViewBoundProtocols{},
466 parent_viewport_watcher.NewRequest(), flatland_connection(),
467 fake_surface_producer());
468 EXPECT_THAT(fake_flatland().graph(), IsEmptyGraph());
469
470 // Pump the loop; the graph should still be empty because nothing called
471 // `Present` yet.
472 loop().RunUntilIdle();
473 EXPECT_THAT(fake_flatland().graph(), IsEmptyGraph());
474
475 // Pump the loop; the contents of the initial `Present` should be processed.
476 flatland_connection()->Present();
477 loop().RunUntilIdle();
478 EXPECT_THAT(fake_flatland().graph(),
479 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
480 view_ref_clone));
481}

◆ TEST_F() [2/54]

flutter_runner::testing::TEST_F ( ExternalViewEmbedderTest  ,
SceneWithOneClippedView   
)

Definition at line 801 of file external_view_embedder_unittests.cc.

801 {
802 fuchsia::ui::composition::ParentViewportWatcherPtr parent_viewport_watcher;
803 fuchsia::ui::views::ViewportCreationToken viewport_creation_token;
804 fuchsia::ui::views::ViewCreationToken view_creation_token;
805 fuchsia::ui::views::ViewRef view_ref_clone;
806 auto view_creation_token_status = zx::channel::create(
807 0u, &viewport_creation_token.value, &view_creation_token.value);
808 ASSERT_EQ(view_creation_token_status, ZX_OK);
809
810 fuchsia::ui::views::ViewRefControl view_ref_control;
811 fuchsia::ui::views::ViewRef view_ref;
812 auto status = zx::eventpair::create(
813 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
814 ASSERT_EQ(status, ZX_OK);
815 view_ref_control.reference.replace(
816 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
817 &view_ref_control.reference);
818 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
819 view_ref.Clone(&view_ref_clone);
820
821 // Create the `ExternalViewEmbedder` and pump the message loop until
822 // the initial scene graph is setup.
823 ExternalViewEmbedder external_view_embedder(
824 std::move(view_creation_token),
825 fuchsia::ui::views::ViewIdentityOnCreation{
826 .view_ref = std::move(view_ref),
827 .view_ref_control = std::move(view_ref_control),
828 },
829 fuchsia::ui::composition::ViewBoundProtocols{},
830 parent_viewport_watcher.NewRequest(), flatland_connection(),
831 fake_surface_producer());
832 flatland_connection()->Present();
833 loop().RunUntilIdle();
834 fake_flatland().FireOnNextFrameBeginEvent(WithPresentCredits(1u));
835 loop().RunUntilIdle();
836 EXPECT_THAT(fake_flatland().graph(),
837 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
838 view_ref_clone));
839
840 // Create the view before drawing the scene.
841 const SkSize child_view_size_signed = SkSize::Make(256.f, 512.f);
842 const fuchsia::math::SizeU child_view_size{
843 static_cast<uint32_t>(child_view_size_signed.width()),
844 static_cast<uint32_t>(child_view_size_signed.height())};
845 auto [child_view_token, child_viewport_token] = ViewTokenPair::New();
846 const uint32_t child_view_id = child_viewport_token.value.get();
847
848 const int kOpacity = 200;
849 const float kOpacityFloat = 200 / 255.0f;
850 const fuchsia::math::VecF kScale{3.0f, 4.0f};
851 const int kTranslateX = 10;
852 const int kTranslateY = 20;
853
854 auto matrix = SkMatrix::I();
855 matrix.setScaleX(kScale.x);
856 matrix.setScaleY(kScale.y);
857 matrix.setTranslateX(kTranslateX);
858 matrix.setTranslateY(kTranslateY);
859
861 SkRect::MakeXYWH(30, 40, child_view_size_signed.width() - 50,
862 child_view_size_signed.height() - 60);
863 fuchsia::math::Rect kClipInMathRect = {
864 static_cast<int32_t>(kClipRect.x()), static_cast<int32_t>(kClipRect.y()),
865 static_cast<int32_t>(kClipRect.width()),
866 static_cast<int32_t>(kClipRect.height())};
867
868 auto mutators_stack = flutter::MutatorsStack();
869 mutators_stack.PushOpacity(kOpacity);
870 mutators_stack.PushTransform(matrix);
871 mutators_stack.PushClipRect(kClipRect);
872
873 flutter::EmbeddedViewParams child_view_params(matrix, child_view_size_signed,
874 mutators_stack);
875 external_view_embedder.CreateView(
876 child_view_id, []() {},
877 [](fuchsia::ui::composition::ContentId,
878 fuchsia::ui::composition::ChildViewWatcherHandle) {});
879 const SkRect child_view_occlusion_hint = SkRect::MakeLTRB(1, 2, 3, 4);
880 const fuchsia::math::Inset child_view_inset{
881 static_cast<int32_t>(child_view_occlusion_hint.top()),
882 static_cast<int32_t>(child_view_occlusion_hint.right()),
883 static_cast<int32_t>(child_view_occlusion_hint.bottom()),
884 static_cast<int32_t>(child_view_occlusion_hint.left())};
885 external_view_embedder.SetViewProperties(
886 child_view_id, child_view_occlusion_hint, /*hit_testable=*/false,
887 /*focusable=*/false);
888
889 // We must take into account the effect of DPR on the view scale.
890 const float kDPR = 2.0f;
891 const float kInvDPR = 1.f / kDPR;
892
893 // Draw the scene. The scene graph shouldn't change yet.
894 const SkISize frame_size_signed = SkISize::Make(512, 512);
895 const fuchsia::math::SizeU frame_size{
896 static_cast<uint32_t>(frame_size_signed.width()),
897 static_cast<uint32_t>(frame_size_signed.height())};
898 DrawFrameWithView(
899 external_view_embedder, frame_size_signed, kDPR, child_view_id,
900 child_view_params,
901 [](flutter::DlCanvas* canvas) {
902 const SkISize layer_size = canvas->GetBaseLayerSize();
903 const SkSize canvas_size =
904 SkSize::Make(layer_size.width(), layer_size.height());
905 flutter::DlPaint rect_paint;
907 canvas->Translate(canvas_size.width() / 4.f,
908 canvas_size.height() / 2.f);
909 canvas->DrawRect(SkRect::MakeWH(canvas_size.width() / 32.f,
910 canvas_size.height() / 32.f),
911 rect_paint);
912 },
913 [](flutter::DlCanvas* canvas) {
914 const SkISize layer_size = canvas->GetBaseLayerSize();
915 const SkSize canvas_size =
916 SkSize::Make(layer_size.width(), layer_size.height());
917 flutter::DlPaint rect_paint;
918 rect_paint.setColor(flutter::DlColor::kRed());
919 canvas->Translate(canvas_size.width() * 3.f / 4.f,
920 canvas_size.height() / 2.f);
921 canvas->DrawRect(SkRect::MakeWH(canvas_size.width() / 32.f,
922 canvas_size.height() / 32.f),
923 rect_paint);
924 });
925 EXPECT_THAT(fake_flatland().graph(),
926 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
927 view_ref_clone));
928
929 // Pump the message loop. The scene updates should propagate to flatland.
930 loop().RunUntilIdle();
931 fake_flatland().FireOnNextFrameBeginEvent(WithPresentCredits(1u));
932 loop().RunUntilIdle();
933
934 EXPECT_THAT(
935 fake_flatland().graph(),
936 IsFlutterGraph(
937 parent_viewport_watcher, viewport_creation_token,
938 view_ref_clone, /*layers*/
939 {IsImageLayer(
940 frame_size, kFirstLayerBlendMode,
941 {IsHitRegion(
942 /* x */ 128.f,
943 /* y */ 256.f,
944 /* width */ 16.f,
945 /* height */ 16.f,
946 /* hit_test */
947 fuchsia::ui::composition::HitTestInteraction::DEFAULT)}),
948 IsClipTransformLayer(
949 {kTranslateX, kTranslateY}, kScale, kClipInMathRect,
950 IsViewportLayer(child_view_token, child_view_size,
951 child_view_inset, {0, 0},
952 FakeTransform::kDefaultScale, kOpacityFloat)),
953 IsImageLayer(
954 frame_size, kUpperLayerBlendMode,
955 {IsHitRegion(
956 /* x */ 384.f,
957 /* y */ 256.f,
958 /* width */ 16.f,
959 /* height */ 16.f,
960 /* hit_test */
961 fuchsia::ui::composition::HitTestInteraction::DEFAULT)})},
962 {kInvDPR, kInvDPR}));
963
964 // Draw another frame with view, but get rid of the clips this time. This
965 // should remove all ClipTransformLayer instances.
966 auto new_matrix = SkMatrix::I();
967 new_matrix.setScaleX(kScale.x);
968 new_matrix.setScaleY(kScale.y);
969 auto new_mutators_stack = flutter::MutatorsStack();
970 new_mutators_stack.PushOpacity(kOpacity);
971 new_mutators_stack.PushTransform(new_matrix);
972 flutter::EmbeddedViewParams new_child_view_params(
973 new_matrix, child_view_size_signed, new_mutators_stack);
974 DrawFrameWithView(
975 external_view_embedder, frame_size_signed, kDPR, child_view_id,
976 new_child_view_params,
977 [](flutter::DlCanvas* canvas) {
978 const SkISize layer_size = canvas->GetBaseLayerSize();
979 const SkSize canvas_size =
980 SkSize::Make(layer_size.width(), layer_size.height());
981 flutter::DlPaint rect_paint;
983 canvas->Translate(canvas_size.width() / 4.f,
984 canvas_size.height() / 2.f);
985 canvas->DrawRect(SkRect::MakeWH(canvas_size.width() / 32.f,
986 canvas_size.height() / 32.f),
987 rect_paint);
988 },
989 [](flutter::DlCanvas* canvas) {
990 const SkISize layer_size = canvas->GetBaseLayerSize();
991 const SkSize canvas_size =
992 SkSize::Make(layer_size.width(), layer_size.height());
993 flutter::DlPaint rect_paint;
994 rect_paint.setColor(flutter::DlColor::kRed());
995 canvas->Translate(canvas_size.width() * 3.f / 4.f,
996 canvas_size.height() / 2.f);
997 canvas->DrawRect(SkRect::MakeWH(canvas_size.width() / 32.f,
998 canvas_size.height() / 32.f),
999 rect_paint);
1000 });
1001 loop().RunUntilIdle();
1002 fake_flatland().FireOnNextFrameBeginEvent(WithPresentCredits(1u));
1003 loop().RunUntilIdle();
1004 EXPECT_THAT(
1005 fake_flatland().graph(),
1006 IsFlutterGraph(
1007 parent_viewport_watcher, viewport_creation_token,
1008 view_ref_clone, /*layers*/
1009 {IsImageLayer(
1010 frame_size, kFirstLayerBlendMode,
1011 {IsHitRegion(
1012 /* x */ 128.f,
1013 /* y */ 256.f,
1014 /* width */ 16.f,
1015 /* height */ 16.f,
1016 /* hit_test */
1017 fuchsia::ui::composition::HitTestInteraction::DEFAULT)}),
1018 IsViewportLayer(child_view_token, child_view_size, child_view_inset,
1019 {0, 0}, kScale, kOpacityFloat),
1020 IsImageLayer(
1021 frame_size, kUpperLayerBlendMode,
1022 {IsHitRegion(
1023 /* x */ 384.f,
1024 /* y */ 256.f,
1025 /* width */ 16.f,
1026 /* height */ 16.f,
1027 /* hit_test */
1028 fuchsia::ui::composition::HitTestInteraction::DEFAULT)})},
1029 {kInvDPR, kInvDPR}));
1030
1031 // Destroy the view and draw another frame without the view.
1032 external_view_embedder.DestroyView(
1033 child_view_id, [](fuchsia::ui::composition::ContentId) {});
1034 DrawSimpleFrame(external_view_embedder, frame_size_signed, 1.f,
1035 [](flutter::DlCanvas* canvas) {
1036 const SkISize layer_size = canvas->GetBaseLayerSize();
1037 const SkSize canvas_size =
1038 SkSize::Make(layer_size.width(), layer_size.height());
1039 flutter::DlPaint rect_paint;
1040 rect_paint.setColor(flutter::DlColor::kGreen());
1041 canvas->Translate(canvas_size.width() / 4.f,
1042 canvas_size.height() / 2.f);
1043 canvas->DrawRect(
1044 SkRect::MakeWH(canvas_size.width() / 32.f,
1045 canvas_size.height() / 32.f),
1046 rect_paint);
1047 });
1048 loop().RunUntilIdle();
1049 EXPECT_THAT(
1050 fake_flatland().graph(),
1051 IsFlutterGraph(
1052 parent_viewport_watcher, viewport_creation_token,
1053 view_ref_clone, /*layers*/
1054 {IsImageLayer(
1055 frame_size, kFirstLayerBlendMode,
1056 {IsHitRegion(
1057 /* x */ 128.f,
1058 /* y */ 256.f,
1059 /* width */ 16.f,
1060 /* height */ 16.f,
1061 /* hit_test */
1062 fuchsia::ui::composition::HitTestInteraction::DEFAULT)})}));
1063}
static const SkMatrix & I()
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:37
virtual void DrawRect(const SkRect &rect, const DlPaint &paint)=0
virtual SkISize GetBaseLayerSize() const =0
virtual void Translate(SkScalar tx, SkScalar ty)=0
DlPaint & setColor(DlColor color)
Definition dl_paint.h:71
unsigned useCenter Optional< SkMatrix > matrix
Definition SkRecords.h:258
static constexpr SkISize Make(int32_t w, int32_t h)
Definition SkSize.h:20
constexpr int32_t width() const
Definition SkSize.h:36
constexpr int32_t height() const
Definition SkSize.h:37
constexpr float left() const
Definition SkRect.h:734
constexpr float top() const
Definition SkRect.h:741
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition SkRect.h:659
constexpr float right() const
Definition SkRect.h:748
static constexpr SkRect MakeWH(float w, float h)
Definition SkRect.h:609
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition SkRect.h:646
constexpr float bottom() const
Definition SkRect.h:755
static constexpr SkSize Make(SkScalar w, SkScalar h)
Definition SkSize.h:56
SkScalar width() const
Definition SkSize.h:76
SkScalar height() const
Definition SkSize.h:77
static constexpr DlColor kRed()
Definition dl_color.h:24
static constexpr DlColor kGreen()
Definition dl_color.h:25
static constexpr int kScale

◆ TEST_F() [3/54]

flutter_runner::testing::TEST_F ( ExternalViewEmbedderTest  ,
SceneWithOneView   
)

Definition at line 564 of file external_view_embedder_unittests.cc.

564 {
565 fuchsia::ui::composition::ParentViewportWatcherPtr parent_viewport_watcher;
566 fuchsia::ui::views::ViewportCreationToken viewport_creation_token;
567 fuchsia::ui::views::ViewCreationToken view_creation_token;
568 fuchsia::ui::views::ViewRef view_ref_clone;
569 auto view_creation_token_status = zx::channel::create(
570 0u, &viewport_creation_token.value, &view_creation_token.value);
571 ASSERT_EQ(view_creation_token_status, ZX_OK);
572
573 fuchsia::ui::views::ViewRefControl view_ref_control;
574 fuchsia::ui::views::ViewRef view_ref;
575 auto status = zx::eventpair::create(
576 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
577 ASSERT_EQ(status, ZX_OK);
578 view_ref_control.reference.replace(
579 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
580 &view_ref_control.reference);
581 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
582 view_ref.Clone(&view_ref_clone);
583
584 // Create the `ExternalViewEmbedder` and pump the message loop until
585 // the initial scene graph is setup.
586 ExternalViewEmbedder external_view_embedder(
587 std::move(view_creation_token),
588 fuchsia::ui::views::ViewIdentityOnCreation{
589 .view_ref = std::move(view_ref),
590 .view_ref_control = std::move(view_ref_control),
591 },
592 fuchsia::ui::composition::ViewBoundProtocols{},
593 parent_viewport_watcher.NewRequest(), flatland_connection(),
594 fake_surface_producer());
595 flatland_connection()->Present();
596 loop().RunUntilIdle();
597 fake_flatland().FireOnNextFrameBeginEvent(WithPresentCredits(1u));
598 loop().RunUntilIdle();
599 EXPECT_THAT(fake_flatland().graph(),
600 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
601 view_ref_clone));
602
603 // Create the view before drawing the scene.
604 const SkSize child_view_size_signed = SkSize::Make(256.f, 512.f);
605 const fuchsia::math::SizeU child_view_size{
606 static_cast<uint32_t>(child_view_size_signed.width()),
607 static_cast<uint32_t>(child_view_size_signed.height())};
608 auto [child_view_token, child_viewport_token] = ViewTokenPair::New();
609 const uint32_t child_view_id = child_viewport_token.value.get();
610
611 const int kOpacity = 200;
612 const float kOpacityFloat = 200 / 255.0f;
613 const fuchsia::math::VecF kScale{3.0f, 4.0f};
614
615 auto matrix = SkMatrix::I();
616 matrix.setScaleX(kScale.x);
617 matrix.setScaleY(kScale.y);
618
619 auto mutators_stack = flutter::MutatorsStack();
620 mutators_stack.PushOpacity(kOpacity);
621 mutators_stack.PushTransform(matrix);
622
623 flutter::EmbeddedViewParams child_view_params(matrix, child_view_size_signed,
624 mutators_stack);
625 external_view_embedder.CreateView(
626 child_view_id, []() {},
627 [](fuchsia::ui::composition::ContentId,
628 fuchsia::ui::composition::ChildViewWatcherHandle) {});
629 const SkRect child_view_occlusion_hint = SkRect::MakeLTRB(1, 2, 3, 4);
630 const fuchsia::math::Inset child_view_inset{
631 static_cast<int32_t>(child_view_occlusion_hint.top()),
632 static_cast<int32_t>(child_view_occlusion_hint.right()),
633 static_cast<int32_t>(child_view_occlusion_hint.bottom()),
634 static_cast<int32_t>(child_view_occlusion_hint.left())};
635 external_view_embedder.SetViewProperties(
636 child_view_id, child_view_occlusion_hint, /*hit_testable=*/false,
637 /*focusable=*/false);
638
639 // We must take into account the effect of DPR on the view scale.
640 const float kDPR = 2.0f;
641 const float kInvDPR = 1.f / kDPR;
642
643 // Draw the scene. The scene graph shouldn't change yet.
644 const SkISize frame_size_signed = SkISize::Make(512, 512);
645 const fuchsia::math::SizeU frame_size{
646 static_cast<uint32_t>(frame_size_signed.width()),
647 static_cast<uint32_t>(frame_size_signed.height())};
648 DrawFrameWithView(
649 external_view_embedder, frame_size_signed, kDPR, child_view_id,
650 child_view_params,
651 [](flutter::DlCanvas* canvas) {
652 const SkISize layer_size = canvas->GetBaseLayerSize();
653 const SkSize canvas_size =
654 SkSize::Make(layer_size.width(), layer_size.height());
655 flutter::DlPaint rect_paint;
657 canvas->Translate(canvas_size.width() / 4.f,
658 canvas_size.height() / 2.f);
659 canvas->DrawRect(SkRect::MakeWH(canvas_size.width() / 32.f,
660 canvas_size.height() / 32.f),
661 rect_paint);
662 },
663 [](flutter::DlCanvas* canvas) {
664 const SkISize layer_size = canvas->GetBaseLayerSize();
665 const SkSize canvas_size =
666 SkSize::Make(layer_size.width(), layer_size.height());
667 flutter::DlPaint rect_paint;
668 rect_paint.setColor(flutter::DlColor::kRed());
669 canvas->Translate(canvas_size.width() * 3.f / 4.f,
670 canvas_size.height() / 2.f);
671 canvas->DrawRect(SkRect::MakeWH(canvas_size.width() / 32.f,
672 canvas_size.height() / 32.f),
673 rect_paint);
674 });
675 EXPECT_THAT(fake_flatland().graph(),
676 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
677 view_ref_clone));
678
679 // Pump the message loop. The scene updates should propagate to flatland.
680 loop().RunUntilIdle();
681 fake_flatland().FireOnNextFrameBeginEvent(WithPresentCredits(1u));
682 loop().RunUntilIdle();
683
684 EXPECT_THAT(
685 fake_flatland().graph(),
686 IsFlutterGraph(
687 parent_viewport_watcher, viewport_creation_token,
688 view_ref_clone, /*layers*/
689 {IsImageLayer(
690 frame_size, kFirstLayerBlendMode,
691 {IsHitRegion(
692 /* x */ 128.f,
693 /* y */ 256.f,
694 /* width */ 16.f,
695 /* height */ 16.f,
696 /* hit_test */
697 fuchsia::ui::composition::HitTestInteraction::DEFAULT)}),
698 IsViewportLayer(child_view_token, child_view_size, child_view_inset,
699 {0, 0}, kScale, kOpacityFloat),
700 IsImageLayer(
701 frame_size, kUpperLayerBlendMode,
702 {IsHitRegion(
703 /* x */ 384.f,
704 /* y */ 256.f,
705 /* width */ 16.f,
706 /* height */ 16.f,
707 /* hit_test */
708 fuchsia::ui::composition::HitTestInteraction::DEFAULT)})},
709 {kInvDPR, kInvDPR}));
710
711 // Destroy the view. The scene graph shouldn't change yet.
712 external_view_embedder.DestroyView(
713 child_view_id, [](fuchsia::ui::composition::ContentId) {});
714 EXPECT_THAT(
715 fake_flatland().graph(),
716 IsFlutterGraph(
717 parent_viewport_watcher, viewport_creation_token,
718 view_ref_clone, /*layers*/
719 {IsImageLayer(
720 frame_size, kFirstLayerBlendMode,
721 {IsHitRegion(
722 /* x */ 128.f,
723 /* y */ 256.f,
724 /* width */ 16.f,
725 /* height */ 16.f,
726 /* hit_test */
727 fuchsia::ui::composition::HitTestInteraction::DEFAULT)}),
728 IsViewportLayer(child_view_token, child_view_size, child_view_inset,
729 {0, 0}, kScale, kOpacityFloat),
730 IsImageLayer(
731 frame_size, kUpperLayerBlendMode,
732 {IsHitRegion(
733 /* x */ 384.f,
734 /* y */ 256.f,
735 /* width */ 16.f,
736 /* height */ 16.f,
737 /* hit_test */
738 fuchsia::ui::composition::HitTestInteraction::DEFAULT)})},
739 {kInvDPR, kInvDPR}));
740
741 // Draw another frame without the view. The scene graph shouldn't change yet.
742 DrawSimpleFrame(external_view_embedder, frame_size_signed, 1.f,
743 [](flutter::DlCanvas* canvas) {
744 const SkISize layer_size = canvas->GetBaseLayerSize();
745 const SkSize canvas_size =
746 SkSize::Make(layer_size.width(), layer_size.height());
747 flutter::DlPaint rect_paint;
749 canvas->Translate(canvas_size.width() / 4.f,
750 canvas_size.height() / 2.f);
751 canvas->DrawRect(
752 SkRect::MakeWH(canvas_size.width() / 32.f,
753 canvas_size.height() / 32.f),
754 rect_paint);
755 });
756 EXPECT_THAT(
757 fake_flatland().graph(),
758 IsFlutterGraph(
759 parent_viewport_watcher, viewport_creation_token,
760 view_ref_clone, /*layers*/
761 {IsImageLayer(
762 frame_size, kFirstLayerBlendMode,
763 {IsHitRegion(
764 /* x */ 128.f,
765 /* y */ 256.f,
766 /* width */ 16.f,
767 /* height */ 16.f,
768 /* hit_test */
769 fuchsia::ui::composition::HitTestInteraction::DEFAULT)}),
770 IsViewportLayer(child_view_token, child_view_size, child_view_inset,
771 {0, 0}, kScale, kOpacityFloat),
772 IsImageLayer(
773 frame_size, kUpperLayerBlendMode,
774 {IsHitRegion(
775 /* x */ 384.f,
776 /* y */ 256.f,
777 /* width */ 16.f,
778 /* height */ 16.f,
779 /* hit_test */
780 fuchsia::ui::composition::HitTestInteraction::DEFAULT)})},
781 {kInvDPR, kInvDPR}));
782
783 // Pump the message loop. The scene updates should propagate to flatland.
784 loop().RunUntilIdle();
785 EXPECT_THAT(
786 fake_flatland().graph(),
787 IsFlutterGraph(
788 parent_viewport_watcher, viewport_creation_token,
789 view_ref_clone, /*layers*/
790 {IsImageLayer(
791 frame_size, kFirstLayerBlendMode,
792 {IsHitRegion(
793 /* x */ 128.f,
794 /* y */ 256.f,
795 /* width */ 16.f,
796 /* height */ 16.f,
797 /* hit_test */
798 fuchsia::ui::composition::HitTestInteraction::DEFAULT)})}));
799}

◆ TEST_F() [4/54]

flutter_runner::testing::TEST_F ( ExternalViewEmbedderTest  ,
SceneWithOneView_DestroyBeforeDrawing   
)

Definition at line 1251 of file external_view_embedder_unittests.cc.

1251 {
1252 fuchsia::ui::composition::ParentViewportWatcherPtr parent_viewport_watcher;
1253 fuchsia::ui::views::ViewportCreationToken viewport_creation_token;
1254 fuchsia::ui::views::ViewCreationToken view_creation_token;
1255 fuchsia::ui::views::ViewRef view_ref_clone;
1256 auto view_creation_token_status = zx::channel::create(
1257 0u, &viewport_creation_token.value, &view_creation_token.value);
1258 ASSERT_EQ(view_creation_token_status, ZX_OK);
1259
1260 fuchsia::ui::views::ViewRefControl view_ref_control;
1261 fuchsia::ui::views::ViewRef view_ref;
1262 auto status = zx::eventpair::create(
1263 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
1264 ASSERT_EQ(status, ZX_OK);
1265 view_ref_control.reference.replace(
1266 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
1267 &view_ref_control.reference);
1268 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
1269 view_ref.Clone(&view_ref_clone);
1270
1271 // Create the `ExternalViewEmbedder` and pump the message loop until
1272 // the initial scene graph is setup.
1273 ExternalViewEmbedder external_view_embedder(
1274 std::move(view_creation_token),
1275 fuchsia::ui::views::ViewIdentityOnCreation{
1276 .view_ref = std::move(view_ref),
1277 .view_ref_control = std::move(view_ref_control),
1278 },
1279 fuchsia::ui::composition::ViewBoundProtocols{},
1280 parent_viewport_watcher.NewRequest(), flatland_connection(),
1281 fake_surface_producer());
1282 flatland_connection()->Present();
1283 loop().RunUntilIdle();
1284 fake_flatland().FireOnNextFrameBeginEvent(WithPresentCredits(1u));
1285 loop().RunUntilIdle();
1286 EXPECT_THAT(fake_flatland().graph(),
1287 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
1288 view_ref_clone));
1289
1290 // Create the view before drawing the scene.
1291 auto [child_view_token, child_viewport_token] = ViewTokenPair::New();
1292 const uint32_t child_view_id = child_viewport_token.value.get();
1293 external_view_embedder.CreateView(
1294 child_view_id, []() {},
1295 [](fuchsia::ui::composition::ContentId,
1296 fuchsia::ui::composition::ChildViewWatcherHandle) {});
1297
1298 // Draw the scene without the view. The scene graph shouldn't change yet.
1299 const SkISize frame_size_signed = SkISize::Make(512, 512);
1300 const fuchsia::math::SizeU frame_size{
1301 static_cast<uint32_t>(frame_size_signed.width()),
1302 static_cast<uint32_t>(frame_size_signed.height())};
1303 DrawSimpleFrame(external_view_embedder, frame_size_signed, 1.f,
1304 [](flutter::DlCanvas* canvas) {
1305 const SkISize layer_size = canvas->GetBaseLayerSize();
1306 const SkSize canvas_size =
1307 SkSize::Make(layer_size.width(), layer_size.height());
1308 flutter::DlPaint rect_paint;
1309 rect_paint.setColor(flutter::DlColor().kGreen());
1310 canvas->Translate(canvas_size.width() / 4.f,
1311 canvas_size.height() / 2.f);
1312 canvas->DrawRect(
1313 SkRect::MakeWH(canvas_size.width() / 32.f,
1314 canvas_size.height() / 32.f),
1315 rect_paint);
1316 });
1317
1318 // Pump the message loop. The scene updates should propagate to flatland.
1319 loop().RunUntilIdle();
1320 fake_flatland().FireOnNextFrameBeginEvent(WithPresentCredits(1u));
1321 loop().RunUntilIdle();
1322 EXPECT_THAT(
1323 fake_flatland().graph(),
1324 IsFlutterGraph(
1325 parent_viewport_watcher, viewport_creation_token, view_ref_clone,
1326 /*layers*/
1327 {IsImageLayer(
1328 frame_size, kFirstLayerBlendMode,
1329 {IsHitRegion(
1330 /* x */ 128.f,
1331 /* y */ 256.f,
1332 /* width */ 16.f,
1333 /* height */ 16.f,
1334 /* hit_test */
1335 fuchsia::ui::composition::HitTestInteraction::DEFAULT)})}));
1336
1337 // Destroy the view. The scene graph shouldn't change yet.
1338 external_view_embedder.DestroyView(
1339 child_view_id, [](fuchsia::ui::composition::ContentId) {});
1340 EXPECT_THAT(
1341 fake_flatland().graph(),
1342 IsFlutterGraph(
1343 parent_viewport_watcher, viewport_creation_token, view_ref_clone,
1344 /*layers*/
1345 {IsImageLayer(
1346 frame_size, kFirstLayerBlendMode,
1347 {IsHitRegion(
1348 /* x */ 128.f,
1349 /* y */ 256.f,
1350 /* width */ 16.f,
1351 /* height */ 16.f,
1352 /* hit_test */
1353 fuchsia::ui::composition::HitTestInteraction::DEFAULT)})}));
1354
1355 // Draw another frame without the view and change the size. The scene graph
1356 // shouldn't change yet.
1357 const SkISize new_frame_size_signed = SkISize::Make(256, 256);
1358 const fuchsia::math::SizeU new_frame_size{
1359 static_cast<uint32_t>(new_frame_size_signed.width()),
1360 static_cast<uint32_t>(new_frame_size_signed.height())};
1361 DrawSimpleFrame(external_view_embedder, new_frame_size_signed, 1.f,
1362 [](flutter::DlCanvas* canvas) {
1363 const SkISize layer_size = canvas->GetBaseLayerSize();
1364 const SkSize canvas_size =
1365 SkSize::Make(layer_size.width(), layer_size.height());
1366 flutter::DlPaint rect_paint;
1367 rect_paint.setColor(flutter::DlColor::kGreen());
1368 canvas->Translate(canvas_size.width() / 4.f,
1369 canvas_size.height() / 2.f);
1370 canvas->DrawRect(
1371 SkRect::MakeWH(canvas_size.width() / 32.f,
1372 canvas_size.height() / 32.f),
1373 rect_paint);
1374 });
1375 EXPECT_THAT(
1376 fake_flatland().graph(),
1377 IsFlutterGraph(
1378 parent_viewport_watcher, viewport_creation_token, view_ref_clone,
1379 /*layers*/
1380 {IsImageLayer(
1381 frame_size, kFirstLayerBlendMode,
1382 {IsHitRegion(
1383 /* x */ 128.f,
1384 /* y */ 256.f,
1385 /* width */ 16.f,
1386 /* height */ 16.f,
1387 /* hit_test */
1388 fuchsia::ui::composition::HitTestInteraction::DEFAULT)})}));
1389
1390 // Pump the message loop. The scene updates should propagate to flatland.
1391 loop().RunUntilIdle();
1392 EXPECT_THAT(
1393 fake_flatland().graph(),
1394 IsFlutterGraph(
1395 parent_viewport_watcher, viewport_creation_token,
1396 view_ref_clone, /*layers*/
1397 {IsImageLayer(
1398 new_frame_size, kFirstLayerBlendMode,
1399 {IsHitRegion(
1400 /* x */ 64.f,
1401 /* y */ 128.f,
1402 /* width */ 8.f,
1403 /* height */ 8.f,
1404 /* hit_test */
1405 fuchsia::ui::composition::HitTestInteraction::DEFAULT)})}));
1406}
static const uint64_t kGreen

◆ TEST_F() [5/54]

flutter_runner::testing::TEST_F ( ExternalViewEmbedderTest  ,
SceneWithOneView_NoOverlay   
)

Definition at line 1065 of file external_view_embedder_unittests.cc.

1065 {
1066 fuchsia::ui::composition::ParentViewportWatcherPtr parent_viewport_watcher;
1067 fuchsia::ui::views::ViewportCreationToken viewport_creation_token;
1068 fuchsia::ui::views::ViewCreationToken view_creation_token;
1069 fuchsia::ui::views::ViewRef view_ref_clone;
1070 auto view_creation_token_status = zx::channel::create(
1071 0u, &viewport_creation_token.value, &view_creation_token.value);
1072 ASSERT_EQ(view_creation_token_status, ZX_OK);
1073
1074 fuchsia::ui::views::ViewRefControl view_ref_control;
1075 fuchsia::ui::views::ViewRef view_ref;
1076 auto status = zx::eventpair::create(
1077 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
1078 ASSERT_EQ(status, ZX_OK);
1079 view_ref_control.reference.replace(
1080 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
1081 &view_ref_control.reference);
1082 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
1083 view_ref.Clone(&view_ref_clone);
1084
1085 // Create the `ExternalViewEmbedder` and pump the message loop until
1086 // the initial scene graph is setup.
1087 ExternalViewEmbedder external_view_embedder(
1088 std::move(view_creation_token),
1089 fuchsia::ui::views::ViewIdentityOnCreation{
1090 .view_ref = std::move(view_ref),
1091 .view_ref_control = std::move(view_ref_control),
1092 },
1093 fuchsia::ui::composition::ViewBoundProtocols{},
1094 parent_viewport_watcher.NewRequest(), flatland_connection(),
1095 fake_surface_producer());
1096 flatland_connection()->Present();
1097 loop().RunUntilIdle();
1098 fake_flatland().FireOnNextFrameBeginEvent(WithPresentCredits(1u));
1099 loop().RunUntilIdle();
1100 EXPECT_THAT(fake_flatland().graph(),
1101 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
1102 view_ref_clone));
1103
1104 // Create the view before drawing the scene.
1105 const SkSize child_view_size_signed = SkSize::Make(256.f, 512.f);
1106 const fuchsia::math::SizeU child_view_size{
1107 static_cast<uint32_t>(child_view_size_signed.width()),
1108 static_cast<uint32_t>(child_view_size_signed.height())};
1109 auto [child_view_token, child_viewport_token] = ViewTokenPair::New();
1110 const uint32_t child_view_id = child_viewport_token.value.get();
1111
1112 const int kOpacity = 125;
1113 const float kOpacityFloat = 125 / 255.0f;
1114 const fuchsia::math::VecF kScale{2.f, 3.0f};
1115
1116 auto matrix = SkMatrix::I();
1117 matrix.setScaleX(kScale.x);
1118 matrix.setScaleY(kScale.y);
1119
1120 auto mutators_stack = flutter::MutatorsStack();
1121 mutators_stack.PushOpacity(kOpacity);
1122 mutators_stack.PushTransform(matrix);
1123
1124 flutter::EmbeddedViewParams child_view_params(matrix, child_view_size_signed,
1125 mutators_stack);
1126 external_view_embedder.CreateView(
1127 child_view_id, []() {},
1128 [](fuchsia::ui::composition::ContentId,
1129 fuchsia::ui::composition::ChildViewWatcherHandle) {});
1130
1131 // Draw the scene. The scene graph shouldn't change yet.
1132 const SkISize frame_size_signed = SkISize::Make(512, 512);
1133 const fuchsia::math::SizeU frame_size{
1134 static_cast<uint32_t>(frame_size_signed.width()),
1135 static_cast<uint32_t>(frame_size_signed.height())};
1136 DrawFrameWithView(
1137 external_view_embedder, frame_size_signed, 1.f, child_view_id,
1138 child_view_params,
1139 [](flutter::DlCanvas* canvas) {
1140 const SkISize layer_size = canvas->GetBaseLayerSize();
1141 const SkSize canvas_size =
1142 SkSize::Make(layer_size.width(), layer_size.height());
1143 flutter::DlPaint rect_paint;
1144 rect_paint.setColor(flutter::DlColor::kGreen());
1145 canvas->Translate(canvas_size.width() / 4.f,
1146 canvas_size.height() / 2.f);
1147 canvas->DrawRect(SkRect::MakeWH(canvas_size.width() / 32.f,
1148 canvas_size.height() / 32.f),
1149 rect_paint);
1150 },
1151 [](flutter::DlCanvas* canvas) {});
1152 EXPECT_THAT(fake_flatland().graph(),
1153 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
1154 view_ref_clone));
1155
1156 // Pump the message loop. The scene updates should propagate to flatland.
1157 loop().RunUntilIdle();
1158 fake_flatland().FireOnNextFrameBeginEvent(WithPresentCredits(1u));
1159 loop().RunUntilIdle();
1160 EXPECT_THAT(
1161 fake_flatland().graph(),
1162 IsFlutterGraph(
1163 parent_viewport_watcher, viewport_creation_token,
1164 view_ref_clone, /*layers*/
1165 {IsImageLayer(
1166 frame_size, kFirstLayerBlendMode,
1167 {IsHitRegion(
1168 /* x */ 128.f,
1169 /* y */ 256.f,
1170 /* width */ 16.f,
1171 /* height */ 16.f,
1172 /* hit_test */
1173 fuchsia::ui::composition::HitTestInteraction::DEFAULT)}),
1174 IsViewportLayer(child_view_token, child_view_size,
1175 FakeViewport::kDefaultViewportInset, {0, 0}, kScale,
1176 kOpacityFloat)}));
1177
1178 // Destroy the view. The scene graph shouldn't change yet.
1179 external_view_embedder.DestroyView(
1180 child_view_id, [](fuchsia::ui::composition::ContentId) {});
1181 EXPECT_THAT(
1182 fake_flatland().graph(),
1183 IsFlutterGraph(
1184 parent_viewport_watcher, viewport_creation_token,
1185 view_ref_clone, /*layers*/
1186 {IsImageLayer(
1187 frame_size, kFirstLayerBlendMode,
1188 {IsHitRegion(
1189 /* x */ 128.f,
1190 /* y */ 256.f,
1191 /* width */ 16.f,
1192 /* height */ 16.f,
1193 /* hit_test */
1194 fuchsia::ui::composition::HitTestInteraction::DEFAULT)}),
1195 IsViewportLayer(child_view_token, child_view_size,
1196 FakeViewport::kDefaultViewportInset, {0, 0}, kScale,
1197 kOpacityFloat)}));
1198
1199 // Draw another frame without the view. The scene graph shouldn't change yet.
1200 DrawSimpleFrame(external_view_embedder, frame_size_signed, 1.f,
1201 [](flutter::DlCanvas* canvas) {
1202 const SkISize layer_size = canvas->GetBaseLayerSize();
1203 const SkSize canvas_size =
1204 SkSize::Make(layer_size.width(), layer_size.height());
1205 flutter::DlPaint rect_paint;
1206 rect_paint.setColor(flutter::DlColor::kGreen());
1207 canvas->Translate(canvas_size.width() / 4.f,
1208 canvas_size.height() / 2.f);
1209 canvas->DrawRect(
1210 SkRect::MakeWH(canvas_size.width() / 32.f,
1211 canvas_size.height() / 32.f),
1212 rect_paint);
1213 });
1214
1215 EXPECT_THAT(
1216 fake_flatland().graph(),
1217 IsFlutterGraph(
1218 parent_viewport_watcher, viewport_creation_token,
1219 view_ref_clone, /*layers*/
1220 {IsImageLayer(
1221 frame_size, kFirstLayerBlendMode,
1222 {IsHitRegion(
1223 /* x */ 128.f,
1224 /* y */ 256.f,
1225 /* width */ 16.f,
1226 /* height */ 16.f,
1227 /* hit_test */
1228 fuchsia::ui::composition::HitTestInteraction::DEFAULT)}),
1229 IsViewportLayer(child_view_token, child_view_size,
1230 FakeViewport::kDefaultViewportInset, {0, 0}, kScale,
1231 kOpacityFloat)}));
1232
1233 // Pump the message loop. The scene updates should propagate to flatland.
1234 loop().RunUntilIdle();
1235 EXPECT_THAT(
1236 fake_flatland().graph(),
1237 IsFlutterGraph(
1238 parent_viewport_watcher, viewport_creation_token,
1239 view_ref_clone, /*layers*/
1240 {IsImageLayer(
1241 frame_size, kFirstLayerBlendMode,
1242 {IsHitRegion(
1243 /* x */ 128.f,
1244 /* y */ 256.f,
1245 /* width */ 16.f,
1246 /* height */ 16.f,
1247 /* hit_test */
1248 fuchsia::ui::composition::HitTestInteraction::DEFAULT)})}));
1249}

◆ TEST_F() [6/54]

flutter_runner::testing::TEST_F ( ExternalViewEmbedderTest  ,
SimpleScene   
)

Definition at line 483 of file external_view_embedder_unittests.cc.

483 {
484 fuchsia::ui::composition::ParentViewportWatcherPtr parent_viewport_watcher;
485 fuchsia::ui::views::ViewportCreationToken viewport_creation_token;
486 fuchsia::ui::views::ViewCreationToken view_creation_token;
487 fuchsia::ui::views::ViewRef view_ref_clone;
488 auto view_creation_token_status = zx::channel::create(
489 0u, &viewport_creation_token.value, &view_creation_token.value);
490 ASSERT_EQ(view_creation_token_status, ZX_OK);
491
492 fuchsia::ui::views::ViewRefControl view_ref_control;
493 fuchsia::ui::views::ViewRef view_ref;
494 auto status = zx::eventpair::create(
495 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
496 ASSERT_EQ(status, ZX_OK);
497 view_ref_control.reference.replace(
498 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
499 &view_ref_control.reference);
500 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
501 view_ref.Clone(&view_ref_clone);
502
503 // Create the `ExternalViewEmbedder` and pump the message loop until
504 // the initial scene graph is setup.
505 ExternalViewEmbedder external_view_embedder(
506 std::move(view_creation_token),
507 fuchsia::ui::views::ViewIdentityOnCreation{
508 .view_ref = std::move(view_ref),
509 .view_ref_control = std::move(view_ref_control),
510 },
511 fuchsia::ui::composition::ViewBoundProtocols{},
512 parent_viewport_watcher.NewRequest(), flatland_connection(),
513 fake_surface_producer());
514 flatland_connection()->Present();
515 loop().RunUntilIdle();
516 fake_flatland().FireOnNextFrameBeginEvent(WithPresentCredits(1u));
517 loop().RunUntilIdle();
518 EXPECT_THAT(fake_flatland().graph(),
519 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
520 view_ref_clone));
521
522 // Draw the scene. The scene graph shouldn't change yet.
523 const SkISize frame_size_signed = SkISize::Make(512, 512);
524 const fuchsia::math::SizeU frame_size{
525 static_cast<uint32_t>(frame_size_signed.width()),
526 static_cast<uint32_t>(frame_size_signed.height())};
527 DrawSimpleFrame(external_view_embedder, frame_size_signed, 1.f,
528 [](flutter::DlCanvas* canvas) {
529 const SkISize layer_size = canvas->GetBaseLayerSize();
530 const SkSize canvas_size =
531 SkSize::Make(layer_size.width(), layer_size.height());
532 flutter::DlPaint rect_paint;
534 canvas->Translate(canvas_size.width() / 4.f,
535 canvas_size.height() / 2.f);
536 canvas->DrawRect(
537 SkRect::MakeWH(canvas_size.width() / 32.f,
538 canvas_size.height() / 32.f),
539 rect_paint);
540 });
541 EXPECT_THAT(fake_flatland().graph(),
542 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
543 view_ref_clone));
544
545 // Pump the message loop. The scene updates should propagate to flatland.
546 loop().RunUntilIdle();
547
548 EXPECT_THAT(
549 fake_flatland().graph(),
550 IsFlutterGraph(
551 parent_viewport_watcher, viewport_creation_token, view_ref_clone,
552 /*layers*/
553 {IsImageLayer(
554 frame_size, kFirstLayerBlendMode,
555 {IsHitRegion(
556 /* x */ 128.f,
557 /* y */ 256.f,
558 /* width */ 16.f,
559 /* height */ 16.f,
560 /* hit_test */
561 fuchsia::ui::composition::HitTestInteraction::DEFAULT)})}));
562}

◆ TEST_F() [7/54]

flutter_runner::testing::TEST_F ( ExternalViewEmbedderTest  ,
SimpleScene_DisjointHitRegions   
)

Definition at line 1411 of file external_view_embedder_unittests.cc.

1411 {
1412 fuchsia::ui::composition::ParentViewportWatcherPtr parent_viewport_watcher;
1413 fuchsia::ui::views::ViewportCreationToken viewport_creation_token;
1414 fuchsia::ui::views::ViewCreationToken view_creation_token;
1415 fuchsia::ui::views::ViewRef view_ref_clone;
1416 auto view_creation_token_status = zx::channel::create(
1417 0u, &viewport_creation_token.value, &view_creation_token.value);
1418 ASSERT_EQ(view_creation_token_status, ZX_OK);
1419
1420 fuchsia::ui::views::ViewRefControl view_ref_control;
1421 fuchsia::ui::views::ViewRef view_ref;
1422 auto status = zx::eventpair::create(
1423 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
1424 ASSERT_EQ(status, ZX_OK);
1425 view_ref_control.reference.replace(
1426 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
1427 &view_ref_control.reference);
1428 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
1429 view_ref.Clone(&view_ref_clone);
1430
1431 // Create the `ExternalViewEmbedder` and pump the message loop until
1432 // the initial scene graph is setup.
1433 ExternalViewEmbedder external_view_embedder(
1434 std::move(view_creation_token),
1435 fuchsia::ui::views::ViewIdentityOnCreation{
1436 .view_ref = std::move(view_ref),
1437 .view_ref_control = std::move(view_ref_control),
1438 },
1439 fuchsia::ui::composition::ViewBoundProtocols{},
1440 parent_viewport_watcher.NewRequest(), flatland_connection(),
1441 fake_surface_producer());
1442 flatland_connection()->Present();
1443 loop().RunUntilIdle();
1444 fake_flatland().FireOnNextFrameBeginEvent(WithPresentCredits(1u));
1445 loop().RunUntilIdle();
1446 EXPECT_THAT(fake_flatland().graph(),
1447 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
1448 view_ref_clone));
1449
1450 // Draw the scene. The scene graph shouldn't change yet.
1451 const SkISize frame_size_signed = SkISize::Make(512, 512);
1452 const fuchsia::math::SizeU frame_size{
1453 static_cast<uint32_t>(frame_size_signed.width()),
1454 static_cast<uint32_t>(frame_size_signed.height())};
1455 DrawSimpleFrame(
1456 external_view_embedder, frame_size_signed, 1.f,
1457 [](flutter::DlCanvas* canvas) {
1458 const SkISize layer_size = canvas->GetBaseLayerSize();
1459 const SkSize canvas_size =
1460 SkSize::Make(layer_size.width(), layer_size.height());
1461
1462 SkRect paint_region_1, paint_region_2;
1463
1464 paint_region_1 = SkRect::MakeXYWH(
1465 canvas_size.width() / 4.f, canvas_size.height() / 2.f,
1466 canvas_size.width() / 32.f, canvas_size.height() / 32.f);
1467
1468 flutter::DlPaint rect_paint;
1469 rect_paint.setColor(flutter::DlColor::kGreen());
1470 canvas->DrawRect(paint_region_1, rect_paint);
1471
1472 paint_region_2 = SkRect::MakeXYWH(
1473 canvas_size.width() * 3.f / 4.f, canvas_size.height() / 2.f,
1474 canvas_size.width() / 32.f, canvas_size.height() / 32.f);
1475
1476 rect_paint.setColor(flutter::DlColor::kRed());
1477 canvas->DrawRect(paint_region_2, rect_paint);
1478 });
1479 EXPECT_THAT(fake_flatland().graph(),
1480 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
1481 view_ref_clone));
1482
1483 // Pump the message loop. The scene updates should propagate to flatland.
1484 loop().RunUntilIdle();
1485
1486 EXPECT_THAT(
1487 fake_flatland().graph(),
1488 IsFlutterGraph(
1489 parent_viewport_watcher, viewport_creation_token, view_ref_clone,
1490 /*layers*/
1491 {IsImageLayer(
1492 frame_size, kFirstLayerBlendMode,
1493 {IsHitRegion(
1494 /* x */ 128.f,
1495 /* y */ 256.f,
1496 /* width */ 16.f,
1497 /* height */ 16.f,
1498 /* hit_test */
1499 fuchsia::ui::composition::HitTestInteraction::DEFAULT),
1500 IsHitRegion(
1501 /* x */ 384.f,
1502 /* y */ 256.f,
1503 /* width */ 16.f,
1504 /* height */ 16.f,
1505 /* hit_test */
1506 fuchsia::ui::composition::HitTestInteraction::DEFAULT)})}));
1507}

◆ TEST_F() [8/54]

flutter_runner::testing::TEST_F ( ExternalViewEmbedderTest  ,
SimpleScene_OverlappingHitRegions   
)

Definition at line 1513 of file external_view_embedder_unittests.cc.

1513 {
1514 fuchsia::ui::composition::ParentViewportWatcherPtr parent_viewport_watcher;
1515 fuchsia::ui::views::ViewportCreationToken viewport_creation_token;
1516 fuchsia::ui::views::ViewCreationToken view_creation_token;
1517 fuchsia::ui::views::ViewRef view_ref_clone;
1518 auto view_creation_token_status = zx::channel::create(
1519 0u, &viewport_creation_token.value, &view_creation_token.value);
1520 ASSERT_EQ(view_creation_token_status, ZX_OK);
1521
1522 fuchsia::ui::views::ViewRefControl view_ref_control;
1523 fuchsia::ui::views::ViewRef view_ref;
1524 auto status = zx::eventpair::create(
1525 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
1526 ASSERT_EQ(status, ZX_OK);
1527 view_ref_control.reference.replace(
1528 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
1529 &view_ref_control.reference);
1530 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
1531 view_ref.Clone(&view_ref_clone);
1532
1533 // Create the `ExternalViewEmbedder` and pump the message loop until
1534 // the initial scene graph is setup.
1535 ExternalViewEmbedder external_view_embedder(
1536 std::move(view_creation_token),
1537 fuchsia::ui::views::ViewIdentityOnCreation{
1538 .view_ref = std::move(view_ref),
1539 .view_ref_control = std::move(view_ref_control),
1540 },
1541 fuchsia::ui::composition::ViewBoundProtocols{},
1542 parent_viewport_watcher.NewRequest(), flatland_connection(),
1543 fake_surface_producer());
1544 flatland_connection()->Present();
1545 loop().RunUntilIdle();
1546 fake_flatland().FireOnNextFrameBeginEvent(WithPresentCredits(1u));
1547 loop().RunUntilIdle();
1548 EXPECT_THAT(fake_flatland().graph(),
1549 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
1550 view_ref_clone));
1551
1552 // Draw the scene. The scene graph shouldn't change yet.
1553 const SkISize frame_size_signed = SkISize::Make(512, 512);
1554 const fuchsia::math::SizeU frame_size{
1555 static_cast<uint32_t>(frame_size_signed.width()),
1556 static_cast<uint32_t>(frame_size_signed.height())};
1557 DrawSimpleFrame(
1558 external_view_embedder, frame_size_signed, 1.f,
1559 [](flutter::DlCanvas* canvas) {
1560 const SkISize layer_size = canvas->GetBaseLayerSize();
1561 const SkSize canvas_size =
1562 SkSize::Make(layer_size.width(), layer_size.height());
1563
1564 SkRect paint_region_1, paint_region_2;
1565
1566 paint_region_1 = SkRect::MakeXYWH(
1567 canvas_size.width() / 4.f, canvas_size.height() / 2.f,
1568 3.f * canvas_size.width() / 8.f, canvas_size.height() / 4.f);
1569
1570 flutter::DlPaint rect_paint;
1571 rect_paint.setColor(flutter::DlColor::kGreen());
1572 canvas->DrawRect(paint_region_1, rect_paint);
1573
1574 paint_region_2 = SkRect::MakeXYWH(
1575 canvas_size.width() * 3.f / 8.f, canvas_size.height() / 2.f,
1576 3.f * canvas_size.width() / 8.f, canvas_size.height() / 4.f);
1577
1578 rect_paint.setColor(flutter::DlColor::kRed());
1579 canvas->DrawRect(paint_region_2, rect_paint);
1580 });
1581 EXPECT_THAT(fake_flatland().graph(),
1582 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
1583 view_ref_clone));
1584
1585 // Pump the message loop. The scene updates should propagate to flatland.
1586 loop().RunUntilIdle();
1587
1588 EXPECT_THAT(
1589 fake_flatland().graph(),
1590 IsFlutterGraph(
1591 parent_viewport_watcher, viewport_creation_token, view_ref_clone,
1592 /*layers*/
1593 {IsImageLayer(
1594 frame_size, kFirstLayerBlendMode,
1595 {IsHitRegion(
1596 /* x */ 128.f,
1597 /* y */ 256.f,
1598 /* width */ 256.f,
1599 /* height */ 128.f,
1600 /* hit_test */
1601 fuchsia::ui::composition::HitTestInteraction::DEFAULT)})}));
1602}

◆ TEST_F() [9/54]

flutter_runner::testing::TEST_F ( ExternalViewEmbedderTest  ,
ViewportCoveredWithInputInterceptor   
)

Definition at line 1604 of file external_view_embedder_unittests.cc.

1604 {
1605 fuchsia::ui::composition::ParentViewportWatcherPtr parent_viewport_watcher;
1606 fuchsia::ui::views::ViewportCreationToken viewport_creation_token;
1607 fuchsia::ui::views::ViewCreationToken view_creation_token;
1608 fuchsia::ui::views::ViewRef view_ref_clone;
1609 auto view_creation_token_status = zx::channel::create(
1610 0u, &viewport_creation_token.value, &view_creation_token.value);
1611 ASSERT_EQ(view_creation_token_status, ZX_OK);
1612
1613 fuchsia::ui::views::ViewRefControl view_ref_control;
1614 fuchsia::ui::views::ViewRef view_ref;
1615 auto status = zx::eventpair::create(
1616 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
1617 ASSERT_EQ(status, ZX_OK);
1618 view_ref_control.reference.replace(
1619 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
1620 &view_ref_control.reference);
1621 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
1622 view_ref.Clone(&view_ref_clone);
1623
1624 // Create the `ExternalViewEmbedder` and pump the message loop until
1625 // the initial scene graph is setup.
1626 ExternalViewEmbedder external_view_embedder(
1627 std::move(view_creation_token),
1628 fuchsia::ui::views::ViewIdentityOnCreation{
1629 .view_ref = std::move(view_ref),
1630 .view_ref_control = std::move(view_ref_control),
1631 },
1632 fuchsia::ui::composition::ViewBoundProtocols{},
1633 parent_viewport_watcher.NewRequest(), flatland_connection(),
1634 fake_surface_producer(),
1635 /*intercept_all_input=*/true // Enables the interceptor.
1636 );
1637 flatland_connection()->Present();
1638 loop().RunUntilIdle();
1639 fake_flatland().FireOnNextFrameBeginEvent(WithPresentCredits(1u));
1640 loop().RunUntilIdle();
1641 EXPECT_THAT(fake_flatland().graph(),
1642 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
1643 view_ref_clone, {IsInputShield()}));
1644
1645 // Create the view before drawing the scene.
1646 const SkSize child_view_size_signed = SkSize::Make(256.f, 512.f);
1647 const fuchsia::math::SizeU child_view_size{
1648 static_cast<uint32_t>(child_view_size_signed.width()),
1649 static_cast<uint32_t>(child_view_size_signed.height())};
1650 auto [child_view_token, child_viewport_token] = ViewTokenPair::New();
1651 const uint32_t child_view_id = child_viewport_token.value.get();
1652
1653 const int kOpacity = 200;
1654 const float kOpacityFloat = 200 / 255.0f;
1655 const fuchsia::math::VecF kScale{3.0f, 4.0f};
1656
1657 auto matrix = SkMatrix::I();
1658 matrix.setScaleX(kScale.x);
1659 matrix.setScaleY(kScale.y);
1660
1661 auto mutators_stack = flutter::MutatorsStack();
1662 mutators_stack.PushOpacity(kOpacity);
1663 mutators_stack.PushTransform(matrix);
1664
1665 flutter::EmbeddedViewParams child_view_params(matrix, child_view_size_signed,
1666 mutators_stack);
1667 external_view_embedder.CreateView(
1668 child_view_id, []() {},
1669 [](fuchsia::ui::composition::ContentId,
1670 fuchsia::ui::composition::ChildViewWatcherHandle) {});
1671 const SkRect child_view_occlusion_hint = SkRect::MakeLTRB(1, 2, 3, 4);
1672 const fuchsia::math::Inset child_view_inset{
1673 static_cast<int32_t>(child_view_occlusion_hint.top()),
1674 static_cast<int32_t>(child_view_occlusion_hint.right()),
1675 static_cast<int32_t>(child_view_occlusion_hint.bottom()),
1676 static_cast<int32_t>(child_view_occlusion_hint.left())};
1677 external_view_embedder.SetViewProperties(
1678 child_view_id, child_view_occlusion_hint, /*hit_testable=*/false,
1679 /*focusable=*/false);
1680
1681 // We must take into account the effect of DPR on the view scale.
1682 const float kDPR = 2.0f;
1683 const float kInvDPR = 1.f / kDPR;
1684
1685 // Draw the scene. The scene graph shouldn't change yet.
1686 const SkISize frame_size_signed = SkISize::Make(512, 512);
1687 const fuchsia::math::SizeU frame_size{
1688 static_cast<uint32_t>(frame_size_signed.width()),
1689 static_cast<uint32_t>(frame_size_signed.height())};
1690 DrawFrameWithView(
1691 external_view_embedder, frame_size_signed, kDPR, child_view_id,
1692 child_view_params,
1693 [](flutter::DlCanvas* canvas) {
1694 const SkISize layer_size = canvas->GetBaseLayerSize();
1695 const SkSize canvas_size =
1696 SkSize::Make(layer_size.width(), layer_size.height());
1697 flutter::DlPaint rect_paint;
1698 rect_paint.setColor(flutter::DlColor::kGreen());
1699 canvas->Translate(canvas_size.width() / 4.f,
1700 canvas_size.height() / 2.f);
1701 canvas->DrawRect(SkRect::MakeWH(canvas_size.width() / 32.f,
1702 canvas_size.height() / 32.f),
1703 rect_paint);
1704 },
1705 [](flutter::DlCanvas* canvas) {
1706 const SkISize layer_size = canvas->GetBaseLayerSize();
1707 const SkSize canvas_size =
1708 SkSize::Make(layer_size.width(), layer_size.height());
1709 flutter::DlPaint rect_paint;
1710 rect_paint.setColor(flutter::DlColor::kRed());
1711 canvas->Translate(canvas_size.width() * 3.f / 4.f,
1712 canvas_size.height() / 2.f);
1713 canvas->DrawRect(SkRect::MakeWH(canvas_size.width() / 32.f,
1714 canvas_size.height() / 32.f),
1715 rect_paint);
1716 });
1717 EXPECT_THAT(fake_flatland().graph(),
1718 IsFlutterGraph(parent_viewport_watcher, viewport_creation_token,
1719 view_ref_clone, {IsInputShield()}));
1720
1721 // Pump the message loop. The scene updates should propagate to flatland.
1722 loop().RunUntilIdle();
1723 fake_flatland().FireOnNextFrameBeginEvent(WithPresentCredits(1u));
1724 loop().RunUntilIdle();
1725
1726 EXPECT_THAT(
1727 fake_flatland().graph(),
1728 IsFlutterGraph(
1729 parent_viewport_watcher, viewport_creation_token,
1730 view_ref_clone, /*layers*/
1731 {IsImageLayer(
1732 frame_size, kFirstLayerBlendMode,
1733 {IsHitRegion(
1734 /* x */ 128.f,
1735 /* y */ 256.f,
1736 /* width */ 16.f,
1737 /* height */ 16.f,
1738 /* hit_test */
1739 fuchsia::ui::composition::HitTestInteraction::DEFAULT)}),
1740 IsViewportLayer(child_view_token, child_view_size, child_view_inset,
1741 {0, 0}, kScale, kOpacityFloat),
1742 IsImageLayer(
1743 frame_size, kUpperLayerBlendMode,
1744 {IsHitRegion(
1745 /* x */ 384.f,
1746 /* y */ 256.f,
1747 /* width */ 16.f,
1748 /* height */ 16.f,
1749 /* hit_test */
1750 fuchsia::ui::composition::HitTestInteraction::DEFAULT)}),
1751 IsInputShield()},
1752 {kInvDPR, kInvDPR}));
1753}

◆ TEST_F() [10/54]

flutter_runner::testing::TEST_F ( FakeFlatlandTest  ,
DebugLabel   
)

Definition at line 62 of file fake_flatland_unittests.cc.

62 {
63 const std::string debug_label = GetCurrentTestName();
64 fuchsia::ui::composition::FlatlandPtr flatland = ConnectFlatland();
65
66 // Set the flatland's debug name. The `SetDebugName` hasn't been processed
67 // yet, so the flatland's view of the debug name is still empty.
68 flatland->SetDebugName(debug_label);
69 EXPECT_EQ(fake_flatland().debug_name(), "");
70
71 // Pump the loop; the contents of the initial `SetDebugName` should be
72 // processed.
73 loop().RunUntilIdle();
74 EXPECT_EQ(fake_flatland().debug_name(), debug_label);
75}

◆ TEST_F() [11/54]

flutter_runner::testing::TEST_F ( FakeFlatlandTest  ,
Initialization   
)

Definition at line 54 of file fake_flatland_unittests.cc.

54 {
55 EXPECT_EQ(fake_flatland().debug_name(), "");
56
57 // Pump the loop one time; the flatland should retain its initial state.
58 loop().RunUntilIdle();
59 EXPECT_EQ(fake_flatland().debug_name(), "");
60}

◆ TEST_F() [12/54]

flutter_runner::testing::TEST_F ( FakeFlatlandTest  ,
Present   
)

Definition at line 77 of file fake_flatland_unittests.cc.

77 {
78 fuchsia::ui::composition::FlatlandPtr flatland = ConnectFlatland();
79
80 // Fire an OnNextFrameBegin event and verify the test receives it.
81 constexpr uint64_t kOnNextFrameAdditionalPresentCredits = 10u;
82 uint64_t on_next_frame_additional_present_credits = 0u;
83 fuchsia::ui::composition::OnNextFrameBeginValues on_next_frame_begin_values;
84 on_next_frame_begin_values.set_additional_present_credits(
85 kOnNextFrameAdditionalPresentCredits);
86 flatland.events().OnNextFrameBegin =
87 [&on_next_frame_additional_present_credits](
88 auto on_next_frame_begin_values) {
89 static bool called_once = false;
90 EXPECT_FALSE(called_once);
91
92 on_next_frame_additional_present_credits =
93 on_next_frame_begin_values.additional_present_credits();
94 called_once = true;
95 };
96 fake_flatland().FireOnNextFrameBeginEvent(
97 std::move(on_next_frame_begin_values));
98 EXPECT_EQ(on_next_frame_additional_present_credits, 0u);
99 loop().RunUntilIdle();
100 EXPECT_EQ(on_next_frame_additional_present_credits,
101 kOnNextFrameAdditionalPresentCredits);
102
103 // Fire an OnFramePresented event and verify the test receives it.
104 constexpr uint64_t kOnFramePresentedNumPresentsAllowed = 20u;
105 uint64_t frame_presented_num_presents_allowed = 0u;
106 flatland.events().OnFramePresented =
107 [&frame_presented_num_presents_allowed](auto frame_presented_info) {
108 static bool called_once = false;
109 EXPECT_FALSE(called_once);
110
111 frame_presented_num_presents_allowed =
112 frame_presented_info.num_presents_allowed;
113 called_once = true;
114 };
115 fake_flatland().FireOnFramePresentedEvent(
116 fuchsia::scenic::scheduling::FramePresentedInfo{
117 .actual_presentation_time = 0,
118 .num_presents_allowed = kOnFramePresentedNumPresentsAllowed,
119 });
120 EXPECT_EQ(frame_presented_num_presents_allowed, 0u);
121 loop().RunUntilIdle();
122 EXPECT_EQ(frame_presented_num_presents_allowed,
123 kOnFramePresentedNumPresentsAllowed);
124
125 // Call Present and verify the fake handled it.
126 constexpr int64_t kPresentRequestedTime = 42;
127 int64_t present_requested_time = 0;
128 fuchsia::ui::composition::PresentArgs present_args;
129 present_args.set_requested_presentation_time(kPresentRequestedTime);
130 fake_flatland().SetPresentHandler(
131 [&present_requested_time](auto present_args) {
132 static bool called_once = false;
133 EXPECT_FALSE(called_once);
134
135 present_requested_time = present_args.requested_presentation_time();
136 called_once = true;
137 });
138 flatland->Present(std::move(present_args));
139 EXPECT_EQ(present_requested_time, 0);
140 loop().RunUntilIdle();
141 EXPECT_EQ(present_requested_time, kPresentRequestedTime);
142}

◆ TEST_F() [13/54]

flutter_runner::testing::TEST_F ( FlatlandConnectionTest  ,
AwaitVsyncsBeforeOnNextFrameBegin   
)

Definition at line 245 of file flatland_connection_unittests.cc.

245 {
246 // Set up callbacks which allow sensing of how many presents were handled.
247 size_t presents_called = 0u;
248 fake_flatland().SetPresentHandler(
249 [&presents_called](auto present_args) { presents_called++; });
250
251 // Create the FlatlandConnection but don't pump the loop. No FIDL calls are
252 // completed yet.
253 flutter_runner::FlatlandConnection flatland_connection(
254 GetCurrentTestName(), TakeFlatlandHandle(), []() { FAIL(); },
255 [](auto...) {});
256 EXPECT_EQ(presents_called, 0u);
257
258 // Pump the loop. Nothing is called.
259 loop().RunUntilIdle();
260 EXPECT_EQ(presents_called, 0u);
261
262 // Simulate an AwaitVsync that comes before the first Present.
263 bool await_vsync_callback_fired = false;
264 AwaitVsyncChecked(flatland_connection, await_vsync_callback_fired,
265 kInitialFlatlandVsyncOffset);
266 EXPECT_TRUE(await_vsync_callback_fired);
267
268 // AwaitVsync that comes before the first Present.
269 bool await_vsync_secondary_callback_fired = false;
270 flatland_connection.AwaitVsyncForSecondaryCallback(
271 [&await_vsync_secondary_callback_fired](fml::TimePoint frame_start,
272 fml::TimePoint frame_end) {
273 await_vsync_secondary_callback_fired = true;
274 });
275 EXPECT_TRUE(await_vsync_secondary_callback_fired);
276}
#define FAIL(name, result)
#define EXPECT_TRUE(handle)
Definition unit_test.h:685

◆ TEST_F() [14/54]

flutter_runner::testing::TEST_F ( FlatlandConnectionTest  ,
BasicPresent   
)

Definition at line 159 of file flatland_connection_unittests.cc.

159 {
160 // Set up callbacks which allow sensing of how many presents were handled.
161 size_t presents_called = 0u;
162 zx_handle_t release_fence_handle;
163 fake_flatland().SetPresentHandler([&presents_called,
164 &release_fence_handle](auto present_args) {
165 presents_called++;
166 release_fence_handle = present_args.release_fences().empty()
167 ? ZX_HANDLE_INVALID
168 : present_args.release_fences().front().get();
169 });
170
171 // Set up a callback which allows sensing of how many vsync's
172 // (`OnFramePresented` events) were handled.
173 size_t vsyncs_handled = 0u;
174 on_frame_presented_event on_frame_presented = [&vsyncs_handled](auto...) {
175 vsyncs_handled++;
176 };
177
178 // Create the FlatlandConnection but don't pump the loop. No FIDL calls are
179 // completed yet.
180 flutter_runner::FlatlandConnection flatland_connection(
181 GetCurrentTestName(), TakeFlatlandHandle(), []() { FAIL(); },
182 std::move(on_frame_presented));
183 EXPECT_EQ(presents_called, 0u);
184 EXPECT_EQ(vsyncs_handled, 0u);
185
186 // Pump the loop. Nothing is called.
187 loop().RunUntilIdle();
188 EXPECT_EQ(presents_called, 0u);
189 EXPECT_EQ(vsyncs_handled, 0u);
190
191 // Simulate an AwaitVsync that comes after the first call.
192 bool await_vsync_fired = false;
193 AwaitVsyncChecked(flatland_connection, await_vsync_fired,
194 kInitialFlatlandVsyncOffset);
195 EXPECT_TRUE(await_vsync_fired);
196
197 // Call Present and Pump the loop; `Present` and its callback is called. No
198 // release fence should be queued.
199 await_vsync_fired = false;
200 zx::event first_release_fence;
201 zx::event::create(0, &first_release_fence);
202 const zx_handle_t first_release_fence_handle = first_release_fence.get();
203 flatland_connection.EnqueueReleaseFence(std::move(first_release_fence));
204 flatland_connection.Present();
205 loop().RunUntilIdle();
206 EXPECT_EQ(presents_called, 1u);
207 EXPECT_EQ(release_fence_handle, ZX_HANDLE_INVALID);
208 EXPECT_EQ(vsyncs_handled, 0u);
209 EXPECT_FALSE(await_vsync_fired);
210
211 // Fire the `OnNextFrameBegin` event. AwaitVsync should be fired.
212 const auto now = fml::TimePoint::Now();
213 const auto kPresentationTime1 = now + fml::TimeDelta::FromSeconds(100);
214 const auto kPresentationTime2 = now + fml::TimeDelta::FromSeconds(200);
215 fuchsia::ui::composition::OnNextFrameBeginValues on_next_frame_begin_values;
216 on_next_frame_begin_values.set_additional_present_credits(3);
217 on_next_frame_begin_values.set_future_presentation_infos(
218 CreateFuturePresentationInfos(kPresentationTime1, kPresentationTime2));
219 fake_flatland().FireOnNextFrameBeginEvent(
220 std::move(on_next_frame_begin_values));
221 loop().RunUntilIdle();
222 AwaitVsyncChecked(flatland_connection, await_vsync_fired, kPresentationTime1);
223 EXPECT_TRUE(await_vsync_fired);
224
225 // Fire the `OnFramePresented` event associated with the first `Present`,
226 fake_flatland().FireOnFramePresentedEvent(
227 fuchsia::scenic::scheduling::FramePresentedInfo());
228 loop().RunUntilIdle();
229 EXPECT_EQ(vsyncs_handled, 1u);
230
231 // Call Present for a second time and Pump the loop; `Present` and its
232 // callback is called. Release fences for the earlier present is used.
233 await_vsync_fired = false;
234 flatland_connection.Present();
235 loop().RunUntilIdle();
236 EXPECT_EQ(presents_called, 2u);
237 EXPECT_EQ(release_fence_handle, first_release_fence_handle);
238
239 // AwaitVsync should be fired with the second present.
240 await_vsync_fired = false;
241 AwaitVsyncChecked(flatland_connection, await_vsync_fired, kPresentationTime2);
242 EXPECT_TRUE(await_vsync_fired);
243}
static constexpr TimeDelta FromSeconds(int64_t seconds)
Definition time_delta.h:49
static TimePoint Now()
Definition time_point.cc:49
EMSCRIPTEN_KEEPALIVE void empty()
std::function< void(fuchsia::scenic::scheduling::FramePresentedInfo)> on_frame_presented_event

◆ TEST_F() [15/54]

flutter_runner::testing::TEST_F ( FlatlandConnectionTest  ,
FlatlandDisconnect   
)

Definition at line 139 of file flatland_connection_unittests.cc.

139 {
140 // Set up a callback which allows sensing of the error state.
141 bool error_fired = false;
142 fml::closure on_session_error = [&error_fired]() { error_fired = true; };
143
144 // Create the FlatlandConnection but don't pump the loop. No FIDL calls are
145 // completed yet.
146 flutter_runner::FlatlandConnection flatland_connection(
147 GetCurrentTestName(), TakeFlatlandHandle(), std::move(on_session_error),
148 [](auto...) { FAIL(); });
149 EXPECT_FALSE(error_fired);
150
151 // Simulate a flatland disconnection, then Pump the loop. The error callback
152 // will fire.
153 fake_flatland().Disconnect(
154 fuchsia::ui::composition::FlatlandError::BAD_OPERATION);
155 loop().RunUntilIdle();
156 EXPECT_TRUE(error_fired);
157}
std::function< void()> closure
Definition closure.h:14

◆ TEST_F() [16/54]

flutter_runner::testing::TEST_F ( FlatlandConnectionTest  ,
Initialization   
)

Definition at line 119 of file flatland_connection_unittests.cc.

119 {
120 // Create the FlatlandConnection but don't pump the loop. No FIDL calls are
121 // completed yet.
122 const std::string debug_name = GetCurrentTestName();
123 flutter_runner::FlatlandConnection flatland_connection(
124 debug_name, TakeFlatlandHandle(), []() { FAIL(); },
125 [](auto...) { FAIL(); });
126 EXPECT_EQ(fake_flatland().debug_name(), "");
127
128 // Simulate an AwaitVsync that returns immediately.
129 bool await_vsync_fired = false;
130 AwaitVsyncChecked(flatland_connection, await_vsync_fired,
131 kInitialFlatlandVsyncOffset);
132 EXPECT_TRUE(await_vsync_fired);
133
134 // Ensure the debug name is set.
135 loop().RunUntilIdle();
136 EXPECT_EQ(fake_flatland().debug_name(), debug_name);
137}

◆ TEST_F() [17/54]

flutter_runner::testing::TEST_F ( FlatlandConnectionTest  ,
PresentCreditExhaustion   
)

Definition at line 342 of file flatland_connection_unittests.cc.

342 {
343 // Set up callbacks which allow sensing of how many presents were handled.
344 size_t num_presents_called = 0u;
345 size_t num_release_fences = 0u;
346 size_t num_acquire_fences = 0u;
347
348 auto reset_test_counters = [&num_presents_called, &num_acquire_fences,
349 &num_release_fences]() {
350 num_presents_called = 0u;
351 num_release_fences = 0u;
352 num_acquire_fences = 0u;
353 };
354
355 fake_flatland().SetPresentHandler(
356 [&num_presents_called, &num_acquire_fences, &num_release_fences](
357 fuchsia::ui::composition::PresentArgs present_args) {
358 num_presents_called++;
359 num_acquire_fences = present_args.acquire_fences().size();
360 num_release_fences = present_args.release_fences().size();
361 });
362
363 // Create the FlatlandConnection but don't pump the loop. No FIDL calls are
364 // completed yet.
365 on_frame_presented_event on_frame_presented = [](auto...) {};
366 flutter_runner::FlatlandConnection flatland_connection(
367 GetCurrentTestName(), TakeFlatlandHandle(), []() { FAIL(); },
368 std::move(on_frame_presented));
369 EXPECT_EQ(num_presents_called, 0u);
370
371 // Pump the loop. Nothing is called.
372 loop().RunUntilIdle();
373 EXPECT_EQ(num_presents_called, 0u);
374
375 // Simulate an AwaitVsync that comes before the first Present.
376 flatland_connection.AwaitVsync([](fml::TimePoint, fml::TimePoint) {});
377 loop().RunUntilIdle();
378 EXPECT_EQ(num_presents_called, 0u);
379
380 // This test uses a fire callback that triggers Present() with a single
381 // acquire and release fence in order to approximate the behavior of the real
382 // flutter fire callback and let us drive presents with ONFBs
383 auto fire_callback = [dispatcher = loop().dispatcher(), &flatland_connection](
385 fml::TimePoint frame_end) {
386 async::PostTask(dispatcher, [&flatland_connection]() {
387 zx::event acquire_fence;
388 zx::event::create(0, &acquire_fence);
389 zx::event release_fence;
390 zx::event::create(0, &release_fence);
391 flatland_connection.EnqueueAcquireFence(std::move(acquire_fence));
392 flatland_connection.EnqueueReleaseFence(std::move(release_fence));
393 flatland_connection.Present();
394 });
395 };
396
397 // Call Await Vsync with a callback that triggers Present and consumes the one
398 // and only present credit we start with.
399 reset_test_counters();
400 flatland_connection.AwaitVsync(fire_callback);
401 loop().RunUntilIdle();
402 EXPECT_EQ(num_presents_called, 1u);
403 EXPECT_EQ(num_acquire_fences, 1u);
404 EXPECT_EQ(num_release_fences, 0u);
405
406 // Do it again, but this time we should not get a present because the client
407 // has exhausted its present credits.
408 reset_test_counters();
409 flatland_connection.AwaitVsync(fire_callback);
410 OnNextFrameBegin(0);
411 loop().RunUntilIdle();
412 EXPECT_EQ(num_presents_called, 0u);
413
414 // Supply a present credit but dont set a new fire callback. Fire callback
415 // from previous ONFB should fire and trigger a Present()
416 reset_test_counters();
417 OnNextFrameBegin(1);
418 loop().RunUntilIdle();
419 EXPECT_EQ(num_presents_called, 1u);
420 EXPECT_EQ(num_acquire_fences, 1u);
421 EXPECT_EQ(num_release_fences, 1u);
422
423 // From here on we are testing handling of a race condition where a fire
424 // callback is fired but another ONFB arrives before the present from the
425 // first fire callback comes in, causing present_credits to be negative
426 // within Present().
427
428 uint num_onfb = 5;
429 uint num_deferred_callbacks = 0;
430 // This callback will accumulate num_onfb+1 calls before firing all
431 // of their presents at once.
432 auto accumulating_fire_callback = [&](fml::TimePoint frame_start,
433 fml::TimePoint frame_end) {
434 num_deferred_callbacks++;
435 if (num_deferred_callbacks > num_onfb) {
437 for (uint i = 0; i < num_onfb + 1; i++) {
438 fire_callback(now, now);
439 num_deferred_callbacks--;
440 }
441 }
442 };
443
444 reset_test_counters();
445 for (uint i = 0; i < num_onfb; i++) {
446 flatland_connection.AwaitVsync(accumulating_fire_callback);
447 // only supply a present credit on the first call. Since Presents are being
448 // deferred this credit will not be used up, but we need a credit to call
449 // the accumulating_fire_callback
450 OnNextFrameBegin(i == 0 ? 1 : 0);
451 loop().RunUntilIdle();
452 EXPECT_EQ(num_presents_called, 0u);
453 }
454
455 // This is the num_onfb+1 call to accumulating_fire_callback which triggers
456 // all of the "racing" presents to fire. the first one should be fired,
457 // but the other num_onfb Presents should be deferred.
458 flatland_connection.AwaitVsync(accumulating_fire_callback);
459 OnNextFrameBegin(0);
460 loop().RunUntilIdle();
461 EXPECT_EQ(num_presents_called, 1u);
462 EXPECT_EQ(num_acquire_fences, 1u);
463 EXPECT_EQ(num_release_fences, 1u);
464
465 // Supply a present credit, but pass an empty lambda to AwaitVsync so
466 // that it doesnt call Present(). Should get a deferred present with
467 // all the accumulate acuire fences
468 reset_test_counters();
469 flatland_connection.AwaitVsync([](fml::TimePoint, fml::TimePoint) {});
470 OnNextFrameBegin(1);
471 loop().RunUntilIdle();
472 EXPECT_EQ(num_presents_called, 1u);
473 EXPECT_EQ(num_acquire_fences, num_onfb);
474 EXPECT_EQ(num_release_fences, 1u);
475
476 // Pump another frame to check that release fences accumulate as expected
477 reset_test_counters();
478 flatland_connection.AwaitVsync(fire_callback);
479 OnNextFrameBegin(1);
480 loop().RunUntilIdle();
481 EXPECT_EQ(num_presents_called, 1u);
482 EXPECT_EQ(num_acquire_fences, 1u);
483 EXPECT_EQ(num_release_fences, num_onfb);
484}
std::string GetCurrentTestName()
Gets the name of the currently running test. This is useful in generating logs or assets based on tes...
Definition testing.cc:15

◆ TEST_F() [18/54]

flutter_runner::testing::TEST_F ( FlatlandConnectionTest  ,
RunsOutOfFuturePresentationInfos   
)

Definition at line 278 of file flatland_connection_unittests.cc.

278 {
279 // Set up callbacks which allow sensing of how many presents were handled.
280 size_t presents_called = 0u;
281 fake_flatland().SetPresentHandler(
282 [&presents_called](auto present_args) { presents_called++; });
283
284 // Set up a callback which allows sensing of how many vsync's
285 // (`OnFramePresented` events) were handled.
286 size_t vsyncs_handled = 0u;
287 on_frame_presented_event on_frame_presented = [&vsyncs_handled](auto...) {
288 vsyncs_handled++;
289 };
290
291 // Create the FlatlandConnection but don't pump the loop. No FIDL calls are
292 // completed yet.
293 flutter_runner::FlatlandConnection flatland_connection(
294 GetCurrentTestName(), TakeFlatlandHandle(), []() { FAIL(); },
295 std::move(on_frame_presented));
296 EXPECT_EQ(presents_called, 0u);
297 EXPECT_EQ(vsyncs_handled, 0u);
298
299 // Pump the loop. Nothing is called.
300 loop().RunUntilIdle();
301 EXPECT_EQ(presents_called, 0u);
302 EXPECT_EQ(vsyncs_handled, 0u);
303
304 // Simulate an AwaitVsync that comes before the first Present.
305 bool await_vsync_callback_fired = false;
306 AwaitVsyncChecked(flatland_connection, await_vsync_callback_fired,
307 kInitialFlatlandVsyncOffset);
308 EXPECT_TRUE(await_vsync_callback_fired);
309
310 // Queue Present.
311 flatland_connection.Present();
312 loop().RunUntilIdle();
313 EXPECT_EQ(presents_called, 1u);
314
315 // Fire the `OnNextFrameBegin` event. AwaitVsync callback should be fired with
316 // the first presentation time.
317 await_vsync_callback_fired = false;
318 const auto kPresentationTime1 =
320 const auto kVsyncInterval = fml::TimeDelta::FromSeconds(234);
321 const auto kPresentationTime2 = kPresentationTime1 + kVsyncInterval;
322 OnNextFrameBegin(1, kPresentationTime1, kPresentationTime2);
323 loop().RunUntilIdle();
324 AwaitVsyncChecked(flatland_connection, await_vsync_callback_fired,
325 kPresentationTime1);
326 EXPECT_TRUE(await_vsync_callback_fired);
327
328 // Second consecutive AwaitVsync callback should be fired with
329 // the second presentation time.
330 await_vsync_callback_fired = false;
331 AwaitVsyncChecked(flatland_connection, await_vsync_callback_fired,
332 kPresentationTime2);
333 EXPECT_TRUE(await_vsync_callback_fired);
334
335 // Another AwaitVsync callback should be fired with vsync_interval.
336 await_vsync_callback_fired = false;
337 AwaitVsyncChecked(flatland_connection, await_vsync_callback_fired,
338 kPresentationTime2 + kVsyncInterval);
339 EXPECT_TRUE(await_vsync_callback_fired);
340}

◆ TEST_F() [19/54]

flutter_runner::testing::TEST_F ( FocusDelegateTest  ,
RequestFocusFailTest   
)

Definition at line 163 of file focus_delegate_unittests.cc.

163 {
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 "[" +
191 std::to_string(
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}
rapidjson::Value ParsePlatformMessage(std::string json)

◆ TEST_F() [20/54]

flutter_runner::testing::TEST_F ( FocusDelegateTest  ,
RequestFocusTest   
)

Definition at line 132 of file focus_delegate_unittests.cc.

132 {
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}

◆ TEST_F() [21/54]

flutter_runner::testing::TEST_F ( FocusDelegateTest  ,
WatchCallbackSeries   
)

Definition at line 65 of file focus_delegate_unittests.cc.

65 {
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.
77 auto response = FakePlatformMessageResponse::Create();
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}

◆ TEST_F() [22/54]

flutter_runner::testing::TEST_F ( PlatformViewTests  ,
ChangesAccessibilitySettings   
)

Definition at line 703 of file platform_view_unittest.cc.

703 {
704 MockPlatformViewDelegate delegate;
705 flutter::TaskRunners task_runners =
706 flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
707
708 EXPECT_FALSE(delegate.semantics_enabled());
709 EXPECT_EQ(delegate.semantics_features(), 0);
710
711 auto platform_view =
712 PlatformViewBuilder(delegate, std::move(task_runners)).Build();
713
714 RunLoopUntilIdle();
715
716 platform_view.SetSemanticsEnabled(true);
717
718 EXPECT_TRUE(delegate.semantics_enabled());
719 EXPECT_EQ(delegate.semantics_features(),
720 static_cast<int32_t>(
722
723 platform_view.SetSemanticsEnabled(false);
724
725 EXPECT_FALSE(delegate.semantics_enabled());
726 EXPECT_EQ(delegate.semantics_features(), 0);
727}
std::unique_ptr< flutter::PlatformViewIOS > platform_view

◆ TEST_F() [23/54]

flutter_runner::testing::TEST_F ( PlatformViewTests  ,
CreateSurfaceTest   
)

Definition at line 637 of file platform_view_unittest.cc.

637 {
638 MockPlatformViewDelegate delegate;
639
640 flutter::TaskRunners task_runners =
641 flutter::TaskRunners("test_runners", // label
642 nullptr, // platform
644 async_get_default_dispatcher()), // raster
645 nullptr, // ui
646 nullptr // io
647 );
648
649 // Test create surface callback function.
651 nullptr,
652 flutter::MakeDefaultContextOptions(flutter::ContextType::kRender));
653 std::shared_ptr<MockExternalViewEmbedder> external_view_embedder =
654 std::make_shared<MockExternalViewEmbedder>();
655 auto CreateSurfaceCallback = [&external_view_embedder, gr_context]() {
656 return std::make_unique<flutter_runner::Surface>(
657 "PlatformViewTest", external_view_embedder, gr_context.get());
658 };
659
660 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
661 .SetCreateSurfaceCallback(CreateSurfaceCallback)
662 .SetExternalViewEmbedder(external_view_embedder)
663 .Build();
664 platform_view.NotifyCreated();
665
666 RunLoopUntilIdle();
667
668 EXPECT_EQ(gr_context.get(), delegate.surface()->GetContext());
669 EXPECT_EQ(external_view_embedder.get(),
670 platform_view.CreateExternalViewEmbedder().get());
671}
static sk_sp< GrDirectContext > MakeMock(const GrMockOptions *, const GrContextOptions &)
T * get() const
Definition SkRefCnt.h:303
fml::RefPtr< fml::TaskRunner > CreateFMLTaskRunner(async_dispatcher_t *dispatcher)
GrContextOptions MakeDefaultContextOptions(ContextType type, std::optional< GrBackendApi > api)
Initializes GrContextOptions with values suitable for Flutter. The options can be further tweaked bef...

◆ TEST_F() [24/54]

flutter_runner::testing::TEST_F ( PlatformViewTests  ,
CreateViewTest   
)

Definition at line 775 of file platform_view_unittest.cc.

775 {
776 MockPlatformViewDelegate delegate;
777 const uint64_t view_id = 42;
778 flutter::TaskRunners task_runners =
779 flutter::TaskRunners("test_runners", // label
781 async_get_default_dispatcher()), // platform
782 nullptr, // raster
783 nullptr, // ui
784 nullptr // io
785 );
786
787 // Test wireframe callback function. If the message sent to the platform
788 // view was properly handled and parsed, this function should be called,
789 // setting |wireframe_enabled| to true.
790 bool create_view_called = false;
791 auto CreateViewCallback =
792 [&create_view_called, this](
793 int64_t view_id, flutter_runner::ViewCallback on_view_created,
794 flutter_runner::ViewCreatedCallback on_view_bound, bool hit_testable,
795 bool focusable) {
796 create_view_called = true;
797 on_view_created();
798 fuchsia::ui::composition::ContentId content_id;
799 on_view_bound(std::move(content_id), MakeChildViewWatcher());
800 };
801
802 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
803 .SetCreateViewCallback(CreateViewCallback)
804 .Build();
805
806 // Cast platform_view to its base view so we can have access to the public
807 // "HandlePlatformMessage" function.
808 auto base_view = static_cast<flutter::PlatformView*>(&platform_view);
809 EXPECT_TRUE(base_view);
810
811 // JSON for the message to be passed into the PlatformView.
812 std::ostringstream create_view_message;
813 create_view_message << "{" << " \"method\":\"View.create\","
814 << " \"args\":{" << " \"viewId\":" << view_id << ","
815 << " \"hitTestable\":true," << " \"focusable\":true"
816 << " }" << "}";
817
818 std::string create_view_call = create_view_message.str();
819 std::unique_ptr<flutter::PlatformMessage> message =
820 std::make_unique<flutter::PlatformMessage>(
821 "flutter/platform_views",
822 fml::MallocMapping::Copy(create_view_call.c_str(),
823 create_view_call.size()),
825 base_view->HandlePlatformMessage(std::move(message));
826
827 RunLoopUntilIdle();
828
829 EXPECT_TRUE(create_view_called);
830
831 // Platform view forwards the 'View.viewConnected' message on the
832 // 'flutter/platform_views' channel when a view gets created.
833 std::ostringstream view_connected_expected_out;
834 view_connected_expected_out << "{" << "\"method\":\"View.viewConnected\","
835 << "\"args\":{" << " \"viewId\":" << view_id
836 << " }" << "}";
837
838 ASSERT_NE(delegate.message(), nullptr);
839 EXPECT_EQ(view_connected_expected_out.str(),
840 ToString(delegate.message()->data()));
841}
Platform views are created by the shell on the platform task runner. Unless explicitly specified,...
static MallocMapping Copy(const T *begin, const T *end)
Definition mapping.h:162
std::function< void()> ViewCallback
std::function< void(fuchsia::ui::composition::ContentId, fuchsia::ui::composition::ChildViewWatcherHandle child_view_watcher)> ViewCreatedCallback

◆ TEST_F() [25/54]

flutter_runner::testing::TEST_F ( PlatformViewTests  ,
DestroyViewTest   
)

Definition at line 960 of file platform_view_unittest.cc.

960 {
961 MockPlatformViewDelegate delegate;
962 const uint64_t view_id = 42;
963
964 flutter::TaskRunners task_runners =
965 flutter::TaskRunners("test_runners", // label
967 async_get_default_dispatcher()), // platform
968 nullptr, // raster
969 nullptr, // ui
970 nullptr // io
971 );
972
973 bool destroy_view_called = false;
974
975 auto on_destroy_view = [&destroy_view_called](
976 int64_t view_id,
977 flutter_runner::ViewIdCallback on_view_unbound) {
978 destroy_view_called = true;
979 fuchsia::ui::composition::ContentId content_id;
980 on_view_unbound(std::move(content_id));
981 };
982
983 bool create_view_called = false;
984 auto on_create_view = [&create_view_called, this](
985 int64_t view_id,
986 flutter_runner::ViewCallback on_view_created,
988 bool hit_testable, bool focusable) {
989 create_view_called = true;
990 on_view_created();
991 fuchsia::ui::composition::ContentId content_id;
992 on_view_bound(std::move(content_id), MakeChildViewWatcher());
993 };
994
995 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
996 .SetCreateViewCallback(on_create_view)
997 .SetDestroyViewCallback(on_destroy_view)
998 .Build();
999
1000 // Cast platform_view to its base view so we can have access to the public
1001 // "HandlePlatformMessage" function.
1002 auto base_view = static_cast<flutter::PlatformView*>(&platform_view);
1003 EXPECT_TRUE(base_view);
1004
1005 std::ostringstream create_message;
1006 create_message << "{" << " \"method\":\"View.create\","
1007 << " \"args\": {" << " \"viewId\":" << view_id << ","
1008 << " \"hitTestable\":true,"
1009 << " \"focusable\":true" << " }" << "}";
1010
1011 auto create_response = FakePlatformMessageResponse::Create();
1012 base_view->HandlePlatformMessage(create_response->WithMessage(
1013 "flutter/platform_views", create_message.str()));
1014 RunLoopUntilIdle();
1015
1016 delegate.Reset();
1017
1018 // JSON for the message to be passed into the PlatformView.
1019 std::ostringstream dispose_message;
1020 dispose_message << "{" << " \"method\":\"View.dispose\","
1021 << " \"args\": {" << " \"viewId\":" << view_id
1022 << " }" << "}";
1023
1024 std::string dispose_view_call = dispose_message.str();
1025 std::unique_ptr<flutter::PlatformMessage> message =
1026 std::make_unique<flutter::PlatformMessage>(
1027 "flutter/platform_views",
1028 fml::MallocMapping::Copy(dispose_view_call.c_str(),
1029 dispose_view_call.size()),
1031 base_view->HandlePlatformMessage(std::move(message));
1032
1033 RunLoopUntilIdle();
1034
1035 EXPECT_TRUE(destroy_view_called);
1036
1037 // Platform view forwards the 'View.viewDisconnected' message on the
1038 // 'flutter/platform_views' channel when a view gets destroyed.
1039 std::ostringstream view_disconnected_expected_out;
1040 view_disconnected_expected_out
1041 << "{" << "\"method\":\"View.viewDisconnected\"," << "\"args\":{"
1042 << " \"viewId\":" << view_id << " }" << "}";
1043
1044 ASSERT_NE(delegate.message(), nullptr);
1045 EXPECT_EQ(view_disconnected_expected_out.str(),
1046 ToString(delegate.message()->data()));
1047}
std::function< void(fuchsia::ui::composition::ContentId)> ViewIdCallback

◆ TEST_F() [26/54]

flutter_runner::testing::TEST_F ( PlatformViewTests  ,
EnableWireframeTest   
)

Definition at line 731 of file platform_view_unittest.cc.

731 {
732 MockPlatformViewDelegate delegate;
733 flutter::TaskRunners task_runners =
734 flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
735
736 // Test wireframe callback function. If the message sent to the platform
737 // view was properly handled and parsed, this function should be called,
738 // setting |wireframe_enabled| to true.
739 bool wireframe_enabled = false;
740 auto EnableWireframeCallback = [&wireframe_enabled](bool should_enable) {
741 wireframe_enabled = should_enable;
742 };
743
744 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
745 .SetEnableWireframeCallback(EnableWireframeCallback)
746 .Build();
747
748 // Cast platform_view to its base view so we can have access to the public
749 // "HandlePlatformMessage" function.
750 auto base_view = static_cast<flutter::PlatformView*>(&platform_view);
751 EXPECT_TRUE(base_view);
752
753 // JSON for the message to be passed into the PlatformView.
754 const uint8_t txt[] =
755 "{"
756 " \"method\":\"View.enableWireframe\","
757 " \"args\": {"
758 " \"enable\":true"
759 " }"
760 "}";
761
762 std::unique_ptr<flutter::PlatformMessage> message =
763 std::make_unique<flutter::PlatformMessage>(
764 "flutter/platform_views", fml::MallocMapping::Copy(txt, sizeof(txt)),
766 base_view->HandlePlatformMessage(std::move(message));
767
768 RunLoopUntilIdle();
769
770 EXPECT_TRUE(wireframe_enabled);
771}

◆ TEST_F() [27/54]

flutter_runner::testing::TEST_F ( PlatformViewTests  ,
GetFocusStatesTest   
)

Definition at line 1052 of file platform_view_unittest.cc.

1052 {
1053 MockPlatformViewDelegate delegate;
1054 flutter::TaskRunners task_runners =
1055 flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
1056
1058 fidl::BindingSet<fuchsia::ui::views::ViewRefFocused> vrf_bindings;
1059 auto vrf_handle = vrf_bindings.AddBinding(&vrf);
1060
1061 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1062 .SetViewRefFocused(std::move(vrf_handle))
1063 .Build();
1064
1065 // Cast platform_view to its base view so we can have access to the public
1066 // "HandlePlatformMessage" function.
1067 auto base_view = static_cast<flutter::PlatformView*>(&platform_view);
1068 EXPECT_TRUE(base_view);
1069
1070 std::vector<bool> vrf_states{false, true, true, false,
1071 true, false, true, true};
1072
1073 for (std::size_t i = 0; i < vrf_states.size(); ++i) {
1074 // View.focus.getNext should complete with the next focus state.
1075 auto response1 = FakePlatformMessageResponse::Create();
1076 base_view->HandlePlatformMessage(response1->WithMessage(
1077 "flutter/platform_views", "{\"method\":\"View.focus.getNext\"}"));
1078 // Duplicate View.focus.getNext requests should complete empty.
1079 auto response2 = FakePlatformMessageResponse::Create();
1080 base_view->HandlePlatformMessage(response2->WithMessage(
1081 "flutter/platform_views", "{\"method\":\"View.focus.getNext\"}"));
1082
1083 // Post watch events and make sure the hanging get is invoked each time.
1084 RunLoopUntilIdle();
1085 EXPECT_EQ(vrf.times_watched, i + 1);
1086
1087 // Dispatch the next vrf event.
1088 vrf.ScheduleCallback(vrf_states[i]);
1089 RunLoopUntilIdle();
1090
1091 // Make sure View.focus.getCurrent completes with the current focus state.
1092 auto response3 = FakePlatformMessageResponse::Create();
1093 base_view->HandlePlatformMessage(response3->WithMessage(
1094 "flutter/platform_views", "{\"method\":\"View.focus.getCurrent\"}"));
1095 // Duplicate View.focus.getCurrent are allowed.
1096 auto response4 = FakePlatformMessageResponse::Create();
1097 base_view->HandlePlatformMessage(response4->WithMessage(
1098 "flutter/platform_views", "{\"method\":\"View.focus.getCurrent\"}"));
1099
1100 // Run event loop and check our results.
1101 RunLoopUntilIdle();
1102 response1->ExpectCompleted(vrf_states[i] ? "[true]" : "[false]");
1103 response2->ExpectCompleted("[null]");
1104 response3->ExpectCompleted(vrf_states[i] ? "[true]" : "[false]");
1105 response4->ExpectCompleted(vrf_states[i] ? "[true]" : "[false]");
1106 }
1107}

◆ TEST_F() [28/54]

flutter_runner::testing::TEST_F ( PlatformViewTests  ,
InvalidPlatformMessageRequest   
)

Definition at line 575 of file platform_view_unittest.cc.

575 {
576 MockPlatformViewDelegate delegate;
577 flutter::TaskRunners task_runners =
578 flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
579
581 fidl::BindingSet<fuchsia::ui::views::ViewRefFocused> vrf_bindings;
582 auto vrf_handle = vrf_bindings.AddBinding(&vrf);
583
584 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
585 .SetViewRefFocused(std::move(vrf_handle))
586 .Build();
587
588 // Cast platform_view to its base view so we can have access to the public
589 // "HandlePlatformMessage" function.
590 auto base_view = static_cast<flutter::PlatformView*>(&platform_view);
591 EXPECT_TRUE(base_view);
592
593 // Invalid platform channel.
594 auto response1 = FakePlatformMessageResponse::Create();
595 base_view->HandlePlatformMessage(response1->WithMessage(
596 "flutter/invalid", "{\"method\":\"Invalid.invalidMethod\"}"));
597
598 // Invalid json.
599 auto response2 = FakePlatformMessageResponse::Create();
600 base_view->HandlePlatformMessage(
601 response2->WithMessage("flutter/platform_views", "{Invalid JSON"));
602
603 // Invalid method.
604 auto response3 = FakePlatformMessageResponse::Create();
605 base_view->HandlePlatformMessage(response3->WithMessage(
606 "flutter/platform_views", "{\"method\":\"View.focus.invalidMethod\"}"));
607
608 // Missing arguments.
609 auto response4 = FakePlatformMessageResponse::Create();
610 base_view->HandlePlatformMessage(response4->WithMessage(
611 "flutter/platform_views", "{\"method\":\"View.update\"}"));
612 auto response5 = FakePlatformMessageResponse::Create();
613 base_view->HandlePlatformMessage(
614 response5->WithMessage("flutter/platform_views",
615 "{\"method\":\"View.update\",\"args\":{"
616 "\"irrelevantField\":\"irrelevantValue\"}}"));
617
618 // Wrong argument types.
619 auto response6 = FakePlatformMessageResponse::Create();
620 base_view->HandlePlatformMessage(response6->WithMessage(
621 "flutter/platform_views",
622 "{\"method\":\"View.update\",\"args\":{\"viewId\":false,\"hitTestable\":"
623 "123,\"focusable\":\"yes\"}}"));
624
625 // Run the event loop and check our responses.
626 RunLoopUntilIdle();
627 response1->ExpectCompleted("");
628 response2->ExpectCompleted("");
629 response3->ExpectCompleted("");
630 response4->ExpectCompleted("");
631 response5->ExpectCompleted("");
632 response6->ExpectCompleted("");
633}

◆ TEST_F() [29/54]

flutter_runner::testing::TEST_F ( PlatformViewTests  ,
OnKeyEvent   
)

Definition at line 1322 of file platform_view_unittest.cc.

1322 {
1323 struct EventFlow {
1324 fuchsia::ui::input3::KeyEvent event;
1325 fuchsia::ui::input3::KeyEventStatus expected_key_event_status;
1326 std::string expected_platform_message;
1327 };
1328
1329 MockPlatformViewDelegate delegate;
1330 flutter::TaskRunners task_runners =
1331 flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
1332
1333 fuchsia::ui::input3::KeyboardHandle keyboard_service;
1334 MockKeyboard keyboard(keyboard_service.NewRequest());
1335
1336 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1337 .SetKeyboard(std::move(keyboard_service))
1338 .Build();
1339 RunLoopUntilIdle();
1340
1341 std::vector<EventFlow> events;
1342 // Press A. Get 'a'.
1343 // The HID usage for the key A is 0x70004, or 458756.
1344 events.emplace_back(EventFlow{
1345 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
1346 fuchsia::input::Key::A),
1347 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1348 R"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":97,"modifiers":0})",
1349 });
1350 // Release A. Get 'a' release.
1351 events.emplace_back(EventFlow{
1352 MakeEvent(fuchsia::ui::input3::KeyEventType::RELEASED, std::nullopt,
1353 fuchsia::input::Key::A),
1354 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1355 R"({"type":"keyup","keymap":"fuchsia","hidUsage":458756,"codePoint":97,"modifiers":0})",
1356 });
1357 // Press CAPS_LOCK. Modifier now active.
1358 events.emplace_back(EventFlow{
1359 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED,
1360 fuchsia::ui::input3::Modifiers::CAPS_LOCK,
1361 fuchsia::input::Key::CAPS_LOCK),
1362 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1363 R"({"type":"keydown","keymap":"fuchsia","hidUsage":458809,"codePoint":0,"modifiers":1})",
1364 });
1365 // Press A. Get 'A'.
1366 events.emplace_back(EventFlow{
1367 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
1368 fuchsia::input::Key::A),
1369 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1370 R"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":65,"modifiers":1})",
1371 });
1372 // Release CAPS_LOCK.
1373 events.emplace_back(EventFlow{
1374 MakeEvent(fuchsia::ui::input3::KeyEventType::RELEASED,
1375 fuchsia::ui::input3::Modifiers::CAPS_LOCK,
1376 fuchsia::input::Key::CAPS_LOCK),
1377 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1378 R"({"type":"keyup","keymap":"fuchsia","hidUsage":458809,"codePoint":0,"modifiers":1})",
1379 });
1380 // Press A again. This time get 'A'.
1381 // CAPS_LOCK is latched active even if it was just released.
1382 events.emplace_back(EventFlow{
1383 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
1384 fuchsia::input::Key::A),
1385 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1386 R"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":65,"modifiers":1})",
1387 });
1388
1389 for (const auto& event : events) {
1390 fuchsia::ui::input3::KeyEvent e;
1391 event.event.Clone(&e);
1392 fuchsia::ui::input3::KeyEventStatus key_event_status{0u};
1393 keyboard.listener_->OnKeyEvent(
1394 std::move(e),
1395 [&key_event_status](fuchsia::ui::input3::KeyEventStatus status) {
1396 key_event_status = status;
1397 });
1398 RunLoopUntilIdle();
1399
1400 ASSERT_NOTNULL(delegate.message());
1401 EXPECT_EQ(event.expected_platform_message,
1402 ToString(delegate.message()->data()));
1403 EXPECT_EQ(event.expected_key_event_status, key_event_status);
1404 }
1405}
#define ASSERT_NOTNULL(ptr)
Definition assert.h:323
FlKeyEvent * event
const char * ToString(ax::mojom::Event event)

◆ TEST_F() [30/54]

flutter_runner::testing::TEST_F ( PlatformViewTests  ,
OnShaderWarmup   
)

Definition at line 1407 of file platform_view_unittest.cc.

1407 {
1408 MockPlatformViewDelegate delegate;
1409 flutter::TaskRunners task_runners =
1410 flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
1411
1412 uint64_t width = 200;
1413 uint64_t height = 100;
1414 std::vector<std::string> shaders = {"foo.skp", "bar.skp", "baz.skp"};
1415
1416 OnShaderWarmupCallback on_shader_warmup_callback =
1417 [&](const std::vector<std::string>& shaders_in,
1418 std::function<void(uint32_t)> completion_callback, uint64_t width_in,
1419 uint64_t height_in) {
1420 ASSERT_EQ(shaders.size(), shaders_in.size());
1421 for (size_t i = 0; i < shaders_in.size(); i++) {
1422 ASSERT_EQ(shaders[i], shaders_in[i]);
1423 }
1424 ASSERT_EQ(width, width_in);
1425 ASSERT_EQ(height, height_in);
1426
1427 completion_callback(shaders_in.size());
1428 };
1429
1430 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1431 .SetShaderWarmupCallback(on_shader_warmup_callback)
1432 .Build();
1433
1434 std::ostringstream shaders_array_ostream;
1435 shaders_array_ostream << "[ ";
1436 for (auto it = shaders.begin(); it != shaders.end(); ++it) {
1437 shaders_array_ostream << "\"" << *it << "\"";
1438 if (std::next(it) != shaders.end()) {
1439 shaders_array_ostream << ", ";
1440 }
1441 }
1442 shaders_array_ostream << "]";
1443
1444 std::string shaders_array_string = shaders_array_ostream.str();
1445
1446 // Create initial view for testing.
1447 std::ostringstream warmup_shaders_ostream;
1448 warmup_shaders_ostream << "{" << " \"method\":\"WarmupSkps\","
1449 << " \"args\":{"
1450 << " \"shaders\":" << shaders_array_string << ","
1451 << " \"width\":" << width << ","
1452 << " \"height\":" << height << " }" << "}\n";
1453 std::string warmup_shaders_string = warmup_shaders_ostream.str();
1454
1456 new TestPlatformMessageResponse);
1457 static_cast<flutter::PlatformView*>(&platform_view)
1458 ->HandlePlatformMessage(std::make_unique<flutter::PlatformMessage>(
1459 "fuchsia/shader_warmup",
1460 fml::MallocMapping::Copy(warmup_shaders_string.c_str(),
1461 warmup_shaders_string.size()),
1462 response));
1463 RunLoopUntilIdle();
1464 ASSERT_TRUE(response->is_complete());
1465
1466 std::ostringstream expected_result_ostream;
1467 expected_result_ostream << "[" << shaders.size() << "]";
1468 std::string expected_result_string = expected_result_ostream.str();
1469 EXPECT_EQ(expected_result_string, response->result_string);
1470}
std::function< void(const std::vector< std::string > &, std::function< void(uint32_t)>, uint64_t, uint64_t)> OnShaderWarmupCallback
int32_t height
int32_t width

◆ TEST_F() [31/54]

flutter_runner::testing::TEST_F ( PlatformViewTests  ,
RequestFocusDisposedTest   
)

Definition at line 1232 of file platform_view_unittest.cc.

1232 {
1233 MockPlatformViewDelegate delegate;
1234 flutter::TaskRunners task_runners =
1235 flutter::TaskRunners("test_runners", // label
1237 async_get_default_dispatcher()), // platform
1238 nullptr, // raster
1239 nullptr, // ui
1240 nullptr // io
1241 );
1242
1243 FakeFocuser focuser;
1244 fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
1245 auto focuser_handle = focuser_bindings.AddBinding(&focuser);
1246
1247 bool create_view_called = false;
1248 auto on_create_view = [&create_view_called, this](
1249 int64_t view_id,
1250 flutter_runner::ViewCallback on_view_created,
1252 bool hit_testable, bool focusable) {
1253 create_view_called = true;
1254 on_view_created();
1255 fuchsia::ui::composition::ContentId content_id;
1256 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1257 };
1258
1259 bool destroy_view_called = false;
1260
1261 auto on_destroy_view = [&destroy_view_called](
1262 int64_t view_id,
1263 flutter_runner::ViewIdCallback on_view_unbound) {
1264 destroy_view_called = true;
1265 fuchsia::ui::composition::ContentId content_id;
1266 on_view_unbound(std::move(content_id));
1267 };
1268
1269 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1270 .SetFocuser(std::move(focuser_handle))
1271 .SetCreateViewCallback(on_create_view)
1272 .SetDestroyViewCallback(on_destroy_view)
1273 .Build();
1274
1275 auto base_view = static_cast<flutter::PlatformView*>(&platform_view);
1276 EXPECT_TRUE(base_view);
1277
1278 uint64_t view_id = 42;
1279
1280 // Create a new view
1281 std::ostringstream create_message;
1282 create_message << "{" << " \"method\":\"View.create\","
1283 << " \"args\": {" << " \"viewId\":" << view_id << ","
1284 << " \"hitTestable\":true,"
1285 << " \"focusable\":true" << " }" << "}";
1286
1287 auto create_response = FakePlatformMessageResponse::Create();
1288 base_view->HandlePlatformMessage(create_response->WithMessage(
1289 "flutter/platform_views", create_message.str()));
1290 RunLoopUntilIdle();
1291
1292 EXPECT_FALSE(destroy_view_called);
1293 // Dispose of the view
1294 std::ostringstream dispose_message;
1295 dispose_message << "{" << " \"method\":\"View.dispose\","
1296 << " \"args\": {" << " \"viewId\":" << view_id
1297 << " }" << "}";
1298
1299 auto dispose_response = FakePlatformMessageResponse::Create();
1300 base_view->HandlePlatformMessage(dispose_response->WithMessage(
1301 "flutter/platform_views", dispose_message.str()));
1302 RunLoopUntilIdle();
1303 EXPECT_TRUE(destroy_view_called);
1304
1305 // Request focus on newly disposed view
1306 std::ostringstream focus_message;
1307 focus_message << "{" << " \"method\":\"View.focus.requestById\","
1308 << " \"args\": {" << " \"viewId\":" << view_id
1309 << " }" << "}";
1310
1311 auto focus_response = FakePlatformMessageResponse::Create();
1312 base_view->HandlePlatformMessage(focus_response->WithMessage(
1313 "flutter/platform_views", focus_message.str()));
1314 RunLoopUntilIdle();
1315
1316 // Expect it to fail
1317 focus_response->ExpectCompleted("[1]");
1318 EXPECT_FALSE(focuser.request_focus_called());
1319}

◆ TEST_F() [32/54]

flutter_runner::testing::TEST_F ( PlatformViewTests  ,
RequestFocusNeverCreatedTest   
)

Definition at line 1180 of file platform_view_unittest.cc.

1180 {
1181 MockPlatformViewDelegate delegate;
1182 flutter::TaskRunners task_runners =
1183 flutter::TaskRunners("test_runners", // label
1185 async_get_default_dispatcher()), // platform
1186 nullptr, // raster
1187 nullptr, // ui
1188 nullptr // io
1189 );
1190
1191 FakeFocuser focuser;
1192 fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
1193 auto focuser_handle = focuser_bindings.AddBinding(&focuser);
1194
1195 bool create_view_called = false;
1196 auto on_create_view = [&create_view_called, this](
1197 int64_t view_id,
1198 flutter_runner::ViewCallback on_view_created,
1200 bool hit_testable, bool focusable) {
1201 create_view_called = true;
1202 on_view_created();
1203 fuchsia::ui::composition::ContentId content_id;
1204 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1205 };
1206
1207 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1208 .SetFocuser(std::move(focuser_handle))
1209 .SetCreateViewCallback(on_create_view)
1210 .Build();
1211
1212 auto base_view = static_cast<flutter::PlatformView*>(&platform_view);
1213 EXPECT_TRUE(base_view);
1214
1215 uint64_t view_id = 42;
1216
1217 std::ostringstream focus_message;
1218 focus_message << "{" << " \"method\":\"View.focus.requestById\","
1219 << " \"args\": {" << " \"viewId\":" << view_id
1220 << " }" << "}";
1221
1222 // Dispatch the plaform message request.
1223 auto focus_response = FakePlatformMessageResponse::Create();
1224 base_view->HandlePlatformMessage(focus_response->WithMessage(
1225 "flutter/platform_views", focus_message.str()));
1226 RunLoopUntilIdle();
1227
1228 focus_response->ExpectCompleted("[1]");
1229 EXPECT_FALSE(focuser.request_focus_called());
1230}

◆ TEST_F() [33/54]

flutter_runner::testing::TEST_F ( PlatformViewTests  ,
RequestFocusTest   
)

Definition at line 1111 of file platform_view_unittest.cc.

1111 {
1112 MockPlatformViewDelegate delegate;
1113 flutter::TaskRunners task_runners =
1114 flutter::TaskRunners("test_runners", // label
1116 async_get_default_dispatcher()), // platform
1117 nullptr, // raster
1118 nullptr, // ui
1119 nullptr // io
1120 );
1121
1122 FakeFocuser focuser;
1123 fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
1124 auto focuser_handle = focuser_bindings.AddBinding(&focuser);
1125
1126 bool create_view_called = false;
1127 auto on_create_view = [&create_view_called, this](
1128 int64_t view_id,
1129 flutter_runner::ViewCallback on_view_created,
1131 bool hit_testable, bool focusable) {
1132 create_view_called = true;
1133 on_view_created();
1134 fuchsia::ui::composition::ContentId content_id;
1135 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1136 };
1137
1138 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1139 .SetFocuser(std::move(focuser_handle))
1140 .SetCreateViewCallback(on_create_view)
1141 .Build();
1142
1143 // Cast platform_view to its base view so we can have access to the public
1144 // "HandlePlatformMessage" function.
1145 auto base_view = static_cast<flutter::PlatformView*>(&platform_view);
1146 EXPECT_TRUE(base_view);
1147
1148 uint64_t view_id = 42;
1149
1150 std::ostringstream create_message;
1151 create_message << "{" << " \"method\":\"View.create\","
1152 << " \"args\": {" << " \"viewId\":" << view_id << ","
1153 << " \"hitTestable\":true,"
1154 << " \"focusable\":true" << " }" << "}";
1155
1156 // Dispatch the plaform message request.
1157 auto create_response = FakePlatformMessageResponse::Create();
1158 base_view->HandlePlatformMessage(create_response->WithMessage(
1159 "flutter/platform_views", create_message.str()));
1160
1161 RunLoopUntilIdle();
1162
1163 // JSON for the message to be passed into the PlatformView.
1164 std::ostringstream focus_message;
1165 focus_message << "{" << " \"method\":\"View.focus.requestById\","
1166 << " \"args\": {" << " \"viewId\":" << view_id
1167 << " }" << "}";
1168
1169 // Dispatch the plaform message request.
1170 auto focus_response = FakePlatformMessageResponse::Create();
1171 base_view->HandlePlatformMessage(focus_response->WithMessage(
1172 "flutter/platform_views", focus_message.str()));
1173 RunLoopUntilIdle();
1174
1175 focus_response->ExpectCompleted("[0]");
1177}

◆ TEST_F() [34/54]

flutter_runner::testing::TEST_F ( PlatformViewTests  ,
SetViewportMetrics   
)

Definition at line 676 of file platform_view_unittest.cc.

676 {
677 constexpr float kDPR = 2;
678 constexpr uint32_t width = 640;
679 constexpr uint32_t height = 480;
680
681 MockPlatformViewDelegate delegate;
682 EXPECT_EQ(delegate.metrics(), flutter::ViewportMetrics());
683
684 MockParentViewportWatcher watcher;
685 flutter::TaskRunners task_runners("test_runners", nullptr, nullptr, nullptr,
686 nullptr);
687 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
688 .SetParentViewportWatcher(watcher.GetHandle())
689 .Build();
690 RunLoopUntilIdle();
691 EXPECT_EQ(delegate.metrics(), flutter::ViewportMetrics());
692
693 watcher.SetLayout(width, height, kDPR);
694 RunLoopUntilIdle();
695 EXPECT_EQ(delegate.metrics(),
696 flutter::ViewportMetrics(kDPR, std::round(width * kDPR),
697 std::round(height * kDPR), -1.0, 0));
698}

◆ TEST_F() [35/54]

flutter_runner::testing::TEST_F ( PlatformViewTests  ,
TouchSourceLogicalToPhysicalConversion   
)

Definition at line 1472 of file platform_view_unittest.cc.

1472 {
1473 constexpr uint32_t width = 640;
1474 constexpr uint32_t height = 480;
1475 constexpr std::array<std::array<float, 2>, 2> kRect = {
1476 {{0, 0}, {width, height}}};
1477 constexpr std::array<float, 9> kIdentity = {1, 0, 0, 0, 1, 0, 0, 0, 1};
1478 constexpr fuchsia::ui::pointer::TouchInteractionId kIxnOne = {
1479 .device_id = 0u, .pointer_id = 1u, .interaction_id = 2u};
1480
1481 MockPlatformViewDelegate delegate;
1482 flutter::TaskRunners task_runners("test_runners", nullptr, nullptr, nullptr,
1483 nullptr);
1484
1485 MockParentViewportWatcher viewport_watcher;
1486 FakeTouchSource touch_server;
1487 fidl::BindingSet<fuchsia::ui::pointer::TouchSource> touch_bindings;
1488 auto touch_handle = touch_bindings.AddBinding(&touch_server);
1489 auto platform_view =
1490 PlatformViewBuilder(delegate, std::move(task_runners))
1491 .SetParentViewportWatcher(viewport_watcher.GetHandle())
1492 .SetTouchSource(std::move(touch_handle))
1493 .Build();
1494 RunLoopUntilIdle();
1495 EXPECT_EQ(delegate.pointer_packets().size(), 0u);
1496
1497 viewport_watcher.SetLayout(width, height);
1498 RunLoopUntilIdle();
1499 EXPECT_EQ(delegate.metrics(),
1501
1502 // Inject
1503 std::vector<fuchsia::ui::pointer::TouchEvent> events =
1504 TouchEventBuilder::New()
1505 .AddTime(/* in nanoseconds */ 1111789u)
1506 .AddViewParameters(kRect, kRect, kIdentity)
1507 .AddSample(kIxnOne, fuchsia::ui::pointer::EventPhase::ADD,
1508 {width / 2, height / 2})
1509 .AddResult(
1510 {.interaction = kIxnOne,
1511 .status = fuchsia::ui::pointer::TouchInteractionStatus::GRANTED})
1512 .BuildAsVector();
1513 touch_server.ScheduleCallback(std::move(events));
1514 RunLoopUntilIdle();
1515
1516 // Unpack
1517 std::vector<std::unique_ptr<flutter::PointerDataPacket>> packets =
1518 delegate.TakePointerDataPackets();
1519 ASSERT_EQ(packets.size(), 1u);
1520 std::vector<flutter::PointerData> flutter_events;
1521 UnpackPointerPacket(flutter_events, std::move(packets[0]));
1522
1523 // Examine phases
1524 ASSERT_EQ(flutter_events.size(), 2u);
1525 EXPECT_EQ(flutter_events[0].change, flutter::PointerData::Change::kAdd);
1526 EXPECT_EQ(flutter_events[1].change, flutter::PointerData::Change::kDown);
1527
1528 // Examine coordinates
1529 EXPECT_EQ(flutter_events[0].physical_x, width / 2);
1530 EXPECT_EQ(flutter_events[0].physical_y, height / 2);
1531 EXPECT_EQ(flutter_events[1].physical_x, width / 2);
1532 EXPECT_EQ(flutter_events[1].physical_y, height / 2);
1533}
constexpr SkRect kRect
void UnpackPointerPacket(std::vector< PointerData > &output, std::unique_ptr< PointerDataPacket > packet)
constexpr std::array< float, 9 > kIdentity
constexpr fup_TouchIxnId kIxnOne

◆ TEST_F() [36/54]

flutter_runner::testing::TEST_F ( PlatformViewTests  ,
UpdateViewTest   
)

Definition at line 845 of file platform_view_unittest.cc.

845 {
846 MockPlatformViewDelegate delegate;
847 flutter::TaskRunners task_runners =
848 flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
849
850 std::optional<SkRect> occlusion_hint_for_test;
851 std::optional<bool> hit_testable_for_test;
852 std::optional<bool> focusable_for_test;
853 auto UpdateViewCallback = [&occlusion_hint_for_test, &hit_testable_for_test,
854 &focusable_for_test](
855 int64_t view_id, SkRect occlusion_hint,
856 bool hit_testable, bool focusable) {
857 occlusion_hint_for_test = occlusion_hint;
858 hit_testable_for_test = hit_testable;
859 focusable_for_test = focusable;
860 };
861
862 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
863 .SetUpdateViewCallback(UpdateViewCallback)
864 .Build();
865
866 // Cast platform_view to its base view so we can have access to the public
867 // "HandlePlatformMessage" function.
868 auto base_view = static_cast<flutter::PlatformView*>(&platform_view);
869 EXPECT_TRUE(base_view);
870
871 // Send a basic message.
872 const uint8_t json[] =
873 "{"
874 " \"method\":\"View.update\","
875 " \"args\": {"
876 " \"viewId\":42,"
877 " \"hitTestable\":true,"
878 " \"focusable\":true"
879 " }"
880 "}";
881 std::unique_ptr<flutter::PlatformMessage> message =
882 std::make_unique<flutter::PlatformMessage>(
883 "flutter/platform_views",
884 fml::MallocMapping::Copy(json, sizeof(json)),
886 base_view->HandlePlatformMessage(std::move(message));
887
888 RunLoopUntilIdle();
889 ASSERT_TRUE(occlusion_hint_for_test.has_value());
890 ASSERT_TRUE(hit_testable_for_test.has_value());
891 ASSERT_TRUE(focusable_for_test.has_value());
892 EXPECT_EQ(occlusion_hint_for_test.value(), SkRect::MakeEmpty());
893 EXPECT_EQ(hit_testable_for_test.value(), true);
894 EXPECT_EQ(focusable_for_test.value(), true);
895
896 // Reset for the next message.
897 occlusion_hint_for_test.reset();
898 hit_testable_for_test.reset();
899 focusable_for_test.reset();
900
901 // Send another basic message.
902 const uint8_t json_false[] =
903 "{"
904 " \"method\":\"View.update\","
905 " \"args\": {"
906 " \"viewId\":42,"
907 " \"hitTestable\":false,"
908 " \"focusable\":false"
909 " }"
910 "}";
911 std::unique_ptr<flutter::PlatformMessage> message_false =
912 std::make_unique<flutter::PlatformMessage>(
913 "flutter/platform_views",
914 fml::MallocMapping::Copy(json_false, sizeof(json_false)),
916 base_view->HandlePlatformMessage(std::move(message_false));
917 RunLoopUntilIdle();
918 ASSERT_TRUE(occlusion_hint_for_test.has_value());
919 ASSERT_TRUE(hit_testable_for_test.has_value());
920 ASSERT_TRUE(focusable_for_test.has_value());
921 EXPECT_EQ(occlusion_hint_for_test.value(), SkRect::MakeEmpty());
922 EXPECT_EQ(hit_testable_for_test.value(), false);
923 EXPECT_EQ(focusable_for_test.value(), false);
924
925 // Reset for the next message.
926 occlusion_hint_for_test.reset();
927 hit_testable_for_test.reset();
928 focusable_for_test.reset();
929
930 // Send a message including an occlusion hint.
931 const uint8_t json_occlusion_hint[] =
932 "{"
933 " \"method\":\"View.update\","
934 " \"args\": {"
935 " \"viewId\":42,"
936 " \"hitTestable\":true,"
937 " \"focusable\":true,"
938 " \"viewOcclusionHintLTRB\":[0.1,0.2,0.3,0.4]"
939 " }"
940 "}";
941 std::unique_ptr<flutter::PlatformMessage> message_occlusion_hint =
942 std::make_unique<flutter::PlatformMessage>(
943 "flutter/platform_views",
944 fml::MallocMapping::Copy(json_occlusion_hint,
945 sizeof(json_occlusion_hint)),
947 base_view->HandlePlatformMessage(std::move(message_occlusion_hint));
948 RunLoopUntilIdle();
949 ASSERT_TRUE(occlusion_hint_for_test.has_value());
950 ASSERT_TRUE(hit_testable_for_test.has_value());
951 ASSERT_TRUE(focusable_for_test.has_value());
952 EXPECT_EQ(occlusion_hint_for_test.value(),
953 SkRect::MakeLTRB(0.1, 0.2, 0.3, 0.4));
954 EXPECT_EQ(hit_testable_for_test.value(), true);
955 EXPECT_EQ(focusable_for_test.value(), true);
956}
static constexpr SkRect MakeEmpty()
Definition SkRect.h:595

◆ TEST_F() [37/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
Coordinates_CorrectMapping   
)

Definition at line 187 of file pointer_delegate_unittests.cc.

187 {
188 std::optional<std::vector<flutter::PointerData>> pointers;
189 pointer_delegate_->WatchLoop(
190 [&pointers](std::vector<flutter::PointerData> events) {
191 pointers = std::move(events);
192 });
193 RunLoopUntilIdle(); // Server gets watch call.
194
195 // Fuchsia ADD event, with a view parameter that maps the viewport identically
196 // to the view. Then the center point of the viewport should map to the center
197 // of the view, (10.f, 10.f).
198 std::vector<fup_TouchEvent> events =
199 TouchEventBuilder::New()
200 .AddTime(2222000u)
201 .AddViewParameters(/*view*/ {{{0, 0}, {20, 20}}},
202 /*viewport*/ {{{0, 0}, {20, 20}}},
203 /*matrix*/ {1, 0, 0, 0, 1, 0, 0, 0, 1})
204 .AddSample(kIxnOne, fup_EventPhase::ADD, {10.f, 10.f})
205 .AddResult(
206 {.interaction = kIxnOne, .status = fup_TouchIxnStatus::GRANTED})
207 .BuildAsVector();
208 touch_source_->ScheduleCallback(std::move(events));
209 RunLoopUntilIdle();
210
211 ASSERT_TRUE(pointers.has_value());
212 ASSERT_EQ(pointers->size(), 2u); // ADD - DOWN
213 EXPECT_FLOAT_EQ((*pointers)[0].physical_x, 10.f);
214 EXPECT_FLOAT_EQ((*pointers)[0].physical_y, 10.f);
215 pointers = {};
216
217 // Fuchsia CHANGE event, with a view parameter that translates the viewport by
218 // (10, 10) within the view. Then the minimal point in the viewport (its
219 // origin) should map to the center of the view, (10.f, 10.f).
220 events = TouchEventBuilder::New()
221 .AddTime(2222000u)
222 .AddViewParameters(/*view*/ {{{0, 0}, {20, 20}}},
223 /*viewport*/ {{{0, 0}, {20, 20}}},
224 /*matrix*/ {1, 0, 0, 0, 1, 0, 10, 10, 1})
225 .AddSample(kIxnOne, fup_EventPhase::CHANGE, {0.f, 0.f})
226 .BuildAsVector();
227 touch_source_->ScheduleCallback(std::move(events));
228 RunLoopUntilIdle();
229
230 ASSERT_TRUE(pointers.has_value());
231 ASSERT_EQ(pointers->size(), 1u); // MOVE
232 EXPECT_FLOAT_EQ((*pointers)[0].physical_x, 10.f);
233 EXPECT_FLOAT_EQ((*pointers)[0].physical_y, 10.f);
234
235 // Fuchsia CHANGE event, with a view parameter that scales the viewport by
236 // (0.5, 0.5) within the view. Then the maximal point in the viewport should
237 // map to the center of the view, (10.f, 10.f).
238 events = TouchEventBuilder::New()
239 .AddTime(2222000u)
240 .AddViewParameters(/*view*/ {{{0, 0}, {20, 20}}},
241 /*viewport*/ {{{0, 0}, {20, 20}}},
242 /*matrix*/ {0.5f, 0, 0, 0, 0.5f, 0, 0, 0, 1})
243 .AddSample(kIxnOne, fup_EventPhase::CHANGE, {20.f, 20.f})
244 .BuildAsVector();
245 touch_source_->ScheduleCallback(std::move(events));
246 RunLoopUntilIdle();
247
248 ASSERT_TRUE(pointers.has_value());
249 ASSERT_EQ(pointers->size(), 1u); // MOVE
250 EXPECT_FLOAT_EQ((*pointers)[0].physical_x, 10.f);
251 EXPECT_FLOAT_EQ((*pointers)[0].physical_y, 10.f);
252}

◆ TEST_F() [38/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
Coordinates_DownEventClampedToView   
)

Definition at line 254 of file pointer_delegate_unittests.cc.

254 {
255 const float kSmallDiscrepancy = -0.00003f;
256
257 std::optional<std::vector<flutter::PointerData>> pointers;
258 pointer_delegate_->WatchLoop(
259 [&pointers](std::vector<flutter::PointerData> events) {
260 pointers = std::move(events);
261 });
262 RunLoopUntilIdle(); // Server gets watch call.
263
264 std::vector<fup_TouchEvent> events =
265 TouchEventBuilder::New()
266 .AddTime(1111000u)
267 .AddViewParameters(kRect, kRect, kIdentity)
268 .AddSample(kIxnOne, fup_EventPhase::ADD, {10.f, kSmallDiscrepancy})
269 .AddResult(
270 {.interaction = kIxnOne, .status = fup_TouchIxnStatus::GRANTED})
271 .BuildAsVector();
272 touch_source_->ScheduleCallback(std::move(events));
273 RunLoopUntilIdle();
274
275 ASSERT_TRUE(pointers.has_value());
276 ASSERT_EQ(pointers->size(), 2u);
277
278 const auto& add_event = (*pointers)[0];
279 EXPECT_FLOAT_EQ(add_event.physical_x, 10.f);
280 EXPECT_FLOAT_EQ(add_event.physical_y, kSmallDiscrepancy);
281
282 const auto& down_event = (*pointers)[1];
283 EXPECT_FLOAT_EQ(down_event.physical_x, 10.f);
284 EXPECT_EQ(down_event.physical_y, 0.f);
285}

◆ TEST_F() [39/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
Data_FuchsiaTimeVersusFlutterTime   
)

Definition at line 72 of file pointer_delegate_unittests.cc.

72 {
73 std::optional<std::vector<flutter::PointerData>> pointers;
74 pointer_delegate_->WatchLoop(
75 [&pointers](std::vector<flutter::PointerData> events) {
76 pointers = std::move(events);
77 });
78 RunLoopUntilIdle(); // Server gets watch call.
79
80 // Fuchsia ADD -> Flutter ADD+DOWN
81 std::vector<fup_TouchEvent> events =
82 TouchEventBuilder::New()
83 .AddTime(/* in nanoseconds */ 1111789u)
84 .AddViewParameters(kRect, kRect, kIdentity)
85 .AddSample(kIxnOne, fup_EventPhase::ADD, {10.f, 10.f})
86 .AddResult(
87 {.interaction = kIxnOne, .status = fup_TouchIxnStatus::GRANTED})
88 .BuildAsVector();
89 touch_source_->ScheduleCallback(std::move(events));
90 RunLoopUntilIdle();
91
92 ASSERT_TRUE(pointers.has_value());
93 ASSERT_EQ(pointers->size(), 2u);
94 EXPECT_EQ((*pointers)[0].time_stamp, /* in microseconds */ 1111u);
95 EXPECT_EQ((*pointers)[1].time_stamp, /* in microseconds */ 1111u);
96}

◆ TEST_F() [40/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
MouseWheel_PixelBased   
)

Definition at line 738 of file pointer_delegate_unittests.cc.

738 {
739 std::optional<std::vector<flutter::PointerData>> pointers;
740 pointer_delegate_->WatchLoop(
741 [&pointers](std::vector<flutter::PointerData> events) {
742 pointers = std::move(events);
743 });
744 RunLoopUntilIdle(); // Server gets watch call.
745
746 std::vector<fup_MouseEvent> events =
747 MouseEventBuilder()
748 .AddTime(1111789u)
749 .AddViewParameters(kRect, kRect, kIdentity)
750 .AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {0, 1}, {0, 120},
752 .AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2})
753 .BuildAsVector();
754 mouse_source_->ScheduleCallback(std::move(events));
755 RunLoopUntilIdle();
756
757 ASSERT_TRUE(pointers.has_value());
758 ASSERT_EQ(pointers.value().size(), 1u);
759 EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kHover);
760 EXPECT_EQ(pointers.value()[0].signal_kind,
762 EXPECT_EQ(pointers.value()[0].kind, flutter::PointerData::DeviceKind::kMouse);
763 EXPECT_EQ(pointers.value()[0].buttons, 0);
764 EXPECT_EQ(pointers.value()[0].scroll_delta_x, 0);
765 EXPECT_EQ(pointers.value()[0].scroll_delta_y, -120);
766 pointers = {};
767
768 // receive a horizontal scroll
769 events = MouseEventBuilder()
770 .AddTime(1111789u)
771 .AddViewParameters(kRect, kRect, kIdentity)
772 .AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {1, 0}, {120, 0},
774 .AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2})
775 .BuildAsVector();
776 mouse_source_->ScheduleCallback(std::move(events));
777 RunLoopUntilIdle();
778
779 ASSERT_TRUE(pointers.has_value());
780 ASSERT_EQ(pointers.value().size(), 1u);
781 EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kHover);
782 EXPECT_EQ(pointers.value()[0].signal_kind,
784 EXPECT_EQ(pointers.value()[0].kind, flutter::PointerData::DeviceKind::kMouse);
785 EXPECT_EQ(pointers.value()[0].buttons, 0);
786 EXPECT_EQ(pointers.value()[0].scroll_delta_x, 120);
787 EXPECT_EQ(pointers.value()[0].scroll_delta_y, 0);
788 pointers = {};
789}

◆ TEST_F() [41/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
MouseWheel_TickBased   
)

Definition at line 685 of file pointer_delegate_unittests.cc.

685 {
686 std::optional<std::vector<flutter::PointerData>> pointers;
687 pointer_delegate_->WatchLoop(
688 [&pointers](std::vector<flutter::PointerData> events) {
689 pointers = std::move(events);
690 });
691 RunLoopUntilIdle(); // Server gets watch call.
692
693 std::vector<fup_MouseEvent> events =
694 MouseEventBuilder()
695 .AddTime(1111789u)
696 .AddViewParameters(kRect, kRect, kIdentity)
697 .AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {0, 1},
699 .AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2})
700 .BuildAsVector();
701 mouse_source_->ScheduleCallback(std::move(events));
702 RunLoopUntilIdle();
703
704 ASSERT_TRUE(pointers.has_value());
705 ASSERT_EQ(pointers.value().size(), 1u);
706 EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kHover);
707 EXPECT_EQ(pointers.value()[0].signal_kind,
709 EXPECT_EQ(pointers.value()[0].kind, flutter::PointerData::DeviceKind::kMouse);
710 EXPECT_EQ(pointers.value()[0].buttons, 0);
711 EXPECT_EQ(pointers.value()[0].scroll_delta_x, 0);
712 EXPECT_EQ(pointers.value()[0].scroll_delta_y, -20);
713 pointers = {};
714
715 // receive a horizontal scroll
716 events = MouseEventBuilder()
717 .AddTime(1111789u)
718 .AddViewParameters(kRect, kRect, kIdentity)
719 .AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {1, 0},
721 .AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2})
722 .BuildAsVector();
723 mouse_source_->ScheduleCallback(std::move(events));
724 RunLoopUntilIdle();
725
726 ASSERT_TRUE(pointers.has_value());
727 ASSERT_EQ(pointers.value().size(), 1u);
728 EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kHover);
729 EXPECT_EQ(pointers.value()[0].signal_kind,
731 EXPECT_EQ(pointers.value()[0].kind, flutter::PointerData::DeviceKind::kMouse);
732 EXPECT_EQ(pointers.value()[0].buttons, 0);
733 EXPECT_EQ(pointers.value()[0].scroll_delta_x, 20);
734 EXPECT_EQ(pointers.value()[0].scroll_delta_y, 0);
735 pointers = {};
736}
constexpr std::array< int64_t, 2 > kNoScrollInPhysicalPixelDelta

◆ TEST_F() [42/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
MouseWheel_TouchpadPixelBased   
)

Definition at line 791 of file pointer_delegate_unittests.cc.

791 {
792 std::optional<std::vector<flutter::PointerData>> pointers;
793 pointer_delegate_->WatchLoop(
794 [&pointers](std::vector<flutter::PointerData> events) {
795 pointers = std::move(events);
796 });
797 RunLoopUntilIdle(); // Server gets watch call.
798
799 std::vector<fup_MouseEvent> events =
800 MouseEventBuilder()
801 .AddTime(1111789u)
802 .AddViewParameters(kRect, kRect, kIdentity)
803 .AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {0, 1}, {0, 120},
805 .AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2})
806 .BuildAsVector();
807 mouse_source_->ScheduleCallback(std::move(events));
808 RunLoopUntilIdle();
809
810 ASSERT_TRUE(pointers.has_value());
811 ASSERT_EQ(pointers.value().size(), 1u);
812 EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kHover);
813 EXPECT_EQ(pointers.value()[0].signal_kind,
815 EXPECT_EQ(pointers.value()[0].kind, flutter::PointerData::DeviceKind::kMouse);
816 EXPECT_EQ(pointers.value()[0].buttons, 0);
817 EXPECT_EQ(pointers.value()[0].scroll_delta_x, 0);
818 EXPECT_EQ(pointers.value()[0].scroll_delta_y, -120);
819 pointers = {};
820
821 // receive a horizontal scroll
822 events = MouseEventBuilder()
823 .AddTime(1111789u)
824 .AddViewParameters(kRect, kRect, kIdentity)
825 .AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {1, 0}, {120, 0},
827 .AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2})
828 .BuildAsVector();
829 mouse_source_->ScheduleCallback(std::move(events));
830 RunLoopUntilIdle();
831
832 ASSERT_TRUE(pointers.has_value());
833 ASSERT_EQ(pointers.value().size(), 1u);
834 EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kHover);
835 EXPECT_EQ(pointers.value()[0].signal_kind,
837 EXPECT_EQ(pointers.value()[0].kind, flutter::PointerData::DeviceKind::kMouse);
838 EXPECT_EQ(pointers.value()[0].buttons, 0);
839 EXPECT_EQ(pointers.value()[0].scroll_delta_x, 120);
840 EXPECT_EQ(pointers.value()[0].scroll_delta_y, 0);
841 pointers = {};
842}

◆ TEST_F() [43/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
Phase_FlutterPhasesAreSynthesized   
)

Definition at line 98 of file pointer_delegate_unittests.cc.

98 {
99 std::optional<std::vector<flutter::PointerData>> pointers;
100 pointer_delegate_->WatchLoop(
101 [&pointers](std::vector<flutter::PointerData> events) {
102 pointers = std::move(events);
103 });
104 RunLoopUntilIdle(); // Server gets watch call.
105
106 // Fuchsia ADD -> Flutter ADD+DOWN
107 std::vector<fup_TouchEvent> events =
108 TouchEventBuilder::New()
109 .AddTime(1111000u)
110 .AddViewParameters(kRect, kRect, kIdentity)
111 .AddSample(kIxnOne, fup_EventPhase::ADD, {10.f, 10.f})
112 .AddResult(
113 {.interaction = kIxnOne, .status = fup_TouchIxnStatus::GRANTED})
114 .BuildAsVector();
115 touch_source_->ScheduleCallback(std::move(events));
116 RunLoopUntilIdle();
117
118 ASSERT_TRUE(pointers.has_value());
119 ASSERT_EQ(pointers->size(), 2u);
120 EXPECT_EQ((*pointers)[0].change, flutter::PointerData::Change::kAdd);
121 EXPECT_EQ((*pointers)[1].change, flutter::PointerData::Change::kDown);
122
123 // Fuchsia CHANGE -> Flutter MOVE
124 events = TouchEventBuilder::New()
125 .AddTime(2222000u)
126 .AddSample(kIxnOne, fup_EventPhase::CHANGE, {10.f, 10.f})
127 .BuildAsVector();
128 touch_source_->ScheduleCallback(std::move(events));
129 RunLoopUntilIdle();
130
131 ASSERT_TRUE(pointers.has_value());
132 ASSERT_EQ(pointers->size(), 1u);
133 EXPECT_EQ((*pointers)[0].change, flutter::PointerData::Change::kMove);
134
135 // Fuchsia REMOVE -> Flutter UP+REMOVE
136 events = TouchEventBuilder::New()
137 .AddTime(3333000u)
138 .AddSample(kIxnOne, fup_EventPhase::REMOVE, {10.f, 10.f})
139 .BuildAsVector();
140 touch_source_->ScheduleCallback(std::move(events));
141 RunLoopUntilIdle();
142
143 ASSERT_TRUE(pointers.has_value());
144 ASSERT_EQ(pointers->size(), 2u);
145 EXPECT_EQ((*pointers)[0].change, flutter::PointerData::Change::kUp);
146 EXPECT_EQ((*pointers)[1].change, flutter::PointerData::Change::kRemove);
147}

◆ TEST_F() [44/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
Phase_FuchsiaCancelBecomesFlutterCancel   
)

Definition at line 149 of file pointer_delegate_unittests.cc.

149 {
150 std::optional<std::vector<flutter::PointerData>> pointers;
151 pointer_delegate_->WatchLoop(
152 [&pointers](std::vector<flutter::PointerData> events) {
153 pointers = std::move(events);
154 });
155 RunLoopUntilIdle(); // Server gets watch call.
156
157 // Fuchsia ADD -> Flutter ADD+DOWN
158 std::vector<fup_TouchEvent> events =
159 TouchEventBuilder::New()
160 .AddTime(1111000u)
161 .AddViewParameters(kRect, kRect, kIdentity)
162 .AddSample(kIxnOne, fup_EventPhase::ADD, {10.f, 10.f})
163 .AddResult(
164 {.interaction = kIxnOne, .status = fup_TouchIxnStatus::GRANTED})
165 .BuildAsVector();
166 touch_source_->ScheduleCallback(std::move(events));
167 RunLoopUntilIdle();
168
169 ASSERT_TRUE(pointers.has_value());
170 ASSERT_EQ(pointers->size(), 2u);
171 EXPECT_EQ((*pointers)[0].change, flutter::PointerData::Change::kAdd);
172 EXPECT_EQ((*pointers)[1].change, flutter::PointerData::Change::kDown);
173
174 // Fuchsia CANCEL -> Flutter CANCEL
175 events = TouchEventBuilder::New()
176 .AddTime(2222000u)
177 .AddSample(kIxnOne, fup_EventPhase::CANCEL, {10.f, 10.f})
178 .BuildAsVector();
179 touch_source_->ScheduleCallback(std::move(events));
180 RunLoopUntilIdle();
181
182 ASSERT_TRUE(pointers.has_value());
183 ASSERT_EQ(pointers->size(), 1u);
184 EXPECT_EQ((*pointers)[0].change, flutter::PointerData::Change::kCancel);
185}

◆ TEST_F() [45/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
Protocol_EarlyGrant   
)

Definition at line 479 of file pointer_delegate_unittests.cc.

479 {
480 std::optional<std::vector<flutter::PointerData>> pointers;
481 pointer_delegate_->WatchLoop(
482 [&pointers](std::vector<flutter::PointerData> events) {
483 pointers = std::move(events);
484 });
485 RunLoopUntilIdle(); // Server gets watch call.
486
487 // Fuchsia ADD, with grant result - release immediately.
488 std::vector<fup_TouchEvent> events =
489 TouchEventBuilder::New()
490 .AddTime(1111000u)
491 .AddViewParameters(kRect, kRect, kIdentity)
492 .AddSample(kIxnOne, fup_EventPhase::ADD, {10.f, 10.f})
493 .AddResult({kIxnOne, fup_TouchIxnStatus::GRANTED})
494 .BuildAsVector();
495 touch_source_->ScheduleCallback(std::move(events));
496 RunLoopUntilIdle();
497
498 ASSERT_TRUE(pointers.has_value());
499 ASSERT_EQ(pointers.value().size(), 2u);
500 EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kAdd);
501 EXPECT_EQ(pointers.value()[1].change, flutter::PointerData::Change::kDown);
502 pointers = {};
503
504 // Fuchsia CHANGE, after grant result - release immediately.
505 events = TouchEventBuilder::New()
506 .AddTime(2222000u)
507 .AddSample(kIxnOne, fup_EventPhase::CHANGE, {10.f, 10.f})
508 .BuildAsVector();
509 touch_source_->ScheduleCallback(std::move(events));
510 RunLoopUntilIdle();
511
512 ASSERT_TRUE(pointers.has_value());
513 ASSERT_EQ(pointers.value().size(), 1u);
514 EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kMove);
515 pointers = {};
516}

◆ TEST_F() [46/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
Protocol_FirstResponseIsEmpty   
)

Definition at line 287 of file pointer_delegate_unittests.cc.

287 {
288 bool called = false;
289 pointer_delegate_->WatchLoop(
290 [&called](std::vector<flutter::PointerData> events) { called = true; });
291 RunLoopUntilIdle(); // Server gets Watch call.
292
293 EXPECT_FALSE(called); // No events yet received to forward to client.
294 // Server sees an initial "response" from client, which is empty, by contract.
295 const auto responses = touch_source_->UploadedResponses();
296 ASSERT_TRUE(responses.has_value());
297 ASSERT_EQ(responses->size(), 0u);
298}

◆ TEST_F() [47/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
Protocol_LateDeny   
)

Definition at line 518 of file pointer_delegate_unittests.cc.

518 {
519 std::optional<std::vector<flutter::PointerData>> pointers;
520 pointer_delegate_->WatchLoop(
521 [&pointers](std::vector<flutter::PointerData> events) {
522 pointers = std::move(events);
523 });
524 RunLoopUntilIdle(); // Server gets watch call.
525
526 // Fuchsia ADD, no grant result - buffer it.
527 std::vector<fup_TouchEvent> events =
528 TouchEventBuilder::New()
529 .AddTime(1111000u)
530 .AddViewParameters(kRect, kRect, kIdentity)
531 .AddSample(kIxnOne, fup_EventPhase::ADD, {10.f, 10.f})
532 .BuildAsVector();
533 touch_source_->ScheduleCallback(std::move(events));
534 RunLoopUntilIdle();
535
536 ASSERT_TRUE(pointers.has_value());
537 EXPECT_EQ(pointers.value().size(), 0u);
538 pointers = {};
539
540 // Fuchsia CHANGE, no grant result - buffer it.
541 events = TouchEventBuilder::New()
542 .AddTime(2222000u)
543 .AddSample(kIxnOne, fup_EventPhase::CHANGE, {10.f, 10.f})
544 .BuildAsVector();
545 touch_source_->ScheduleCallback(std::move(events));
546 RunLoopUntilIdle();
547
548 ASSERT_TRUE(pointers.has_value());
549 EXPECT_EQ(pointers.value().size(), 0u);
550 pointers = {};
551
552 // Fuchsia result: ownership denied. Buffered pointers deleted.
553 events = TouchEventBuilder::New()
554 .AddTime(3333000u)
555 .AddResult({kIxnOne, fup_TouchIxnStatus::DENIED})
556 .BuildAsVector();
557 touch_source_->ScheduleCallback(std::move(events));
558 RunLoopUntilIdle();
559
560 ASSERT_TRUE(pointers.has_value());
561 ASSERT_EQ(pointers.value().size(), 0u); // Do not release to client!
562 pointers = {};
563}

◆ TEST_F() [48/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
Protocol_LateDenyCombo   
)

Definition at line 565 of file pointer_delegate_unittests.cc.

565 {
566 std::optional<std::vector<flutter::PointerData>> pointers;
567 pointer_delegate_->WatchLoop(
568 [&pointers](std::vector<flutter::PointerData> events) {
569 pointers = std::move(events);
570 });
571 RunLoopUntilIdle(); // Server gets watch call.
572
573 // Fuchsia ADD, no grant result - buffer it.
574 std::vector<fup_TouchEvent> events =
575 TouchEventBuilder::New()
576 .AddTime(1111000u)
577 .AddViewParameters(kRect, kRect, kIdentity)
578 .AddSample(kIxnOne, fup_EventPhase::ADD, {10.f, 10.f})
579 .BuildAsVector();
580 touch_source_->ScheduleCallback(std::move(events));
581 RunLoopUntilIdle();
582
583 ASSERT_TRUE(pointers.has_value());
584 EXPECT_EQ(pointers.value().size(), 0u);
585 pointers = {};
586
587 // Fuchsia CHANGE, no grant result - buffer it.
588 events = TouchEventBuilder::New()
589 .AddTime(2222000u)
590 .AddSample(kIxnOne, fup_EventPhase::CHANGE, {10.f, 10.f})
591 .BuildAsVector();
592 touch_source_->ScheduleCallback(std::move(events));
593 RunLoopUntilIdle();
594
595 ASSERT_TRUE(pointers.has_value());
596 EXPECT_EQ(pointers.value().size(), 0u);
597 pointers = {};
598
599 // Fuchsia result: ownership denied. Buffered pointers deleted.
600 events = TouchEventBuilder::New()
601 .AddTime(3333000u)
602 .AddSample(kIxnOne, fup_EventPhase::CANCEL, {10.f, 10.f})
603 .AddResult({kIxnOne, fup_TouchIxnStatus::DENIED})
604 .BuildAsVector();
605 touch_source_->ScheduleCallback(std::move(events));
606 RunLoopUntilIdle();
607
608 ASSERT_TRUE(pointers.has_value());
609 ASSERT_EQ(pointers.value().size(), 0u); // Do not release to client!
610 pointers = {};
611}

◆ TEST_F() [49/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
Protocol_LateGrant   
)

Definition at line 359 of file pointer_delegate_unittests.cc.

359 {
360 std::optional<std::vector<flutter::PointerData>> pointers;
361 pointer_delegate_->WatchLoop(
362 [&pointers](std::vector<flutter::PointerData> events) {
363 pointers = std::move(events);
364 });
365 RunLoopUntilIdle(); // Server gets watch call.
366
367 // Fuchsia ADD, no grant result - buffer it.
368 std::vector<fup_TouchEvent> events =
369 TouchEventBuilder::New()
370 .AddTime(1111000u)
371 .AddViewParameters(kRect, kRect, kIdentity)
372 .AddSample(kIxnOne, fup_EventPhase::ADD, {10.f, 10.f})
373 .BuildAsVector();
374 touch_source_->ScheduleCallback(std::move(events));
375 RunLoopUntilIdle();
376
377 ASSERT_TRUE(pointers.has_value());
378 EXPECT_EQ(pointers.value().size(), 0u);
379 pointers = {};
380
381 // Fuchsia CHANGE, no grant result - buffer it.
382 events = TouchEventBuilder::New()
383 .AddTime(2222000u)
384 .AddSample(kIxnOne, fup_EventPhase::CHANGE, {10.f, 10.f})
385 .BuildAsVector();
386 touch_source_->ScheduleCallback(std::move(events));
387 RunLoopUntilIdle();
388
389 ASSERT_TRUE(pointers.has_value());
390 EXPECT_EQ(pointers.value().size(), 0u);
391 pointers = {};
392
393 // Fuchsia result: ownership granted. Buffered pointers released.
394 events = TouchEventBuilder::New()
395 .AddTime(3333000u)
396 .AddResult({kIxnOne, fup_TouchIxnStatus::GRANTED})
397 .BuildAsVector();
398 touch_source_->ScheduleCallback(std::move(events));
399 RunLoopUntilIdle();
400
401 ASSERT_TRUE(pointers.has_value());
402 ASSERT_EQ(pointers.value().size(), 3u); // ADD - DOWN - MOVE
403 EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kAdd);
404 EXPECT_EQ(pointers.value()[1].change, flutter::PointerData::Change::kDown);
405 EXPECT_EQ(pointers.value()[2].change, flutter::PointerData::Change::kMove);
406 pointers = {};
407
408 // Fuchsia CHANGE, grant result - release immediately.
409 events = TouchEventBuilder::New()
410 .AddTime(/* in nanoseconds */ 4444000u)
411 .AddSample(kIxnOne, fup_EventPhase::CHANGE, {10.f, 10.f})
412 .BuildAsVector();
413 touch_source_->ScheduleCallback(std::move(events));
414 RunLoopUntilIdle();
415
416 ASSERT_TRUE(pointers.has_value());
417 ASSERT_EQ(pointers.value().size(), 1u);
418 EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kMove);
419 EXPECT_EQ(pointers.value()[0].time_stamp, /* in microseconds */ 4444u);
420 pointers = {};
421}

◆ TEST_F() [50/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
Protocol_LateGrantCombo   
)

Definition at line 423 of file pointer_delegate_unittests.cc.

423 {
424 std::optional<std::vector<flutter::PointerData>> pointers;
425 pointer_delegate_->WatchLoop(
426 [&pointers](std::vector<flutter::PointerData> events) {
427 pointers = std::move(events);
428 });
429 RunLoopUntilIdle(); // Server gets watch call.
430
431 // Fuchsia ADD, no grant result - buffer it.
432 std::vector<fup_TouchEvent> events =
433 TouchEventBuilder::New()
434 .AddTime(1111000u)
435 .AddViewParameters(kRect, kRect, kIdentity)
436 .AddSample(kIxnOne, fup_EventPhase::ADD, {10.f, 10.f})
437 .BuildAsVector();
438 touch_source_->ScheduleCallback(std::move(events));
439 RunLoopUntilIdle();
440
441 ASSERT_TRUE(pointers.has_value());
442 EXPECT_EQ(pointers.value().size(), 0u);
443 pointers = {};
444
445 // Fuchsia CHANGE, no grant result - buffer it.
446 events = TouchEventBuilder::New()
447 .AddTime(2222000u)
448 .AddSample(kIxnOne, fup_EventPhase::CHANGE, {10.f, 10.f})
449 .BuildAsVector();
450 touch_source_->ScheduleCallback(std::move(events));
451 RunLoopUntilIdle();
452
453 ASSERT_TRUE(pointers.has_value());
454 EXPECT_EQ(pointers.value().size(), 0u);
455 pointers = {};
456
457 // Fuchsia CHANGE, with grant result - release buffered events.
458 events = TouchEventBuilder::New()
459 .AddTime(3333000u)
460 .AddSample(kIxnOne, fup_EventPhase::CHANGE, {10.f, 10.f})
461 .AddResult({kIxnOne, fup_TouchIxnStatus::GRANTED})
462 .BuildAsVector();
463 touch_source_->ScheduleCallback(std::move(events));
464 RunLoopUntilIdle();
465
466 ASSERT_TRUE(pointers.has_value());
467 ASSERT_EQ(pointers.value().size(), 4u); // ADD - DOWN - MOVE - MOVE
468 EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kAdd);
469 EXPECT_EQ(pointers.value()[0].time_stamp, 1111u);
470 EXPECT_EQ(pointers.value()[1].change, flutter::PointerData::Change::kDown);
471 EXPECT_EQ(pointers.value()[1].time_stamp, 1111u);
472 EXPECT_EQ(pointers.value()[2].change, flutter::PointerData::Change::kMove);
473 EXPECT_EQ(pointers.value()[2].time_stamp, 2222u);
474 EXPECT_EQ(pointers.value()[3].change, flutter::PointerData::Change::kMove);
475 EXPECT_EQ(pointers.value()[3].time_stamp, 3333u);
476 pointers = {};
477}

◆ TEST_F() [51/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
Protocol_PointersAreIndependent   
)

Definition at line 613 of file pointer_delegate_unittests.cc.

613 {
614 std::optional<std::vector<flutter::PointerData>> pointers;
615 pointer_delegate_->WatchLoop(
616 [&pointers](std::vector<flutter::PointerData> events) {
617 pointers = std::move(events);
618 });
619 RunLoopUntilIdle(); // Server gets watch call.
620
621 constexpr fup_TouchIxnId kIxnTwo = {
622 .device_id = 1u, .pointer_id = 2u, .interaction_id = 2u};
623
624 // Fuchsia ptr1 ADD and ptr2 ADD, no grant result for either - buffer them.
625 std::vector<fup_TouchEvent> events =
626 TouchEventBuilder::New()
627 .AddTime(1111000u)
628 .AddViewParameters(kRect, kRect, kIdentity)
629 .AddSample(kIxnOne, fup_EventPhase::ADD, {10.f, 10.f})
630 .BuildAsVector();
631 fup_TouchEvent ptr2 =
632 TouchEventBuilder::New()
633 .AddTime(1111000u)
634 .AddSample(kIxnTwo, fup_EventPhase::ADD, {15.f, 15.f})
635 .Build();
636 events.emplace_back(std::move(ptr2));
637 touch_source_->ScheduleCallback(std::move(events));
638 RunLoopUntilIdle();
639
640 ASSERT_TRUE(pointers.has_value());
641 EXPECT_EQ(pointers.value().size(), 0u);
642 pointers = {};
643
644 // Server grants win to pointer 2.
645 events = TouchEventBuilder::New()
646 .AddTime(2222000u)
647 .AddResult({kIxnTwo, fup_TouchIxnStatus::GRANTED})
648 .BuildAsVector();
649 touch_source_->ScheduleCallback(std::move(events));
650 RunLoopUntilIdle();
651
652 // Note: Fuchsia's device and pointer IDs (both 32 bit) are coerced together
653 // to fit in Flutter's 64-bit device ID. However, Flutter's pointer_identifier
654 // is not set by platform runner code - PointerDataCaptureConverter (PDPC)
655 // sets it.
656 ASSERT_TRUE(pointers.has_value());
657 ASSERT_EQ(pointers.value().size(), 2u);
658 EXPECT_EQ(pointers.value()[0].pointer_identifier, 0); // reserved for PDPC
659 EXPECT_EQ(pointers.value()[0].device, (int64_t)((1ul << 32) | 2u));
660 EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kAdd);
661 EXPECT_EQ(pointers.value()[1].pointer_identifier, 0); // reserved for PDPC
662 EXPECT_EQ(pointers.value()[1].device, (int64_t)((1ul << 32) | 2u));
663 EXPECT_EQ(pointers.value()[1].change, flutter::PointerData::Change::kDown);
664 pointers = {};
665
666 // Server grants win to pointer 1.
667 events = TouchEventBuilder::New()
668 .AddTime(3333000u)
669 .AddResult({kIxnOne, fup_TouchIxnStatus::GRANTED})
670 .BuildAsVector();
671 touch_source_->ScheduleCallback(std::move(events));
672 RunLoopUntilIdle();
673
674 ASSERT_TRUE(pointers.has_value());
675 ASSERT_EQ(pointers.value().size(), 2u);
676 EXPECT_EQ(pointers.value()[0].pointer_identifier, 0); // reserved for PDPC
677 EXPECT_EQ(pointers.value()[0].device, (int64_t)((1ul << 32) | 1u));
678 EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kAdd);
679 EXPECT_EQ(pointers.value()[1].pointer_identifier, 0); // reserved for PDPC
680 EXPECT_EQ(pointers.value()[1].device, (int64_t)((1ul << 32) | 1u));
681 EXPECT_EQ(pointers.value()[1].change, flutter::PointerData::Change::kDown);
682 pointers = {};
683}
Build(configs, env, options)
Definition build.py:232
fuchsia::ui::pointer::TouchEvent fup_TouchEvent

◆ TEST_F() [52/54]

flutter_runner::testing::TEST_F ( PointerDelegateTest  ,
Protocol_ResponseMatchesEarlierEvents   
)

Definition at line 300 of file pointer_delegate_unittests.cc.

300 {
301 std::optional<std::vector<flutter::PointerData>> pointers;
302 pointer_delegate_->WatchLoop(
303 [&pointers](std::vector<flutter::PointerData> events) {
304 pointers = std::move(events);
305 });
306 RunLoopUntilIdle(); // Server gets watch call.
307
308 // Fuchsia view parameter only. Empty response.
309 std::vector<fup_TouchEvent> events =
310 TouchEventBuilder::New()
311 .AddTime(1111000u)
312 .AddViewParameters(kRect, kRect, kIdentity)
313 .BuildAsVector();
314
315 // Fuchsia ptr 1 ADD sample. Yes response.
317 TouchEventBuilder::New()
318 .AddTime(1111000u)
319 .AddViewParameters(kRect, kRect, kIdentity)
320 .AddSample({.device_id = 0u, .pointer_id = 1u, .interaction_id = 3u},
321 fup_EventPhase::ADD, {10.f, 10.f})
322 .Build();
323 events.emplace_back(std::move(e1));
324
325 // Fuchsia ptr 2 ADD sample. Yes response.
326 fup_TouchEvent e2 =
327 TouchEventBuilder::New()
328 .AddTime(1111000u)
329 .AddSample({.device_id = 0u, .pointer_id = 2u, .interaction_id = 3u},
330 fup_EventPhase::ADD, {5.f, 5.f})
331 .Build();
332 events.emplace_back(std::move(e2));
333
334 // Fuchsia ptr 3 ADD sample. Yes response.
335 fup_TouchEvent e3 =
336 TouchEventBuilder::New()
337 .AddTime(1111000u)
338 .AddSample({.device_id = 0u, .pointer_id = 3u, .interaction_id = 3u},
339 fup_EventPhase::ADD, {1.f, 1.f})
340 .Build();
341 events.emplace_back(std::move(e3));
342 touch_source_->ScheduleCallback(std::move(events));
343 RunLoopUntilIdle();
344
345 const auto responses = touch_source_->UploadedResponses();
346 ASSERT_TRUE(responses.has_value());
347 ASSERT_EQ(responses.value().size(), 4u);
348 // Event 0 did not carry a sample, so no response.
349 EXPECT_FALSE(responses.value()[0].has_response_type());
350 // Events 1-3 had a sample, must have a response.
351 EXPECT_TRUE(responses.value()[1].has_response_type());
352 EXPECT_EQ(responses.value()[1].response_type(), fup_TouchResponseType::YES);
353 EXPECT_TRUE(responses.value()[2].has_response_type());
354 EXPECT_EQ(responses.value()[2].response_type(), fup_TouchResponseType::YES);
355 EXPECT_TRUE(responses.value()[3].has_response_type());
356 EXPECT_EQ(responses.value()[3].response_type(), fup_TouchResponseType::YES);
357}
float e1

◆ TEST_F() [53/54]

flutter_runner::testing::TEST_F ( TextDelegateTest  ,
ActivateIme   
)

Definition at line 139 of file text_delegate_unittests.cc.

139 {
140 auto fake_platform_message_response = FakePlatformMessageResponse::Create();
141 {
142 // Initialize the editor. Without this initialization, the protocol code
143 // will crash.
144 const auto set_client_msg = R"(
145 {
146 "method": "TextInput.setClient",
147 "args": [
148 7,
149 {
150 "inputType": {
151 "name": "TextInputType.multiline",
152 "signed":null,
153 "decimal":null
154 },
155 "readOnly": false,
156 "obscureText": false,
157 "autocorrect":true,
158 "smartDashesType":"1",
159 "smartQuotesType":"1",
160 "enableSuggestions":true,
161 "enableInteractiveSelection":true,
162 "actionLabel":null,
163 "inputAction":"TextInputAction.newline",
164 "textCapitalization":"TextCapitalization.none",
165 "keyboardAppearance":"Brightness.dark",
166 "enableIMEPersonalizedLearning":true,
167 "enableDeltaModel":false
168 }
169 ]
170 }
171 )";
172 auto message = fake_platform_message_response->WithMessage(
173 kTextInputChannel, set_client_msg);
174 text_delegate_->HandleFlutterTextInputChannelPlatformMessage(
175 std::move(message));
176 RunLoopUntilIdle();
177 EXPECT_EQ(ime_service_.action_,
178 fuchsia::ui::input::InputMethodAction::NEWLINE);
179 EXPECT_FALSE(ime_service_.IsKeyboardShown());
180 }
181
182 {
183 // Verify that showing keyboard results in the correct platform effect.
184 const auto set_client_msg = R"(
185 {
186 "method": "TextInput.show"
187 }
188 )";
189 auto message = fake_platform_message_response->WithMessage(
190 kTextInputChannel, set_client_msg);
191 text_delegate_->HandleFlutterTextInputChannelPlatformMessage(
192 std::move(message));
193 RunLoopUntilIdle();
194 EXPECT_TRUE(ime_service_.IsKeyboardShown());
195 }
196
197 {
198 // Verify that hiding keyboard results in the correct platform effect.
199 const auto set_client_msg = R"(
200 {
201 "method": "TextInput.hide"
202 }
203 )";
204 auto message = fake_platform_message_response->WithMessage(
205 kTextInputChannel, set_client_msg);
206 text_delegate_->HandleFlutterTextInputChannelPlatformMessage(
207 std::move(message));
208 RunLoopUntilIdle();
209 EXPECT_FALSE(ime_service_.IsKeyboardShown());
210 }
211
212 {
213 // Update the editing state from the Fuchsia platform side.
214 fuchsia::ui::input::TextInputState state = {
215 .revision = 42,
216 .text = "Foo",
217 .selection = fuchsia::ui::input::TextSelection{},
218 .composing = fuchsia::ui::input::TextRange{},
219 };
220 auto input_event = std::make_unique<fuchsia::ui::input::InputEvent>();
221 ime_service_.client_->DidUpdateState(std::move(state),
222 std::move(input_event));
223 RunLoopUntilIdle();
224 EXPECT_EQ(
225 R"({"method":"TextInputClient.updateEditingState","args":[7,{"text":"Foo","selectionBase":0,"selectionExtent":0,"selectionAffinity":"TextAffinity.upstream","selectionIsDirectional":true,"composingBase":-1,"composingExtent":-1}]})",
226 MessageToString(*last_message_));
227 }
228
229 {
230 // Notify Flutter that the action key has been pressed.
231 ime_service_.client_->OnAction(fuchsia::ui::input::InputMethodAction::DONE);
232 RunLoopUntilIdle();
233 EXPECT_EQ(
234 R"({"method":"TextInputClient.performAction","args":[7,"TextInputAction.done"]})",
235 MessageToString(*last_message_));
236 }
237}
AtkStateType state
static NSString *const kTextInputChannel
static std::string MessageToString(PlatformMessage &message)

◆ TEST_F() [54/54]

flutter_runner::testing::TEST_F ( TextDelegateTest  ,
OnAction   
)

Definition at line 242 of file text_delegate_unittests.cc.

242 {
243 {
244 // A sensible key event is converted into a platform message.
245 fuchsia::ui::input3::KeyEvent key_event;
246 *key_event.mutable_type() = fuchsia::ui::input3::KeyEventType::PRESSED;
247 *key_event.mutable_key() = fuchsia::input::Key::A;
248 key_event.mutable_key_meaning()->set_codepoint('a');
249
250 fuchsia::ui::input3::KeyEventStatus status;
251 keyboard_service_.listener_->OnKeyEvent(
252 std::move(key_event), [&status](fuchsia::ui::input3::KeyEventStatus s) {
253 status = std::move(s);
254 });
255 RunLoopUntilIdle();
256 EXPECT_EQ(fuchsia::ui::input3::KeyEventStatus::HANDLED, status);
257 EXPECT_EQ(
258 R"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":97,"modifiers":0})",
259 MessageToString(*last_message_));
260 }
261
262 {
263 // SYNC event is not handled.
264 // This is currently expected, though we may need to change that behavior.
265 fuchsia::ui::input3::KeyEvent key_event;
266 *key_event.mutable_type() = fuchsia::ui::input3::KeyEventType::SYNC;
267
268 fuchsia::ui::input3::KeyEventStatus status;
269 keyboard_service_.listener_->OnKeyEvent(
270 std::move(key_event), [&status](fuchsia::ui::input3::KeyEventStatus s) {
271 status = std::move(s);
272 });
273 RunLoopUntilIdle();
274 EXPECT_EQ(fuchsia::ui::input3::KeyEventStatus::NOT_HANDLED, status);
275 }
276
277 {
278 // CANCEL event is not handled.
279 // This is currently expected, though we may need to change that behavior.
280 fuchsia::ui::input3::KeyEvent key_event;
281 *key_event.mutable_type() = fuchsia::ui::input3::KeyEventType::CANCEL;
282
283 fuchsia::ui::input3::KeyEventStatus status;
284 keyboard_service_.listener_->OnKeyEvent(
285 std::move(key_event), [&status](fuchsia::ui::input3::KeyEventStatus s) {
286 status = std::move(s);
287 });
288 RunLoopUntilIdle();
289 EXPECT_EQ(fuchsia::ui::input3::KeyEventStatus::NOT_HANDLED, status);
290 }
291}
struct MyStruct s
FlutterKeyEvent key_event

◆ TEST_P() [1/8]

flutter_runner::testing::TEST_P ( PointerInjectorDelegateTest  ,
DestroyedViewsDontGetPointerEvents   
)

Definition at line 569 of file pointer_injector_delegate_unittest.cc.

569 {
570 const uint64_t view_id = 1, num_events = 150;
571
572 fuchsia::ui::views::ViewRefControl view_ref_control;
573 fuchsia::ui::views::ViewRef view_ref;
574 auto status = zx::eventpair::create(
575 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
576 ZX_ASSERT(status == ZX_OK);
577 view_ref_control.reference.replace(
578 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
579 &view_ref_control.reference);
580 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
581
582 // Create the view.
583 CreateView(view_id);
584
585 // Inject |num_events| platform messages.
586 for (size_t i = 0; i < num_events; i++) {
587 auto response = FakePlatformMessageResponse::Create();
588
589 EXPECT_TRUE(pointer_injector_delegate_->HandlePlatformMessage(
590 PlatformMessageBuilder().SetViewId(view_id).Build(), response));
591
592 response->ExpectCompleted("[0]");
593 }
594
595 // Destroy the view.
596 pointer_injector_delegate_->OnDestroyView(view_id);
597
598 // The view does not receive |num_events| pointer events as it gets destroyed
599 // before all the pointer events could be dispatched.
600 const zx::duration timeout = zx::sec(1), step = zx::msec(10);
601 EXPECT_FALSE(RunLoopWithTimeoutOrUntil(
602 [this] { return registry_->num_events_received() == num_events; },
603 timeout, step));
604
605 EXPECT_LT(registry_->num_events_received(), num_events);
606}
static int step(int x, SkScalar min, SkScalar max)
Definition BlurTest.cpp:215

◆ TEST_P() [2/8]

flutter_runner::testing::TEST_P ( PointerInjectorDelegateTest  ,
DeviceRetriesRegisterWhenClosed   
)

Definition at line 668 of file pointer_injector_delegate_unittest.cc.

668 {
669 const uint64_t view_id = 1;
670 const int pointer_id = 1;
671 fuchsia::ui::views::ViewRefControl view_ref_control;
672 fuchsia::ui::views::ViewRef view_ref;
673 auto status = zx::eventpair::create(
674 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
675 ZX_ASSERT(status == ZX_OK);
676 view_ref_control.reference.replace(
677 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
678 &view_ref_control.reference);
679 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
680
681 auto response = FakePlatformMessageResponse::Create();
682 auto response_2 = FakePlatformMessageResponse::Create();
683
684 // Create the view.
685 fuv_ViewRef view_ref_clone;
686 fidl::Clone(view_ref, &view_ref_clone);
687 CreateView(view_id, std::move(view_ref_clone));
688
689 EXPECT_TRUE(pointer_injector_delegate_->HandlePlatformMessage(
690 PlatformMessageBuilder()
691 .SetViewId(view_id)
692 .SetPointerId(pointer_id)
693 .Build(),
694 response));
695
696 response->ExpectCompleted("[0]");
697
698 // The mock Pointerinjector registry server receives a pointer event from
699 // |f.u.p.Device.Inject| call for the view.
700 RunLoopUntil([this] { return registry_->num_events_received() == 1; });
701
702 // The mock Pointerinjector registry server receives a
703 // |f.u.p.Registry.Register| call for the view.
704 ASSERT_TRUE(registry_->num_register_calls() == 1);
705
706 // Close the device channel.
707 registry_->ClearBindings();
708 RunLoopUntilIdle();
709
710 EXPECT_TRUE(pointer_injector_delegate_->HandlePlatformMessage(
711 PlatformMessageBuilder()
712 .SetViewId(view_id)
713 .SetPointerId(pointer_id)
714 .Build(),
715 response_2));
716
717 response_2->ExpectCompleted("[0]");
718
719 // The mock Pointerinjector registry server receives a pointer event from
720 // |f.u.p.Device.Inject| call for the view.
721 RunLoopUntil([this] { return registry_->num_events_received() == 2; });
722
723 // The device tries to register again as the channel got closed.
724 ASSERT_TRUE(registry_->num_register_calls() == 2);
725}

◆ TEST_P() [3/8]

flutter_runner::testing::TEST_P ( PointerInjectorDelegateTest  ,
IncorrectPlatformMessage_ShouldFail   
)

Definition at line 255 of file pointer_injector_delegate_unittest.cc.

255 {
256 const uint64_t view_id = 1;
257
258 // Create a view.
259 CreateView(view_id);
260
261 // A platform message in incorrect JSON format should fail.
262 {
263 auto response = FakePlatformMessageResponse::Create();
264
265 EXPECT_FALSE(pointer_injector_delegate_->HandlePlatformMessage(
266 ParsePlatformMessage("{Incorrect Json}"), response));
267 }
268
269 // |PointerInjectorDelegate| only handles "View.Pointerinjector.inject"
270 // platform messages.
271 {
272 auto response = FakePlatformMessageResponse::Create();
273
274 EXPECT_FALSE(pointer_injector_delegate_->HandlePlatformMessage(
275 ParsePlatformMessage("{\"method\":\"View.focus.getCurrent\"}"),
276 response));
277 }
278
279 // A platform message with no args should fail.
280 {
281 auto response = FakePlatformMessageResponse::Create();
282
283 EXPECT_FALSE(pointer_injector_delegate_->HandlePlatformMessage(
284 ParsePlatformMessage("{\"method\":\"View.Pointerinjector.inject\"}"),
285 response));
286 }
287}

◆ TEST_P() [4/8]

flutter_runner::testing::TEST_P ( PointerInjectorDelegateTest  ,
ValidPointerEventTest   
)

Definition at line 495 of file pointer_injector_delegate_unittest.cc.

495 {
496 const uint64_t view_id = 1;
497
498 const float x = 2.f, y = 2.f, width = 5.f, height = 5.f;
499 const int phase = 2, pointer_id = 5, trace_flow_id = 5, timestamp = 10;
500
501 auto response = FakePlatformMessageResponse::Create();
502
503 fuchsia::ui::views::ViewRefControl view_ref_control;
504 fuchsia::ui::views::ViewRef view_ref;
505 auto status = zx::eventpair::create(
506 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
507 ZX_ASSERT(status == ZX_OK);
508 view_ref_control.reference.replace(
509 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
510 &view_ref_control.reference);
511 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
512
513 // Create the view.
514 fuv_ViewRef view_ref_clone;
515 fidl::Clone(view_ref, &view_ref_clone);
516 CreateView(view_id, std::move(view_ref_clone));
517
518 // Inject a platform message.
519 EXPECT_TRUE(pointer_injector_delegate_->HandlePlatformMessage(
520 PlatformMessageBuilder()
521 .SetViewId(view_id)
522 .SetPointerX(x)
523 .SetPointerY(y)
524 .SetPhase(phase)
525 .SetPointerId(pointer_id)
526 .SetTraceFlowId(trace_flow_id)
527 .SetLogicalWidth(width)
528 .SetLogicalHeight(height)
529 .SetTimestamp(timestamp)
530 .Build(),
531 response));
532
533 response->ExpectCompleted("[0]");
534
535 // The mock Pointerinjector registry server receives a pointer event from
536 // |f.u.p.Device.Inject| call for the view.
537 RunLoopUntil([this] { return registry_->num_events_received() == 1; });
538
539 // The mock Pointerinjector registry server receives a
540 // |f.u.p.Registry.Register| call for the view.
541 ASSERT_TRUE(registry_->num_register_calls() == 1);
542
543 const auto& events = registry_->events();
544
545 ASSERT_EQ(events.size(), 1u);
546
547 const auto& event = events[0];
548
549 ASSERT_TRUE(event.has_timestamp());
550 EXPECT_EQ(event.timestamp(), timestamp);
551
552 ASSERT_TRUE(event.has_trace_flow_id());
553 EXPECT_EQ(event.trace_flow_id(), static_cast<uint64_t>(trace_flow_id));
554
555 ASSERT_TRUE(event.has_data());
556 ASSERT_TRUE(event.data().is_pointer_sample());
557
558 const auto& pointer_sample = event.data().pointer_sample();
559
560 ASSERT_TRUE(pointer_sample.has_pointer_id());
561 ASSERT_TRUE(pointer_sample.has_phase());
562 ASSERT_TRUE(pointer_sample.has_position_in_viewport());
563 EXPECT_EQ(pointer_sample.pointer_id(), static_cast<uint32_t>(pointer_id));
564 EXPECT_EQ(pointer_sample.phase(), static_cast<fup_EventPhase>(phase));
565 EXPECT_THAT(pointer_sample.position_in_viewport(),
566 ::testing::ElementsAre(x, y));
567}
double y
double x
fuchsia::ui::pointer::EventPhase fup_EventPhase

◆ TEST_P() [5/8]

flutter_runner::testing::TEST_P ( PointerInjectorDelegateTest  ,
ValidRegistrationConfigTest   
)

Definition at line 417 of file pointer_injector_delegate_unittest.cc.

417 {
418 const uint64_t view_id = 1;
419
420 const float x = 2.f, y = 2.f, width = 5.f, height = 5.f;
421 const int phase = 2, pointer_id = 5, trace_flow_id = 5, timestamp = 10;
422
423 auto response = FakePlatformMessageResponse::Create();
424
425 fuchsia::ui::views::ViewRefControl view_ref_control;
426 fuchsia::ui::views::ViewRef view_ref;
427 auto status = zx::eventpair::create(
428 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
429 ZX_ASSERT(status == ZX_OK);
430 view_ref_control.reference.replace(
431 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
432 &view_ref_control.reference);
433 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
434
435 // Create the view.
436 fuv_ViewRef view_ref_clone;
437 fidl::Clone(view_ref, &view_ref_clone);
438 CreateView(view_id, std::move(view_ref_clone));
439
440 // Inject a platform message.
441 EXPECT_TRUE(pointer_injector_delegate_->HandlePlatformMessage(
442 PlatformMessageBuilder()
443 .SetViewId(view_id)
444 .SetPointerX(x)
445 .SetPointerY(y)
446 .SetPhase(phase)
447 .SetPointerId(pointer_id)
448 .SetTraceFlowId(trace_flow_id)
449 .SetLogicalWidth(width)
450 .SetLogicalHeight(height)
451 .SetTimestamp(timestamp)
452 .Build(),
453 response));
454
455 response->ExpectCompleted("[0]");
456
457 // The mock Pointerinjector registry server receives a pointer event from
458 // |f.u.p.Device.Inject| call for the view.
459 RunLoopUntil([this] { return registry_->num_events_received() == 1; });
460
461 // The mock Pointerinjector registry server receives a
462 // |f.u.p.Registry.Register| call for the view.
463 ASSERT_TRUE(registry_->num_register_calls() == 1);
464
465 const auto& config = registry_->config();
466
467 ASSERT_TRUE(config.has_device_id());
468 EXPECT_EQ(config.device_id(), 1u);
469
470 ASSERT_TRUE(config.has_device_type());
471 EXPECT_EQ(config.device_type(), fup_DeviceType::TOUCH);
472
473 ASSERT_TRUE(config.has_dispatch_policy());
474 EXPECT_EQ(config.dispatch_policy(), fup_DispatchPolicy::EXCLUSIVE_TARGET);
475
476 ASSERT_TRUE(config.has_context());
477 ASSERT_TRUE(config.context().is_view());
478 EXPECT_EQ(ExtractKoid(config.context().view()), ExtractKoid(host_view_ref_));
479
480 ASSERT_TRUE(config.has_target());
481 ASSERT_TRUE(config.target().is_view());
482 EXPECT_EQ(ExtractKoid(config.target().view()), ExtractKoid(view_ref));
483
484 ASSERT_TRUE(config.has_viewport());
485 ASSERT_TRUE(config.viewport().has_viewport_to_context_transform());
486 EXPECT_EQ(config.viewport().viewport_to_context_transform(), kIdentityMatrix);
487
488 std::array<std::array<float, 2>, 2> extents{{{0, 0}, {width, height}}};
489 ASSERT_TRUE(config.viewport().has_extents());
490 EXPECT_EQ(config.viewport().extents(), extents);
491}

◆ TEST_P() [6/8]

flutter_runner::testing::TEST_P ( PointerInjectorDelegateTest  ,
ViewsDontReceivePointerEventsBeforeCreation   
)

Definition at line 354 of file pointer_injector_delegate_unittest.cc.

355 {
356 const uint64_t num_events = 150;
357 const uint64_t view_id_1 = 1;
358
359 // Inject |num_events| platform messages for |view_id_1|.
360 {
361 fuchsia::ui::views::ViewRefControl view_ref_control;
362 fuchsia::ui::views::ViewRef view_ref;
363 auto status = zx::eventpair::create(
364 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
365 ASSERT_EQ(status, ZX_OK);
366 view_ref_control.reference.replace(
367 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
368 &view_ref_control.reference);
369 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
370
371 for (size_t i = 0; i < num_events; i++) {
372 auto response = FakePlatformMessageResponse::Create();
373
374 // The platform message is *silently* accepted for non-existent views, in
375 // order to cleanly handle the lifecycle case where the child view is
376 // forcibly killed. By doing so, products avoid "MissingPluginException"
377 // log spam.
378 EXPECT_TRUE(pointer_injector_delegate_->HandlePlatformMessage(
379 PlatformMessageBuilder().SetViewId(view_id_1).Build(), response));
380 }
381 }
382
383 const uint64_t view_id_2 = 2;
384
385 // Inject |num_events| platform messages for |view_id_2|.
386 {
387 fuchsia::ui::views::ViewRefControl view_ref_control;
388 fuchsia::ui::views::ViewRef view_ref;
389 auto status = zx::eventpair::create(
390 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
391 ASSERT_EQ(status, ZX_OK);
392 view_ref_control.reference.replace(
393 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
394 &view_ref_control.reference);
395 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
396
397 for (size_t i = 0; i < num_events; i++) {
398 auto response = FakePlatformMessageResponse::Create();
399
400 // The platform message is *silently* accepted for non-existent views, in
401 // order to cleanly handle the lifecycle case where the child view is
402 // forcibly killed. By doing so, products avoid "MissingPluginException"
403 // log spam.
404 EXPECT_TRUE(pointer_injector_delegate_->HandlePlatformMessage(
405 PlatformMessageBuilder().SetViewId(view_id_2).Build(), response));
406 }
407 }
408
409 RunLoopUntilIdle();
410
411 // The views do not receive any pointer events till they get created.
412 EXPECT_TRUE(registry_->num_events_received() == 0);
413}

◆ TEST_P() [7/8]

flutter_runner::testing::TEST_P ( PointerInjectorDelegateTest  ,
ViewsGetPointerEventsInFIFO   
)

Definition at line 608 of file pointer_injector_delegate_unittest.cc.

608 {
609 const uint64_t view_id = 1, num_events = 150;
610
611 fuchsia::ui::views::ViewRefControl view_ref_control;
612 fuchsia::ui::views::ViewRef view_ref;
613 auto status = zx::eventpair::create(
614 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
615 ZX_ASSERT(status == ZX_OK);
616 view_ref_control.reference.replace(
617 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
618 &view_ref_control.reference);
619 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
620
621 // Create the view.
622 CreateView(view_id);
623
624 // Inject |num_events| platform messages.
625 for (size_t i = 0; i < num_events; i++) {
626 auto response = FakePlatformMessageResponse::Create();
627
628 EXPECT_TRUE(pointer_injector_delegate_->HandlePlatformMessage(
629 PlatformMessageBuilder()
630 .SetViewId(view_id)
631 .SetPointerId(static_cast<uint32_t>(i))
632 .Build(),
633 response));
634
635 response->ExpectCompleted("[0]");
636 }
637
638 // The mock Pointerinjector registry server receives |num_events| pointer
639 // events from |f.u.p.Device.Inject| call for the view.
640 RunLoopUntil(
641 [this] { return registry_->num_events_received() == num_events; });
642
643 // The mock Pointerinjector registry server receives a
644 // |f.u.p.Registry.Register| call for the view.
645 ASSERT_TRUE(registry_->num_register_calls() == 1);
646
647 auto& events = registry_->events();
648
649 // The view should receive the pointer events in a FIFO order. As we injected
650 // platform messages with an increasing |pointer_id|, the received pointer
651 // events should also have the |pointer_id| in an increasing order.
652 for (size_t i = 0; i < events.size() - 1; i++) {
653 ASSERT_TRUE(events[i].has_data());
654 ASSERT_TRUE(events[i + 1].has_data());
655 ASSERT_TRUE(events[i].data().is_pointer_sample());
656 ASSERT_TRUE(events[i + 1].data().is_pointer_sample());
657
658 const auto& pointer_sample_1 = events[i].data().pointer_sample();
659 const auto& pointer_sample_2 = events[i + 1].data().pointer_sample();
660
661 ASSERT_TRUE(pointer_sample_1.has_pointer_id());
662 ASSERT_TRUE(pointer_sample_2.has_pointer_id());
663
664 EXPECT_TRUE(pointer_sample_1.pointer_id() < pointer_sample_2.pointer_id());
665 }
666}

◆ TEST_P() [8/8]

flutter_runner::testing::TEST_P ( PointerInjectorDelegateTest  ,
ViewsReceiveInjectedEvents   
)

Definition at line 289 of file pointer_injector_delegate_unittest.cc.

289 {
290 const uint64_t num_events = 150;
291
292 // Inject |num_events| platform messages for view 1.
293 {
294 const uint64_t view_id = 1;
295
296 CreateView(view_id);
297
298 fuchsia::ui::views::ViewRefControl view_ref_control;
299 fuchsia::ui::views::ViewRef view_ref;
300 auto status = zx::eventpair::create(
301 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
302 ASSERT_EQ(status, ZX_OK);
303 view_ref_control.reference.replace(
304 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
305 &view_ref_control.reference);
306 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
307
308 for (size_t i = 0; i < num_events; i++) {
309 auto response = FakePlatformMessageResponse::Create();
310
311 EXPECT_TRUE(pointer_injector_delegate_->HandlePlatformMessage(
312 PlatformMessageBuilder().SetViewId(view_id).Build(), response));
313
314 response->ExpectCompleted("[0]");
315 }
316 }
317
318 // Inject |num_events| platform messages for view 2.
319 {
320 const uint64_t view_id = 2;
321
322 CreateView(view_id);
323
324 fuchsia::ui::views::ViewRefControl view_ref_control;
325 fuchsia::ui::views::ViewRef view_ref;
326 auto status = zx::eventpair::create(
327 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
328 ASSERT_EQ(status, ZX_OK);
329 view_ref_control.reference.replace(
330 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
331 &view_ref_control.reference);
332 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
333
334 for (size_t i = 0; i < num_events; i++) {
335 auto response = FakePlatformMessageResponse::Create();
336
337 EXPECT_TRUE(pointer_injector_delegate_->HandlePlatformMessage(
338 PlatformMessageBuilder().SetViewId(view_id).Build(), response));
339
340 response->ExpectCompleted("[0]");
341 }
342 }
343
344 // The mock Pointerinjector registry server receives |num_events| pointer
345 // events from |f.u.p.Device.Inject| calls for each view.
346 RunLoopUntil(
347 [this] { return registry_->num_events_received() == 2 * num_events; });
348
349 // The mock Pointerinjector registry server receives a
350 // |f.u.p.Registry.Register| call for each view.
351 EXPECT_TRUE(registry_->num_register_calls() == 2);
352}

Variable Documentation

◆ kIdentity

constexpr std::array<float, 9> flutter_runner::testing::kIdentity = {1, 0, 0, 0, 1, 0, 0, 0, 1}
constexpr

Definition at line 36 of file pointer_delegate_unittests.cc.

36{1, 0, 0, 0, 1, 0, 0, 0, 1};

◆ kInfiniteHitRegion

constexpr fuchsia::ui::composition::HitRegion flutter_runner::testing::kInfiniteHitRegion
staticconstexpr
Initial value:
= {
.region = {-FLT_MAX, -FLT_MAX, FLT_MAX, FLT_MAX}}

Definition at line 152 of file fake_flatland_types.h.

152 {
153 .region = {-FLT_MAX, -FLT_MAX, FLT_MAX, FLT_MAX}};

◆ kInvalidContentId

constexpr fuchsia::ui::composition::ContentId flutter_runner::testing::kInvalidContentId {0}
staticconstexpr

Definition at line 151 of file fake_flatland_types.h.

151{0};

◆ kInvalidTransformId

constexpr fuchsia::ui::composition::TransformId flutter_runner::testing::kInvalidTransformId {0}
staticconstexpr

Definition at line 150 of file fake_flatland_types.h.

150{0};

◆ kIxnOne

constexpr fup_TouchIxnId flutter_runner::testing::kIxnOne
constexpr
Initial value:
= {.device_id = 1u,
.pointer_id = 1u,
.interaction_id = 2u}

Definition at line 37 of file pointer_delegate_unittests.cc.

37 {.device_id = 1u,
38 .pointer_id = 1u,
39 .interaction_id = 2u};

◆ kMouseDeviceId

constexpr uint32_t flutter_runner::testing::kMouseDeviceId = 123
constexpr

Definition at line 41 of file pointer_delegate_unittests.cc.

◆ kNoScrollInPhysicalPixelDelta

constexpr std::array<int64_t, 2> flutter_runner::testing::kNoScrollInPhysicalPixelDelta = {0, 0}
constexpr

Definition at line 42 of file pointer_delegate_unittests.cc.

42{0, 0};

◆ kNotPrecisionScroll

const bool flutter_runner::testing::kNotPrecisionScroll = false

Definition at line 43 of file pointer_delegate_unittests.cc.

◆ kPrecisionScroll

const bool flutter_runner::testing::kPrecisionScroll = true

Definition at line 44 of file pointer_delegate_unittests.cc.

◆ kRect

constexpr std::array<std::array<float, 2>, 2> flutter_runner::testing::kRect = {{{0, 0}, {20, 20}}}
constexpr

Definition at line 35 of file pointer_delegate_unittests.cc.

35{{{0, 0}, {20, 20}}};