|  | // Copyright 2019 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/developer/kcounter_inspect/vmo_file_with_update.h" | 
|  |  | 
|  | #include <lib/syslog/cpp/macros.h> | 
|  |  | 
|  | #include <gtest/gtest.h> | 
|  |  | 
|  | #include "fuchsia/kernel/cpp/fidl.h" | 
|  | #include "lib/fidl/cpp/binding_set.h" | 
|  | #include "lib/fidl/cpp/interface_handle.h" | 
|  | #include "lib/gtest/real_loop_fixture.h" | 
|  | #include "lib/sys/cpp/testing/service_directory_provider.h" | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // Stub fuchsia.kernel.Counter service that returns canned respo | 
|  | class StubKcounter : public fuchsia::kernel::Counter { | 
|  | public: | 
|  | StubKcounter() { EXPECT_EQ(zx::vmo::create(kSize, 0, &vmo_), ZX_OK); } | 
|  |  | 
|  | void GetInspectVmo(GetInspectVmoCallback callback) override { | 
|  | zx::vmo ret; | 
|  | EXPECT_EQ(vmo_.duplicate(ZX_RIGHT_SAME_RIGHTS, &ret), ZX_OK); | 
|  | fuchsia::mem::Buffer buffer{.vmo = std::move(ret), .size = kSize}; | 
|  | callback(ZX_OK, std::move(buffer)); | 
|  | } | 
|  |  | 
|  | void UpdateInspectVmo(UpdateInspectVmoCallback callback) override { | 
|  | ++update_count_; | 
|  | callback(ZX_OK); | 
|  | } | 
|  |  | 
|  | fidl::InterfaceRequestHandler<fuchsia::kernel::Counter> GetHandler() { | 
|  | return bindings_.GetHandler(this); | 
|  | } | 
|  |  | 
|  | int update_count() const { return update_count_; } | 
|  |  | 
|  | private: | 
|  | static constexpr size_t kSize = 4096; | 
|  |  | 
|  | fidl::BindingSet<fuchsia::kernel::Counter> bindings_; | 
|  | zx::vmo vmo_; | 
|  | int update_count_ = 0; | 
|  | }; | 
|  |  | 
|  | class VmoFileWithUpdateTest : public gtest::RealLoopFixture { | 
|  | public: | 
|  | void SetUp() override { | 
|  | EXPECT_EQ(loop_.StartThread(), ZX_OK); | 
|  | service_directory_provider_.reset( | 
|  | new ::sys::testing::ServiceDirectoryProvider(loop_.dispatcher())); | 
|  | stub_kcounter_.reset(new StubKcounter); | 
|  | FX_CHECK(service_directory_provider_->AddService(stub_kcounter_->GetHandler()) == ZX_OK); | 
|  | } | 
|  |  | 
|  | void TearDown() override { | 
|  | loop_.Quit(); | 
|  | loop_.JoinThreads(); | 
|  | } | 
|  |  | 
|  | async::Loop loop_{&kAsyncLoopConfigNoAttachToCurrentThread}; | 
|  | std::unique_ptr<::sys::testing::ServiceDirectoryProvider> service_directory_provider_; | 
|  | std::unique_ptr<StubKcounter> stub_kcounter_; | 
|  | thrd_t thread_; | 
|  | }; | 
|  |  | 
|  | TEST_F(VmoFileWithUpdateTest, DoNothing) { VmoFileWithUpdate noop(zx::vmo(), 0, 0, nullptr); } | 
|  |  | 
|  | TEST_F(VmoFileWithUpdateTest, EnsureUpdateCalled) { | 
|  | fuchsia::kernel::CounterSyncPtr kcounter; | 
|  | ASSERT_EQ(service_directory_provider_->service_directory()->Connect<fuchsia::kernel::Counter>( | 
|  | kcounter.NewRequest()), | 
|  | ZX_OK); | 
|  |  | 
|  | zx_status_t status; | 
|  | fuchsia::mem::Buffer buffer; | 
|  | EXPECT_EQ(kcounter->GetInspectVmo(&status, &buffer), ZX_OK); | 
|  |  | 
|  | auto vmo_file = | 
|  | std::make_unique<VmoFileWithUpdate>(std::move(buffer.vmo), 0, buffer.size, &kcounter); | 
|  | EXPECT_EQ(stub_kcounter_->update_count(), 0); | 
|  |  | 
|  | std::vector<uint8_t> data; | 
|  | EXPECT_EQ(vmo_file->ReadAt(128 /*any amount, doesn't really matter*/, 0, &data), ZX_OK); | 
|  | EXPECT_EQ(stub_kcounter_->update_count(), 1); | 
|  |  | 
|  | fuchsia::io::NodeInfo node_info; | 
|  | vmo_file->Describe(&node_info); | 
|  | EXPECT_EQ(stub_kcounter_->update_count(), 2); | 
|  | } | 
|  |  | 
|  | }  // namespace |