| // 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 "src/camera/lib/fake_camera/fake_camera.h" |
| |
| #include <fuchsia/sysmem/cpp/fidl.h> |
| #include <lib/sys/cpp/component_context.h> |
| #include <zircon/status.h> |
| #include <zircon/types.h> |
| |
| #include "src/lib/fsl/handles/object_info.h" |
| #include "src/lib/testing/loop_fixture/real_loop_fixture.h" |
| |
| constexpr auto kCameraIdentifier = "FakeCameraTest"; |
| |
| class FakeCameraTest : public gtest::RealLoopFixture { |
| public: |
| FakeCameraTest() { context_ = sys::ComponentContext::CreateAndServeOutgoingDirectory(); } |
| |
| protected: |
| virtual void SetUp() override { |
| context_->svc()->Connect(allocator_.NewRequest()); |
| allocator_->SetDebugClientInfo(fsl::GetCurrentProcessName(), fsl::GetCurrentProcessKoid()); |
| allocator_.set_error_handler(MakeErrorHandler("Sysmem Allocator")); |
| } |
| |
| virtual void TearDown() override { |
| allocator_ = nullptr; |
| RunLoopUntilIdle(); |
| } |
| |
| static fit::function<void(zx_status_t status)> MakeErrorHandler(std::string server) { |
| return [server](zx_status_t status) { |
| ADD_FAILURE() << server << " server disconnected - " << status; |
| }; |
| } |
| |
| template <class T> |
| static void SetFailOnError(fidl::InterfacePtr<T>& ptr, std::string name = T::Name_) { |
| ptr.set_error_handler([=](zx_status_t status) { |
| ADD_FAILURE() << name << " server disconnected: " << zx_status_get_string(status); |
| }); |
| } |
| |
| std::unique_ptr<sys::ComponentContext> context_; |
| fuchsia::sysmem::AllocatorPtr allocator_; |
| }; |
| |
| TEST_F(FakeCameraTest, InvalidArgs) { |
| { // No configurations. |
| auto result = camera::FakeCamera::Create(kCameraIdentifier, {}); |
| ASSERT_TRUE(result.is_error()); |
| EXPECT_EQ(result.error(), ZX_ERR_INVALID_ARGS); |
| } |
| |
| { // No streams. |
| std::vector<camera::FakeConfiguration> configs; |
| configs.push_back({}); |
| auto result = camera::FakeCamera::Create(kCameraIdentifier, std::move(configs)); |
| ASSERT_TRUE(result.is_error()); |
| EXPECT_EQ(result.error(), ZX_ERR_INVALID_ARGS); |
| } |
| |
| { // Null stream. |
| camera::FakeConfiguration config; |
| config.push_back(nullptr); |
| std::vector<camera::FakeConfiguration> configs; |
| configs.push_back(std::move(config)); |
| auto result = camera::FakeCamera::Create(kCameraIdentifier, std::move(configs)); |
| ASSERT_TRUE(result.is_error()); |
| EXPECT_EQ(result.error(), ZX_ERR_INVALID_ARGS); |
| } |
| } |
| |
| TEST_F(FakeCameraTest, SetBufferCollectionInvokesCallback) { |
| fuchsia::camera3::StreamProperties properties{ |
| .image_format{.pixel_format{.type = fuchsia::sysmem::PixelFormatType::NV12}, |
| .coded_width = 256, |
| .coded_height = 128, |
| .bytes_per_row = 256, |
| .color_space{.type = fuchsia::sysmem::ColorSpaceType::REC601_NTSC}}, |
| .frame_rate{ |
| .numerator = 30, |
| .denominator = 1, |
| }}; |
| bool callback_invoked = false; |
| auto stream_result = camera::FakeStream::Create( |
| std::move(properties), |
| [&](fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken> token) { |
| callback_invoked = true; |
| }); |
| ASSERT_TRUE(stream_result.is_ok()); |
| std::shared_ptr<camera::FakeStream> stream = stream_result.take_value(); |
| |
| camera::FakeConfiguration config; |
| config.push_back(stream); |
| std::vector<camera::FakeConfiguration> configs; |
| configs.push_back(std::move(config)); |
| auto camera_result = camera::FakeCamera::Create(kCameraIdentifier, std::move(configs)); |
| ASSERT_TRUE(camera_result.is_ok()); |
| auto camera = camera_result.take_value(); |
| |
| fuchsia::camera3::DevicePtr device_protocol; |
| SetFailOnError(device_protocol, "Device"); |
| fuchsia::camera3::StreamPtr stream_protocol; |
| SetFailOnError(stream_protocol, "Stream"); |
| camera->GetHandler()(device_protocol.NewRequest()); |
| fuchsia::sysmem::BufferCollectionTokenPtr token; |
| SetFailOnError(token, "Token"); |
| device_protocol->GetConfigurations( |
| [&](std::vector<fuchsia::camera3::Configuration> configurations) { |
| ASSERT_FALSE(configurations.empty()); |
| ASSERT_FALSE(configurations[0].streams.empty()); |
| device_protocol->ConnectToStream(0, stream_protocol.NewRequest()); |
| allocator_->AllocateSharedCollection(token.NewRequest()); |
| token->Sync([&] { stream_protocol->SetBufferCollection(std::move(token)); }); |
| }); |
| RunLoopUntil([&]() { return HasFailure() || callback_invoked; }); |
| } |