[modular][tests] Add a fake for Modules

This creates a fake module that gives you the the intent it was launched
with, access to its ModuleContext, as well as the capabilities granted by the
generic FakeComponent.

MF-387 #done

Change-Id: I9cbd5e61e386c8445462b296a8acc57103d7f9dc
diff --git a/peridot/public/lib/modular_test_harness/cpp/BUILD.gn b/peridot/public/lib/modular_test_harness/cpp/BUILD.gn
index c17f689..bd1ecb7 100644
--- a/peridot/public/lib/modular_test_harness/cpp/BUILD.gn
+++ b/peridot/public/lib/modular_test_harness/cpp/BUILD.gn
@@ -26,6 +26,8 @@
   sources = [
     "fake_component.cc",
     "fake_component.h",
+    "fake_module.cc",
+    "fake_module.h",
     "test_harness_fixture.cc",
     "test_harness_fixture.h",
   ]
diff --git a/peridot/public/lib/modular_test_harness/cpp/fake_module.cc b/peridot/public/lib/modular_test_harness/cpp/fake_module.cc
new file mode 100644
index 0000000..dd67273
--- /dev/null
+++ b/peridot/public/lib/modular_test_harness/cpp/fake_module.cc
@@ -0,0 +1,46 @@
+// 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 <lib/modular_test_harness/cpp/fake_module.h>
+
+namespace modular {
+namespace testing {
+
+FakeModule::FakeModule(
+    fit::function<void(fuchsia::modular::Intent)> on_intent_handled)
+    : on_intent_handled_(std::move(on_intent_handled)) {
+  ZX_ASSERT(on_intent_handled_);
+}
+
+FakeModule::~FakeModule() = default;
+
+// |modular::testing::FakeComponent|
+void FakeModule::OnCreate(fuchsia::sys::StartupInfo startup_info) {
+  component_context()->svc()->Connect(module_context_.NewRequest());
+  module_context_.set_error_handler([this](zx_status_t err) {
+    if (err != ZX_OK) {
+      ZX_PANIC("Could not connext to ModuleContext service.");
+    }
+  });
+
+  component_context()
+      ->outgoing()
+      ->AddPublicService<fuchsia::modular::IntentHandler>(
+          [this](
+              fidl::InterfaceRequest<fuchsia::modular::IntentHandler> request) {
+            bindings_.AddBinding(this, std::move(request));
+          });
+}
+
+std::vector<std::string> FakeModule::GetSandboxServices() {
+  return {"fuchsia.modular.ModuleContext"};
+}
+
+// |IntentHandler|
+void FakeModule::HandleIntent(fuchsia::modular::Intent intent) {
+  on_intent_handled_(std::move(intent));
+};
+
+}  // namespace testing
+}  // namespace modular
diff --git a/peridot/public/lib/modular_test_harness/cpp/fake_module.h b/peridot/public/lib/modular_test_harness/cpp/fake_module.h
new file mode 100644
index 0000000..cac9118
--- /dev/null
+++ b/peridot/public/lib/modular_test_harness/cpp/fake_module.h
@@ -0,0 +1,61 @@
+// 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.
+
+#ifndef LIB_MODULAR_TEST_HARNESS_CPP_FAKE_MODULE_H_
+#define LIB_MODULAR_TEST_HARNESS_CPP_FAKE_MODULE_H_
+
+#include <fuchsia/modular/cpp/fidl.h>
+#include <fuchsia/modular/testing/cpp/fidl.h>
+#include <lib/modular_test_harness/cpp/fake_component.h>
+#include <src/lib/fxl/logging.h>
+
+namespace modular {
+namespace testing {
+
+// A fake module that exposes an IntentHandler service that can be used with
+// the TestHarness. Refer to detailed documentation at test_harness_fixture.h.
+//
+// EXAMPLE USAGE
+// ...
+//
+// FakeModule fake_module;
+//
+// builder.InterceptComponent(
+//   fake_module->GetOnCreateHandler(),
+//   { .url = fake_module_url,
+//     .sandbox_services = fake_module->GetSandboxServices() });
+//
+// ...
+class FakeModule : public modular::testing::FakeComponent,
+                   fuchsia::modular::IntentHandler {
+ public:
+  // |on_intent_handled| will be invoked whenever HandleIntent() is called.
+  // If |on_intent_handled| is null, construction will fail.
+  FakeModule(fit::function<void(fuchsia::modular::Intent)> on_intent_handled);
+  ~FakeModule();
+
+  // Returns the module's |module_context_|
+  fuchsia::modular::ModuleContext* module_context() {
+    return module_context_.get();
+  }
+
+  static std::vector<std::string> GetSandboxServices();
+
+ private:
+  // |FakeComponent|
+  void OnCreate(fuchsia::sys::StartupInfo startup_info) override;
+
+  // |IntentHandler|
+  void HandleIntent(fuchsia::modular::Intent intent) override;
+
+  // A callback to be executed when HandleIntent() is invoked.
+  fit::function<void(fuchsia::modular::Intent)> on_intent_handled_;
+  fuchsia::modular::ModuleContextPtr module_context_;
+  fidl::BindingSet<fuchsia::modular::IntentHandler> bindings_;
+};
+
+}  // namespace testing
+}  // namespace modular
+
+#endif  // LIB_MODULAR_TEST_HARNESS_CPP_FAKE_MODULE_H_
diff --git a/src/modular/tests/intents_test.cc b/src/modular/tests/intents_test.cc
index 7f25981..4f02022 100644
--- a/src/modular/tests/intents_test.cc
+++ b/src/modular/tests/intents_test.cc
@@ -6,11 +6,10 @@
 #include <fuchsia/modular/testing/cpp/fidl.h>
 #include <lib/fit/function.h>
 #include <lib/fsl/vmo/strings.h>
