[sessionctl] Integration test to ensure sessionctl is able to launch

TEST=fx run-test sessionctl_integration_tests
MF-139 #comment Integration test to ensure sessionctl is able to launch

Change-Id: I37b29ee30307fbea06fae8fde256a2f75d787990
diff --git a/bin/basemgr/basemgr_settings.cc b/bin/basemgr/basemgr_settings.cc
index 3cb9842..23a1612 100644
--- a/bin/basemgr/basemgr_settings.cc
+++ b/bin/basemgr/basemgr_settings.cc
@@ -16,12 +16,12 @@
 BasemgrSettings::BasemgrSettings(const fxl::CommandLine& command_line) {
   base_shell.url = command_line.GetOptionValueWithDefault(
       "base_shell",
-      "fuchsia-pkg://fuchsia.com/userpicker_base_shell#meta/userpicker_base_shell.cmx");
+      "fuchsia-pkg://fuchsia.com/userpicker_base_shell#meta/"
+      "userpicker_base_shell.cmx");
   story_shell.url =
       command_line.GetOptionValueWithDefault("story_shell", "mondrian");
   sessionmgr.url = command_line.GetOptionValueWithDefault(
-      "sessionmgr",
-      "fuchsia-pkg://fuchsia.com/sessionmgr#meta/sessionmgr.cmx");
+      "sessionmgr", "fuchsia-pkg://fuchsia.com/sessionmgr#meta/sessionmgr.cmx");
   session_shell.url = command_line.GetOptionValueWithDefault(
       "session_shell", "ermine_session_shell");
   account_provider.url = command_line.GetOptionValueWithDefault(
@@ -30,6 +30,11 @@
   disable_statistics = command_line.HasOption("disable_statistics");
   no_minfs = command_line.HasOption("no_minfs");
   test = command_line.HasOption("test");
+  run_base_shell_with_test_runner =
+      command_line.GetOptionValueWithDefault("run_base_shell_with_test_runner",
+                                             "true") == "true"
+          ? true
+          : false;
   enable_presenter = command_line.HasOption("enable_presenter");
 
   ParseShellArgs(command_line.GetOptionValueWithDefault("base_shell_args", ""),
@@ -46,7 +51,9 @@
       &session_shell.args);
 
   if (test) {
-    base_shell.args.push_back("--test");
+    if (run_base_shell_with_test_runner) {
+      base_shell.args.push_back("--test");
+    }
     story_shell.args.push_back("--test");
     sessionmgr.args.push_back("--test");
     session_shell.args.push_back("--test");
diff --git a/bin/basemgr/basemgr_settings.h b/bin/basemgr/basemgr_settings.h
index 1e91a06..45333c7 100644
--- a/bin/basemgr/basemgr_settings.h
+++ b/bin/basemgr/basemgr_settings.h
@@ -31,6 +31,7 @@
   bool disable_statistics;
   bool no_minfs;
   bool test;
+  bool run_base_shell_with_test_runner;
   bool enable_presenter;
 
  private:
diff --git a/bin/sessionctl/main.cc b/bin/sessionctl/main.cc
index ffa5a3d..4b387ef 100644
--- a/bin/sessionctl/main.cc
+++ b/bin/sessionctl/main.cc
@@ -123,9 +123,10 @@
   // See peridot/bin/sessionmgr/sessionmgr_impl.cc's definition of
   // kSessionCtlDir for "sessionctl". These must match.
   std::vector<DebugService> sessions;
-  FindDebugServicesForPath("/hub/c/sessionmgr.cmx/*/out/debug/sessionctl",
-                           kRegex, &sessions);
+  FindDebugServicesForPath(modular::kSessionCtlServiceGlobPath, kRegex,
+                           &sessions);
 
+  // Path to sessionctl service from a virtual console
   FindDebugServicesForPath(
       "/hub/r/sys/*/c/sessionmgr.cmx/*/out/debug/sessionctl", kRegex,
       &sessions);
@@ -148,8 +149,8 @@
   auto request = basemgr.NewRequest().TakeChannel();
 
   std::vector<DebugService> services;
-  FindDebugServicesForPath("/hub/c/basemgr.cmx/*/out/debug/basemgr",
-                           "basemgr.cmx", &services);
+  FindDebugServicesForPath(modular::kBasemgrDebugServiceGlobPath, "basemgr.cmx",
+                           &services);
 
   if (services.empty()) {
     return nullptr;
diff --git a/bin/sessionctl/session_ctl_constants.h b/bin/sessionctl/session_ctl_constants.h
index 9bcc580..7ccc0c3 100644
--- a/bin/sessionctl/session_ctl_constants.h
+++ b/bin/sessionctl/session_ctl_constants.h
@@ -26,6 +26,11 @@
 // Internal error string returned from SessionCtlApp.ExecuteCommand() if
 // the user does not set a required flag.
 constexpr char kGetUsageErrorString[] = "GetUsage";
+
+constexpr char kSessionCtlServiceGlobPath[] =
+    "/hub/c/sessionmgr.cmx/*/out/debug/sessionctl";
+constexpr char kBasemgrDebugServiceGlobPath[] =
+    "/hub/c/basemgr.cmx/*/out/debug/basemgr";
 }  // namespace modular
 
 #endif  // PERIDOT_BIN_SESSIONCTL_SESSION_CTL_CONSTANTS_H_
diff --git a/packages/tests/modular_integration_tests b/packages/tests/modular_integration_tests
index db78459..d5a82d3 100644
--- a/packages/tests/modular_integration_tests
+++ b/packages/tests/modular_integration_tests
@@ -36,6 +36,7 @@
         "//peridot/tests/trigger:trigger_test_agent",
         "//peridot/tests/trigger:trigger_test_module",
         "//peridot/tests/trigger:trigger_test_session_shell",
-        "//peridot/tests/session_shell:session_shell_test_session_shell"
+        "//peridot/tests/session_shell:session_shell_test_session_shell",
+        "//peridot/tests/sessionctl:sessionctl_integration_tests"
     ]
 }
