[ledger][testing] Add Ledger instance provider.

Adds a binary that returns Ledger instances.
Will be used for tests that are built outside of peridot because those
don't have access to the necessary ledger::internal API.

TEST=None.

Change-Id: I7900cc2ffd56bacfba0ac99039dcb491f7003d25
diff --git a/bin/ledger/testing/ledger_test_instance_provider/BUILD.gn b/bin/ledger/testing/ledger_test_instance_provider/BUILD.gn
new file mode 100644
index 0000000..ab280b7
--- /dev/null
+++ b/bin/ledger/testing/ledger_test_instance_provider/BUILD.gn
@@ -0,0 +1,43 @@
+# Copyright 2017 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("//build/package.gni")
+
+executable("ledger_test_instance_provider_bin") {
+  testonly = true
+
+  sources = [
+    "ledger_test_instance_provider.cc",
+  ]
+
+  deps = [
+    "//garnet/public/lib/component/cpp/testing",
+    "//garnet/public/lib/svc/cpp",
+    "//peridot/bin/ledger/fidl",
+  ]
+
+  configs += [ "//peridot/bin/ledger:ledger_config" ]
+
+  public_deps = [
+    "//peridot/lib/convert",
+    "//peridot/lib/scoped_tmpfs",
+  ]
+}
+
+package("ledger_test_instance_provider") {
+  testonly = true
+
+  meta = [
+    {
+      path = rebase_path("meta/ledger_test_instance_provider.cmx")
+      dest = "ledger_test_instance_provider.cmx"
+    },
+  ]
+
+  binary = "ledger_test_instance_provider_bin"
+
+  deps = [
+    ":ledger_test_instance_provider_bin",
+  ]
+}
diff --git a/bin/ledger/testing/ledger_test_instance_provider/MAINTAINERS b/bin/ledger/testing/ledger_test_instance_provider/MAINTAINERS
new file mode 100644
index 0000000..e4db192
--- /dev/null
+++ b/bin/ledger/testing/ledger_test_instance_provider/MAINTAINERS
@@ -0,0 +1,2 @@
+etiennej@google.com
+jif@google.com
diff --git a/bin/ledger/testing/ledger_test_instance_provider/README.md b/bin/ledger/testing/ledger_test_instance_provider/README.md
new file mode 100644
index 0000000..d6bbd36
--- /dev/null
+++ b/bin/ledger/testing/ledger_test_instance_provider/README.md
@@ -0,0 +1,8 @@
+# Ledger Test Instance Provider
+
+This is a package containing a `ledger_test_instance_provider_bin` binary whose
+purpose is to return a single Ledger instance backed by memfs.
+
+It exists to allow tests built outside of peridot to get access to a Ledger
+instance, a task otherwise impossible because the required API
+(LedgerRepository) is not available outside of peridot.
diff --git a/bin/ledger/testing/ledger_test_instance_provider/ledger_test_instance_provider.cc b/bin/ledger/testing/ledger_test_instance_provider/ledger_test_instance_provider.cc
new file mode 100644
index 0000000..8cf5fc8
--- /dev/null
+++ b/bin/ledger/testing/ledger_test_instance_provider/ledger_test_instance_provider.cc
@@ -0,0 +1,65 @@
+// Copyright 2018 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 <cstdlib>
+
+#include <fuchsia/ledger/cpp/fidl.h>
+#include <fuchsia/ledger/internal/cpp/fidl.h>
+#include <lib/async-loop/cpp/loop.h>
+
+#include "lib/component/cpp/startup_context.h"
+#include "lib/fsl/io/fd.h"
+#include "lib/fxl/strings/string_view.h"
+#include "lib/svc/cpp/services.h"
+#include "peridot/lib/convert/convert.h"
+#include "peridot/lib/scoped_tmpfs/scoped_tmpfs.h"
+
+namespace {
+
+constexpr char kLedgerBinaryPath[] =
+    "fuchsia-pkg://fuchsia.com/ledger#meta/ledger.cmx";
+constexpr fxl::StringView kLedgerName = "test ledger instance";
+
+}  // namespace
+
+// Exposes a public service that serves an in-memory Ledger.
+// Exits once the Ledger is served.
+int main(int argc, char const *argv[]) {
+  async::Loop loop(&kAsyncLoopConfigAttachToThread);
+  std::unique_ptr<component::StartupContext> context(
+      component::StartupContext::CreateFromStartupInfo());
+
+  // Get a repository factory.
+  component::Services services;
+  fuchsia::sys::LaunchInfo launch_info;
+  launch_info.url = kLedgerBinaryPath;
+  launch_info.directory_request = services.NewRequest();
+  launch_info.arguments.push_back("--disable_reporting");
+  fuchsia::sys::ComponentControllerPtr controller;
+  context->launcher()->CreateComponent(std::move(launch_info),
+                                       controller.NewRequest());
+  fuchsia::ledger::internal::LedgerRepositoryFactoryPtr repository_factory;
+  services.ConnectToService(repository_factory.NewRequest());
+
+  // Create memfs.
+  auto memfs = std::make_unique<scoped_tmpfs::ScopedTmpFS>();
+  zx::channel memfs_channel =
+      fsl::CloneChannelFromFileDescriptor(memfs->root_fd());
+
+  // Get a repository.
+  fuchsia::ledger::internal::LedgerRepositorySyncPtr repository;
+  repository_factory->GetRepository(std::move(memfs_channel), nullptr, "",
+                                    repository.NewRequest());
+
+  // Serve the repository.
+  context->outgoing().AddPublicService<fuchsia::ledger::Ledger>(
+      [&repository](fidl::InterfaceRequest<fuchsia::ledger::Ledger> request) {
+        zx_status_t status = repository->GetLedger(
+            convert::ExtendedStringView(kLedgerName).ToArray(),
+            std::move(request));
+        exit(status == ZX_OK ? EXIT_SUCCESS : EXIT_FAILURE);
+      });
+  loop.Run();
+  return EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/bin/ledger/testing/ledger_test_instance_provider/meta/ledger_test_instance_provider.cmx b/bin/ledger/testing/ledger_test_instance_provider/meta/ledger_test_instance_provider.cmx
new file mode 100644
index 0000000..58bb40c
--- /dev/null
+++ b/bin/ledger/testing/ledger_test_instance_provider/meta/ledger_test_instance_provider.cmx
@@ -0,0 +1,10 @@
+{
+    "program": {
+        "binary": "bin/app"
+    },
+    "sandbox": {
+        "services": [
+            "fuchsia.sys.Launcher"
+        ]
+    }
+}
diff --git a/packages/tests/ledger b/packages/tests/ledger
index 2dce5f9..dbf807b 100644
--- a/packages/tests/ledger
+++ b/packages/tests/ledger
@@ -5,6 +5,7 @@
     ],
     "packages": [
         "//peridot/bin/ledger:ledger_tests",
-        "//peridot/bin/ledger:ledger_fuzzers"
+        "//peridot/bin/ledger:ledger_fuzzers",
+        "//peridot/bin/ledger/testing/ledger_test_instance_provider:ledger_test_instance_provider"
     ]
 }