-#include <lib/modular_test_harness/cpp/fake_component.h>
+#include <lib/modular_test_harness/cpp/fake_module.h>
 #include <lib/modular_test_harness/cpp/test_harness_fixture.h>
 #include <sdk/lib/sys/cpp/component_context.h>
 #include <sdk/lib/sys/cpp/service_directory.h>
-#include <sdk/lib/sys/cpp/testing/test_with_environment.h>
 #include <src/lib/fxl/logging.h>
 
 #include "peridot/lib/testing/session_shell_impl.h"
@@ -29,58 +28,20 @@
 constexpr char kStoryName[] = "story";
 constexpr char kIntentAction[] = "action";
 
-class TestModule : public modular::testing::FakeComponent,
-                   fuchsia::modular::IntentHandler {
- public:
-  TestModule(fit::function<void()> on_intent_handled)
-      : on_intent_handled_(std::move(on_intent_handled)) {}
-
-  // Returns the module's |module_context_|
-  fuchsia::modular::ModuleContext* module_context() {
-    return module_context_.get();
-  }
-
-  // Returns the latest handled intent
-  fuchsia::modular::Intent* latest_handled_intent() {
-    return &latest_handled_intent_;
-  }
-
- private:
-  // |modular::testing::FakeComponent|
-  void OnCreate(fuchsia::sys::StartupInfo startup_info) override {
-    component_context()->svc()->Connect(module_context_.NewRequest());
-    component_context()
-        ->outgoing()
-        ->AddPublicService<fuchsia::modular::IntentHandler>(
-            [this](fidl::InterfaceRequest<fuchsia::modular::IntentHandler>
-                       request) {
-              bindings_.AddBinding(this, std::move(request));
-            });
-  }
-
-  // |IntentHandler|
-  void HandleIntent(fuchsia::modular::Intent intent) override {
-    latest_handled_intent_ = std::move(intent);
-    on_intent_handled_();
-  };
-
-  // A callback to be executed when HandleIntent() is invoked.
-  fit::function<void()> on_intent_handled_;
-  fuchsia::modular::ModuleContextPtr module_context_;
-  fidl::BindingSet<fuchsia::modular::IntentHandler> bindings_;
-  fuchsia::modular::Intent latest_handled_intent_;
-};
-
 class IntentsTest : public modular::testing::TestHarnessFixture {
  public:
   void SetUp() override {
-    test_module_ =
-        std::make_unique<TestModule>([this]() { intent_handled_ = true; });
+    test_module_ = std::make_unique<modular::testing::FakeModule>(
+        [this](fuchsia::modular::Intent intent) {
+          latest_handled_intent_ = std::move(intent);
+          intent_handled_ = true;
+        });
     test_module_url_ = builder_.GenerateFakeUrl();
     builder_.InterceptComponent(
         test_module_->GetOnCreateHandler(),
         {.url = test_module_url_,
-         .sandbox_services = {"fuchsia.modular.ModuleContext"}});
+         .sandbox_services =
+             modular::testing::FakeModule::GetSandboxServices()});
 
     test_harness().events().OnNewComponent =
         builder_.BuildOnNewComponentHandler();
@@ -171,9 +132,10 @@
     return false;
   }
 
-  std::unique_ptr<TestModule> test_module_;
+  std::unique_ptr<modular::testing::FakeModule> test_module_;
   modular::testing::TestHarnessBuilder builder_;
   std::string test_module_url_;
+  fuchsia::modular::Intent latest_handled_intent_;
   bool intent_handled_;
 };
 
@@ -188,7 +150,7 @@
       [&] { return test_module_->is_running(); }, kTimeout));
 
   // Check that the intent handler received the intent
-  EXPECT_TRUE(IntentMatchesExpectations(test_module_->latest_handled_intent(),
+  EXPECT_TRUE(IntentMatchesExpectations(&latest_handled_intent_,
                                         kIntentParameterName,
                                         kInitialIntentParameterData));
 }
@@ -219,9 +181,8 @@
   ASSERT_TRUE(
       RunLoopWithTimeoutOrUntil([&] { return intent_handled_; }, kTimeout));
 
-  EXPECT_TRUE(IntentMatchesExpectations(test_module_->latest_handled_intent(),
-                                        kIntentParameterName,
-                                        second_module_param_data));
+  EXPECT_TRUE(IntentMatchesExpectations(
+      &latest_handled_intent_, kIntentParameterName, second_module_param_data));
 }
 
 // Launches a module that exposes an intent handler service then tests that a
@@ -251,7 +212,7 @@
   ASSERT_TRUE(
       RunLoopWithTimeoutOrUntil([&] { return intent_handled_; }, kTimeout));
 
-  EXPECT_TRUE(IntentMatchesExpectations(test_module_->latest_handled_intent(),
+  EXPECT_TRUE(IntentMatchesExpectations(&latest_handled_intent_,
                                         second_module_param_name,
                                         second_module_param_data));
 }
@@ -286,7 +247,7 @@
 
   // Check that the intercepted_module_'s latest handled intent matches the
   // initial module
-  EXPECT_TRUE(IntentMatchesExpectations(test_module_->latest_handled_intent(),
+  EXPECT_TRUE(IntentMatchesExpectations(&latest_handled_intent_,
                                         kIntentParameterName,
                                         kInitialIntentParameterData));
 }