|  | // Copyright 2020 The Fuchsia Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "sdk/lib/ui/scenic/cpp/session.h" | 
|  |  | 
|  | #include <lib/gtest/test_loop_fixture.h> | 
|  | #include <lib/zx/channel.h> | 
|  | #include <zircon/types.h> | 
|  |  | 
|  | #include <gtest/gtest.h> | 
|  |  | 
|  | #include "lib/ui/scenic/cpp/commands.h" | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | class MockScenicSession : public scenic::Session { | 
|  | public: | 
|  | MockScenicSession(fuchsia::ui::scenic::SessionPtr client) : Session(std::move(client)) {} | 
|  |  | 
|  | void Flush() override { | 
|  | num_flushed_++; | 
|  | commands_.clear(); | 
|  | }; | 
|  |  | 
|  | int64_t num_flushed_ = 0; | 
|  | size_t num_commands() { return commands_.size(); } | 
|  | int64_t num_bytes() { return commands_num_bytes_; } | 
|  | int64_t num_handles() { return commands_num_handles_; } | 
|  | }; | 
|  |  | 
|  | class ScenicSessionFlushTest : public ::gtest::TestLoopFixture { | 
|  | public: | 
|  | ScenicSessionFlushTest() = default; | 
|  | ~ScenicSessionFlushTest() override = default; | 
|  |  | 
|  | std::unique_ptr<MockScenicSession> session_; | 
|  |  | 
|  | protected: | 
|  | void SetUp() override { | 
|  | zx::channel client_end, server_end; | 
|  | zx::channel::create(0, &client_end, &server_end); | 
|  | fuchsia::ui::scenic::SessionPtr client; | 
|  | client.Bind(std::move(client_end)); | 
|  | session_ = std::make_unique<MockScenicSession>(std::move(client)); | 
|  | } | 
|  |  | 
|  | void TearDown() override { session_.reset(); } | 
|  | }; | 
|  |  | 
|  | TEST_F(ScenicSessionFlushTest, AddOneInputCommand) { | 
|  | fuchsia::ui::input::SendPointerInputCmd send_pointer_input_cmd; | 
|  |  | 
|  | fuchsia::ui::input::Command input_cmd; | 
|  | input_cmd.set_send_pointer_input(send_pointer_input_cmd); | 
|  |  | 
|  | fuchsia::ui::scenic::Command cmd; | 
|  | cmd.set_input(std::move(input_cmd)); | 
|  |  | 
|  | session_->Enqueue(std::move(cmd)); | 
|  |  | 
|  | EXPECT_EQ(session_->num_flushed_, 1); | 
|  | EXPECT_EQ(session_->num_commands(), 0u); | 
|  | EXPECT_EQ(session_->num_bytes(), | 
|  | // See commands_sizing_test.cc for details. | 
|  | scenic::kEnqueueRequestBaseNumBytes + 104u); | 
|  | EXPECT_EQ(session_->num_handles(), | 
|  | // See commands_sizing_test.cc for details. | 
|  | 0u); | 
|  | } | 
|  |  | 
|  | TEST_F(ScenicSessionFlushTest, AddTwoInputCommands) { | 
|  | for (int64_t i = 0; i < 2; ++i) { | 
|  | fuchsia::ui::input::SendPointerInputCmd send_pointer_input_cmd; | 
|  |  | 
|  | fuchsia::ui::input::Command input_cmd; | 
|  | input_cmd.set_send_pointer_input(send_pointer_input_cmd); | 
|  |  | 
|  | fuchsia::ui::scenic::Command cmd; | 
|  | cmd.set_input(std::move(input_cmd)); | 
|  |  | 
|  | session_->Enqueue(std::move(cmd)); | 
|  | } | 
|  |  | 
|  | EXPECT_EQ(session_->num_flushed_, 2); | 
|  | EXPECT_EQ(session_->num_commands(), 0u); | 
|  |  | 
|  | // The overriden Flush does not reset byte and handle counts, so we accumulate each | 
|  | // command's size. | 
|  | EXPECT_EQ(session_->num_bytes(), | 
|  | // See commands_sizing_test.cc for details. | 
|  | scenic::kEnqueueRequestBaseNumBytes + 2 * 104u); | 
|  | EXPECT_EQ(session_->num_handles(), | 
|  | // See commands_sizing_test.cc for details. | 
|  | 0u); | 
|  | } | 
|  |  | 
|  | TEST_F(ScenicSessionFlushTest, AddTenNonInputCommandsThenOneInputCommand) { | 
|  | for (int64_t i = 0; i < 10; ++i) { | 
|  | fuchsia::ui::gfx::MemoryArgs memory_args; | 
|  |  | 
|  | fuchsia::ui::gfx::ResourceArgs resource_args; | 
|  | resource_args.set_memory(std::move(memory_args)); | 
|  |  | 
|  | fuchsia::ui::gfx::CreateResourceCmd create_resource_cmd; | 
|  | create_resource_cmd.resource = std::move(resource_args); | 
|  |  | 
|  | fuchsia::ui::gfx::Command gfx_cmd; | 
|  | gfx_cmd.set_create_resource(std::move(create_resource_cmd)); | 
|  |  | 
|  | fuchsia::ui::scenic::Command cmd; | 
|  | cmd.set_gfx(std::move(gfx_cmd)); | 
|  |  | 
|  | session_->Enqueue(std::move(cmd)); | 
|  | } | 
|  |  | 
|  | // We accumulate all commands (without ever flushing). | 
|  | EXPECT_EQ(session_->num_flushed_, 0u); | 
|  | EXPECT_EQ(session_->num_commands(), 10u); | 
|  | EXPECT_EQ(session_->num_bytes(), | 
|  | // See commands_sizing_test.cc for details. | 
|  | scenic::kEnqueueRequestBaseNumBytes + 10 * 104u); | 
|  | EXPECT_EQ(session_->num_handles(), | 
|  | // See commands_sizing_test.cc for details. | 
|  | 10 * 1u); | 
|  |  | 
|  | { | 
|  | fuchsia::ui::input::SendPointerInputCmd send_pointer_input_cmd; | 
|  |  | 
|  | fuchsia::ui::input::Command input_cmd; | 
|  | input_cmd.set_send_pointer_input(send_pointer_input_cmd); | 
|  |  | 
|  | fuchsia::ui::scenic::Command cmd; | 
|  | cmd.set_input(std::move(input_cmd)); | 
|  |  | 
|  | session_->Enqueue(std::move(cmd)); | 
|  | } | 
|  |  | 
|  | // Since input commands are eagerly flushed, we send all eleven commands at | 
|  | // once. | 
|  | EXPECT_EQ(session_->num_flushed_, 1u); | 
|  | EXPECT_EQ(session_->num_commands(), 0u); | 
|  | EXPECT_EQ(session_->num_bytes(), | 
|  | // See commands_sizing_test.cc for details. | 
|  | scenic::kEnqueueRequestBaseNumBytes + 11 * 104u); | 
|  | EXPECT_EQ(session_->num_handles(), | 
|  | // See commands_sizing_test.cc for details. | 
|  | 10 * 1u); | 
|  | } | 
|  |  | 
|  | TEST_F(ScenicSessionFlushTest, AddNonInputCommandThenPresent) { | 
|  | // Enqueue CreateResourceCmd | 
|  | { | 
|  | fuchsia::ui::gfx::MemoryArgs memory_args; | 
|  |  | 
|  | fuchsia::ui::gfx::ResourceArgs resource_args; | 
|  | resource_args.set_memory(std::move(memory_args)); | 
|  |  | 
|  | fuchsia::ui::gfx::CreateResourceCmd create_resource_cmd; | 
|  | create_resource_cmd.resource = std::move(resource_args); | 
|  |  | 
|  | fuchsia::ui::gfx::Command gfx_cmd; | 
|  | gfx_cmd.set_create_resource(std::move(create_resource_cmd)); | 
|  |  | 
|  | fuchsia::ui::scenic::Command cmd; | 
|  | cmd.set_gfx(std::move(gfx_cmd)); | 
|  |  | 
|  | session_->Enqueue(std::move(cmd)); | 
|  | } | 
|  |  | 
|  | // The enqueued command has not been flushed, but will be when we present. | 
|  | EXPECT_EQ(session_->num_flushed_, 0); | 
|  |  | 
|  | // Present | 
|  | auto callback = [&](fuchsia::images::PresentationInfo info) {}; | 
|  | session_->Present(0u, std::move(callback)); | 
|  |  | 
|  | // And check that we've flushed. | 
|  | EXPECT_EQ(session_->num_flushed_, 1); | 
|  | } | 
|  |  | 
|  | TEST_F(ScenicSessionFlushTest, AddNonInputCommandThenPresent2) { | 
|  | // Enqueue CreateResourceCmd | 
|  | { | 
|  | fuchsia::ui::gfx::MemoryArgs memory_args; | 
|  |  | 
|  | fuchsia::ui::gfx::ResourceArgs resource_args; | 
|  | resource_args.set_memory(std::move(memory_args)); | 
|  |  | 
|  | fuchsia::ui::gfx::CreateResourceCmd create_resource_cmd; | 
|  | create_resource_cmd.resource = std::move(resource_args); | 
|  |  | 
|  | fuchsia::ui::gfx::Command gfx_cmd; | 
|  | gfx_cmd.set_create_resource(std::move(create_resource_cmd)); | 
|  |  | 
|  | fuchsia::ui::scenic::Command cmd; | 
|  | cmd.set_gfx(std::move(gfx_cmd)); | 
|  |  | 
|  | session_->Enqueue(std::move(cmd)); | 
|  | } | 
|  |  | 
|  | // The enqueued command has not been flushed, but will be when we present. | 
|  | EXPECT_EQ(session_->num_flushed_, 0); | 
|  |  | 
|  | // Present2 | 
|  | auto callback = [&](fuchsia::scenic::scheduling::FuturePresentationTimes info) {}; | 
|  | session_->Present2(0u, 0u, std::move(callback)); | 
|  |  | 
|  | // And check that we've flushed. | 
|  | EXPECT_EQ(session_->num_flushed_, 1); | 
|  | } | 
|  |  | 
|  | }  // namespace |