chromium/chromecast/crash/fuchsia/cast_crash_storage_impl_fuchsia_unittest.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromecast/crash/fuchsia/cast_crash_storage_impl_fuchsia.h"

#include <fuchsia/feedback/cpp/fidl.h>
#include <fuchsia/feedback/cpp/fidl_test_base.h>
#include <lib/fidl/cpp/clone.h>
#include <lib/fidl/cpp/comparison.h>
#include <lib/sys/cpp/outgoing_directory.h>
#include <lib/sys/cpp/service_directory.h>

#include <memory>

#include "base/fuchsia/scoped_service_binding.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "chromecast/crash/fuchsia/constants.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace chromecast {
namespace {

class MockComponentDataRegister
    : public fuchsia::feedback::testing::ComponentDataRegister_TestBase {
 public:
  MockComponentDataRegister(
      fidl::InterfaceRequest<fuchsia::io::Directory> channel) {
    outgoing_directory_ = std::make_unique<sys::OutgoingDirectory>();
    outgoing_directory_->GetOrCreateDirectory("svc")->Serve(
        fuchsia::io::OpenFlags::RIGHT_READABLE |
            fuchsia::io::OpenFlags::RIGHT_WRITABLE,
        channel.TakeChannel());
    binding_ = std::make_unique<
        base::ScopedServiceBinding<fuchsia::feedback::ComponentDataRegister>>(
        outgoing_directory_.get(), this);
  }

  fuchsia::feedback::ComponentData GetLatest() {
    return fidl::Clone(component_data_);
  }

  void Upsert(fuchsia::feedback::ComponentData data,
              UpsertCallback callback) final {
    component_data_ = std::move(data);
    callback();
  }

  void NotImplemented_(const std::string& name) final { ADD_FAILURE(); }

 private:
  std::unique_ptr<sys::OutgoingDirectory> outgoing_directory_;
  std::unique_ptr<
      base::ScopedServiceBinding<fuchsia::feedback::ComponentDataRegister>>
      binding_;

  fuchsia::feedback::ComponentData component_data_;
};

class CastCrashStorageImplFuchsiaTest : public ::testing::Test {
 public:
  CastCrashStorageImplFuchsiaTest() {
    fidl::InterfaceHandle<fuchsia::io::Directory> directory;
    component_data_register_ =
        std::make_unique<MockComponentDataRegister>(directory.NewRequest());
    incoming_directory_ =
        std::make_unique<sys::ServiceDirectory>(std::move(directory));
  }

  void SetUp() final {
    cast_crash_storage_ = std::make_unique<CastCrashStorageImplFuchsia>(
        incoming_directory_.get());
  }

  void TearDown() final { cast_crash_storage_ = nullptr; }

  void VerifyLatestAnnotation(const fuchsia::feedback::Annotation& annotation) {
    fuchsia::feedback::ComponentData latest =
        component_data_register_->GetLatest();
    EXPECT_EQ(latest.namespace_(), crash::kCastNamespace);
    ASSERT_EQ(latest.annotations().size(), 1uL);

    fuchsia::feedback::Annotation latest_annotation =
        fidl::Clone(latest.annotations()[0]);
    EXPECT_EQ(annotation.key, latest_annotation.key);
    EXPECT_EQ(annotation.value, latest_annotation.value);
  }

 protected:
  std::unique_ptr<CastCrashStorageImplFuchsia> cast_crash_storage_;

 private:
  base::test::TaskEnvironment task_environment_{
      base::test::TaskEnvironment::MainThreadType::IO};
  std::unique_ptr<MockComponentDataRegister> component_data_register_;
  std::unique_ptr<sys::ServiceDirectory> incoming_directory_;
};

TEST_F(CastCrashStorageImplFuchsiaTest, LastLaunchedApp) {
  fuchsia::feedback::Annotation annotation;
  annotation.key = "app.last-launched";
  annotation.value = "last_launched_app_id";

  cast_crash_storage_->SetLastLaunchedApp("last_launched_app_id");
  base::RunLoop().RunUntilIdle();
  VerifyLatestAnnotation(annotation);
}

TEST_F(CastCrashStorageImplFuchsiaTest, CurrentApp) {
  fuchsia::feedback::Annotation annotation;
  annotation.key = "app.current";
  annotation.value = "current_app_id";

  cast_crash_storage_->SetCurrentApp("current_app_id");
  base::RunLoop().RunUntilIdle();
  VerifyLatestAnnotation(annotation);
}

TEST_F(CastCrashStorageImplFuchsiaTest, PreviousApp) {
  fuchsia::feedback::Annotation annotation;
  annotation.key = "app.previous";
  annotation.value = "previous_app_id";

  cast_crash_storage_->SetPreviousApp("previous_app_id");
  base::RunLoop().RunUntilIdle();
  VerifyLatestAnnotation(annotation);
}

TEST_F(CastCrashStorageImplFuchsiaTest, StadiaSessionId) {
  fuchsia::feedback::Annotation annotation;
  annotation.key = "stadia-session-id";
  annotation.value = "session_id";

  cast_crash_storage_->SetStadiaSessionId("session_id");
  base::RunLoop().RunUntilIdle();
  VerifyLatestAnnotation(annotation);
}

}  // namespace
}  // namespace chromecast