diff --git a/tests/sessionctl/BUILD.gn b/tests/sessionctl/BUILD.gn
new file mode 100644
index 0000000..e137c12
--- /dev/null
+++ b/tests/sessionctl/BUILD.gn
@@ -0,0 +1,35 @@
+# 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.
+
+import("//peridot/build/tests_package.gni")
+
+executable("sessionctl_test") {
+  testonly = true
+  output_name = "sessionctl_test"
+
+  sources = [
+    "sessionctl_test.cc",
+  ]
+
+  deps = [
+    "//garnet/public/fidl/fuchsia.sys",
+    "//garnet/public/fidl/fuchsia.testing.runner",
+    "//garnet/public/lib/component/cpp",
+    "//garnet/public/lib/component/cpp/testing",
+    "//garnet/public/lib/fxl",
+    "//garnet/public/lib/fxl/test:gtest_main",
+    "//garnet/public/lib/test_runner/cpp",
+    "//peridot/bin/sessionctl:lib",
+    "//peridot/public/fidl/fuchsia.modular",
+    "//peridot/public/fidl/fuchsia.modular.internal",
+    "//peridot/public/lib/integration_testing/cpp",
+    "//third_party/googletest:gtest",
+  ]
+}
+
+hermetic_tests_package("sessionctl_integration_tests") {
+  deps = [
+    ":sessionctl_test",
+  ]
+}
diff --git a/tests/sessionctl/README.md b/tests/sessionctl/README.md
new file mode 100644
index 0000000..131b6ec
--- /dev/null
+++ b/tests/sessionctl/README.md
@@ -0,0 +1,4 @@
+# sessionctl integration test
+
+This ensures that the sessionctl service can be found in /hub after `basemgr`
+is launched.
\ No newline at end of file
diff --git a/tests/sessionctl/meta/sessionctl_test.cmx b/tests/sessionctl/meta/sessionctl_test.cmx
new file mode 100644
index 0000000..bbced21
--- /dev/null
+++ b/tests/sessionctl/meta/sessionctl_test.cmx
@@ -0,0 +1,36 @@
+{
+    "facets": {
+        "fuchsia.test": {
+            "injected-services": {
+                "fuchsia.devicesettings.DeviceSettingsManager": "fuchsia-pkg://fuchsia.com/device_settings_manager#meta/device_settings_manager.cmx",
+                "fuchsia.tracelink.Registry": "fuchsia-pkg://fuchsia.com/trace_manager#meta/trace_manager.cmx"
+            }
+        }
+    },
+    "program": {
+        "binary": "test/sessionctl_test"
+    },
+    "sandbox": {
+        "features": [
+            "shell"
+        ],
+        "services": [
+            "fuchsia.cobalt.LoggerFactory",
+            "fuchsia.modular.ComponentContext",
+            "fuchsia.modular.ModuleContext",
+            "fuchsia.modular.PuppetMaster",
+            "fuchsia.modular.SessionShellContext",
+            "fuchsia.net.LegacySocketProvider",
+            "fuchsia.sys.Environment",
+            "fuchsia.sys.Launcher",
+            "fuchsia.sys.Loader",
+            "fuchsia.testing.runner.TestRunner",
+            "fuchsia.testing.runner.TestRunnerStore",
+            "fuchsia.tracelink.Registry",
+            "fuchsia.ui.policy.Presenter",
+            "fuchsia.ui.scenic.Scenic",
+            "fuchsia.ui.viewsv1.ViewManager",
+            "fuchsia.ui.viewsv1.ViewSnapshot"
+        ]
+    }
+}
diff --git a/tests/sessionctl/sessionctl_test.cc b/tests/sessionctl/sessionctl_test.cc
new file mode 100644
index 0000000..b6f762c
--- /dev/null
+++ b/tests/sessionctl/sessionctl_test.cc
@@ -0,0 +1,73 @@
+// 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 <fuchsia/modular/cpp/fidl.h>
+#include <fuchsia/modular/internal/cpp/fidl.h>
+#include <fuchsia/sys/cpp/fidl.h>
+#include <lib/async/default.h>
+
+#include "lib/component/cpp/environment_services_helper.h"
+#include "lib/component/cpp/testing/test_util.h"
+#include "lib/component/cpp/testing/test_with_environment.h"
+#include "lib/fxl/files/directory.h"
+#include "lib/fxl/files/file.h"
+#include "lib/fxl/files/glob.h"
+#include "lib/fxl/strings/join_strings.h"
+
+#include "gtest/gtest.h"
+#include "peridot/bin/sessionctl/session_ctl_constants.h"
+
+namespace sessionctl {
+
+class SessionCtlTest : public component::testing::TestWithEnvironment {
+ protected:
+  void RunBasemgr() {
+    std::vector<std::string> args;
+    args.push_back("--test");
+    args.push_back("--run_base_shell_with_test_runner=false");
+    args.push_back(
+        "--account_provider=fuchsia-pkg://fuchsia.com/dev_token_manager#meta/"
+        "dev_token_manager.cmx");
+    args.push_back(
+        "--base_shell=fuchsia-pkg://fuchsia.com/dev_base_shell#meta/"
+        "dev_base_shell.cmx");
+    args.push_back(
+        "--session_shell=fuchsia-pkg://fuchsia.com/dev_session_shell#meta/"
+        "dev_session_shell.cmx");
+    args.push_back(
+        "--story_shell=fuchsia-pkg://fuchsia.com/dev_story_shell#meta/"
+        "dev_story_shell.cmx");
+    args.push_back("--sessionmgr_args=--use_memfs_for_ledger");
+
+    RunComponent("fuchsia-pkg://fuchsia.com/basemgr#meta/basemgr.cmx", args);
+  }
+
+  void RunComponent(const std::string& component_url,
+                    const std::vector<std::string>& args) {
+    fuchsia::sys::LaunchInfo launch_info;
+    launch_info.url = component_url;
+    for (auto arg : args) {
+      launch_info.arguments.push_back(arg);
+    }
+
+    fuchsia::sys::ComponentControllerPtr controller;
+    launcher_ptr()->CreateComponent(std::move(launch_info),
+                                    controller.NewRequest());
+    component_ptrs_.push_back(std::move(controller));
+
+    RunLoopWithTimeout(zx::sec(10));
+  }
+
+  std::vector<fuchsia::sys::ComponentControllerPtr> component_ptrs_;
+};
+
+TEST_F(SessionCtlTest, FindSessionCtlService) {
+  RunBasemgr();
+
+  files::Glob sessionctl_service(modular::kSessionCtlServiceGlobPath);
+  EXPECT_EQ(sessionctl_service.size(), 1u)
+      << modular::kSessionCtlServiceGlobPath << " expected to match once.";
+}
+
+}  // namespace sessionctl