| // 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. | 
 |  | 
 | #ifndef SRC_LIB_LOADER_SERVICE_LOADER_SERVICE_TEST_FIXTURE_H_ | 
 | #define SRC_LIB_LOADER_SERVICE_LOADER_SERVICE_TEST_FIXTURE_H_ | 
 |  | 
 | #include <fuchsia/ldsvc/llcpp/fidl.h> | 
 | #include <lib/async-loop/cpp/loop.h> | 
 | #include <lib/async-loop/default.h> | 
 | #include <lib/memfs/cpp/vnode.h> | 
 | #include <lib/zx/resource.h> | 
 |  | 
 | #include <memory> | 
 | #include <vector> | 
 |  | 
 | #include <fbl/ref_ptr.h> | 
 | #include <fbl/unique_fd.h> | 
 | #include <gtest/gtest.h> | 
 |  | 
 | #include "src/lib/loader_service/loader_service.h" | 
 | #include "src/lib/testing/loop_fixture/real_loop_fixture.h" | 
 |  | 
 | namespace loader { | 
 | namespace test { | 
 |  | 
 | struct TestDirectoryEntry { | 
 |   std::string path; | 
 |   std::string file_contents; | 
 |   bool executable; | 
 |  | 
 |   TestDirectoryEntry(std::string path, std::string file_contents, bool executable) | 
 |       : path(std::move(path)), file_contents(std::move(file_contents)), executable(executable) {} | 
 | }; | 
 |  | 
 | class LoaderServiceTest : public gtest::RealLoopFixture { | 
 |  public: | 
 |   LoaderServiceTest() | 
 |       : fs_loop_(&kAsyncLoopConfigNoAttachToCurrentThread), | 
 |         loader_loop_(&kAsyncLoopConfigNoAttachToCurrentThread) {} | 
 |  | 
 |   virtual void TearDown() override; | 
 |  | 
 |   // Either this or CreateTestDirectory should only be called once per test case. This would be in | 
 |   // SetUp but we want to allow test defined directory contents. | 
 |   template <typename T> | 
 |   void CreateTestLoader(std::vector<TestDirectoryEntry> config, std::shared_ptr<T>* loader) { | 
 |     fbl::unique_fd root_fd; | 
 |     ASSERT_NO_FATAL_FAILURE(CreateTestDirectory(std::move(config), &root_fd)); | 
 |     const ::testing::TestInfo* const test_info = | 
 |         ::testing::UnitTest::GetInstance()->current_test_info(); | 
 |     *loader = T::Create(loader_loop_.dispatcher(), std::move(root_fd), test_info->name()); | 
 |   } | 
 |  | 
 |   // Either this or CreateTestLoader should only be called once per test case. This would be in | 
 |   // SetUp but we want to allow test defined directory contents. | 
 |   void CreateTestDirectory(std::vector<TestDirectoryEntry> config, fbl::unique_fd* root_fd); | 
 |  | 
 |   // Add a directory entry to the given VnodeDir. Can be used to add entries mid-test case using | 
 |   // root_dir() below. | 
 |   void AddDirectoryEntry(const fbl::RefPtr<memfs::VnodeDir>& root, TestDirectoryEntry entry); | 
 |  | 
 |   // Exercise a LoadObject call and assert that the result matches `expected`. | 
 |   // | 
 |   // This takes a non-const reference because LLCPP SyncClient's generated methods are non-const. | 
 |   void LoadObject(fidl::WireSyncClient<fuchsia_ldsvc::Loader>& client, std::string name, | 
 |                   zx::status<std::string> expected); | 
 |  | 
 |   // Exercise a Config call and assert that the result matches `expected`. | 
 |   // | 
 |   // This takes a non-const reference because LLCPP SyncClient's generated methods are non-const. | 
 |   void Config(fidl::WireSyncClient<fuchsia_ldsvc::Loader>& client, std::string config, | 
 |               zx::status<zx_status_t> expected); | 
 |  | 
 |   // Helper function to interact with fuchsia.kernel.VmexResource | 
 |   static zx::status<zx::unowned_resource> GetVmexResource(); | 
 |  | 
 |   async::Loop& fs_loop() { return fs_loop_; } | 
 |   async::Loop& loader_loop() { return loader_loop_; } | 
 |   fbl::RefPtr<memfs::VnodeDir>& root_dir() { return root_dir_; } | 
 |  | 
 |  private: | 
 |   async::Loop fs_loop_; | 
 |   async::Loop loader_loop_; | 
 |   std::unique_ptr<memfs::Vfs> vfs_; | 
 |   fbl::RefPtr<memfs::VnodeDir> root_dir_; | 
 | }; | 
 |  | 
 | }  // namespace test | 
 | }  // namespace loader | 
 |  | 
 | #endif  // SRC_LIB_LOADER_SERVICE_LOADER_SERVICE_TEST_FIXTURE_H_ |