1 // Copyright 2020 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_FUCHSIA_TEST_COMPONENT_CONTEXT_FOR_PROCESS_H_ 6 #define BASE_FUCHSIA_TEST_COMPONENT_CONTEXT_FOR_PROCESS_H_ 7 8 #include <fidl/fuchsia.io/cpp/fidl.h> 9 10 #include <memory> 11 12 #include "base/base_export.h" 13 #include "base/containers/span.h" 14 #include "base/strings/string_piece.h" 15 16 namespace sys { 17 class ComponentContext; 18 class OutgoingDirectory; 19 class ServiceDirectory; 20 } // namespace sys 21 22 namespace base { 23 24 class FilteredServiceDirectory; 25 26 // Replaces the process-global sys::ComponentContext (as returned by the 27 // base::ComponentContextForProcess() function) with an empty instance which the 28 // calling test can configure, and restores the original when deleted. 29 // 30 // The test ComponentContext runs on the test main thread, which means that: 31 // - Tests using TestComponentContextForProcess must instantiate a 32 // [SingleThread]TaskEnvironment with UI or IO main-thread-type. 33 // - If all services exposed via the test ComponentContext run on the test 34 // main thread, and the code under test does as well, then RunUntilIdle() can 35 // normally be used to "flush" any pending FIDL requests and related work. 36 // Note that this is not true if any services, or code under test, use threads 37 // or processes! 38 // 39 // The test ComponentContext is typically instantiated within a test body or 40 // test base-class: 41 // 42 // TEST(MyFunkyTest, IsFunky) { 43 // TestComponentContextForProcess test_context; 44 // // Configure the |test_context|. 45 // // Run tests of code that uses ComponentContextForProcess(). 46 // } 47 // 48 // By default created context doesn't expose any services. Services from the 49 // original process-global ComponentContext (usually the environment in which 50 // the test process is running), can be exposed through the |test_context| with 51 // AddServices(), during test setup: 52 // 53 // test_context.AddServices({fuchsia::memorypressure::Provider::Name_, ...}); 54 // // ... Execute tests which use fuchsia.memorypressure.Provider ... 55 // 56 // Alternatively InitialState::kCloneAll can be passed to the constructor to 57 // expose all services listed in /svc, e.g.: 58 // 59 // TestComponentContextForProcess test_context( 60 // TestComponentContextForProcess::InitialState::kCloneAll); 61 // 62 // Fake/mock implementations can be exposed via additional_services(): 63 // 64 // ScopedServiceBinding<funky::Service> binding( 65 // test_context.additional_services(), &funky_implementation); 66 // // ... Execute tests which use funky.Service. 67 // 68 // Services published to the process' ComponentContext by code-under-test 69 // can be accessed via published_services(): 70 // 71 // funky::HamsterPtr hamster_service; 72 // test_context.published_services()->Connect(hamster_service.NewRequest()); 73 // // ... Execute tests which exercise the funky.Hamster implementation. 74 // 75 class BASE_EXPORT TestComponentContextForProcess { 76 public: 77 enum class InitialState { 78 kEmpty, 79 kCloneAll, 80 }; 81 82 explicit TestComponentContextForProcess( 83 InitialState initial_state = InitialState::kEmpty); 84 ~TestComponentContextForProcess(); 85 86 TestComponentContextForProcess(const TestComponentContextForProcess&) = 87 delete; 88 TestComponentContextForProcess& operator=( 89 const TestComponentContextForProcess&) = delete; 90 91 // Returns an OutgoingDirectory into which additional services may be 92 // published for use by the code-under test. 93 sys::OutgoingDirectory* additional_services(); 94 95 // Allows the specified service(s) from the original ComponentContext to be 96 // exposed via the test default ComponentContext. 97 void AddService(const base::StringPiece service); 98 void AddServices(base::span<const base::StringPiece> services); 99 100 // Returns the directory of services that the code under test has published 101 // to its outgoing service directory. published_services()102 std::shared_ptr<sys::ServiceDirectory> published_services() const { 103 return published_services_; 104 } 105 106 fidl::UnownedClientEnd<fuchsia_io::Directory> published_services_natural(); 107 108 private: 109 std::unique_ptr<sys::ComponentContext> old_context_; 110 111 std::unique_ptr<FilteredServiceDirectory> context_services_; 112 std::shared_ptr<sys::ServiceDirectory> published_services_; 113 fidl::ClientEnd<fuchsia_io::Directory> published_services_natural_; 114 }; 115 116 } // namespace base 117 118 #endif // BASE_FUCHSIA_TEST_COMPONENT_CONTEXT_FOR_PROCESS_H_ 119