diff --git a/Builds/VisualStudio2015/RippleD.vcxproj b/Builds/VisualStudio2015/RippleD.vcxproj
index b2e407700..f83e0351a 100644
--- a/Builds/VisualStudio2015/RippleD.vcxproj
+++ b/Builds/VisualStudio2015/RippleD.vcxproj
@@ -3279,6 +3279,10 @@
True
True
+
+ True
+ True
+
True
True
diff --git a/Builds/VisualStudio2015/RippleD.vcxproj.filters b/Builds/VisualStudio2015/RippleD.vcxproj.filters
index 8822874aa..a93564270 100644
--- a/Builds/VisualStudio2015/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2015/RippleD.vcxproj.filters
@@ -3768,6 +3768,9 @@
ripple\rpc\tests
+
+ ripple\rpc\tests
+
ripple\rpc\tests
diff --git a/src/ripple/rpc/tests/LedgerRequestRPC.test.cpp b/src/ripple/rpc/tests/LedgerRequestRPC.test.cpp
new file mode 100644
index 000000000..90a923b0e
--- /dev/null
+++ b/src/ripple/rpc/tests/LedgerRequestRPC.test.cpp
@@ -0,0 +1,159 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of rippled: https://github.com/ripple/rippled
+ Copyright (c) 2012-2016 Ripple Labs Inc.
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#include
+#include
+#include
+#include
+#include
+
+namespace ripple {
+
+namespace RPC {
+
+class LedgerRequestRPC_test : public beast::unit_test::suite
+{
+public:
+ void testLedgerRequest()
+ {
+ using namespace test::jtx;
+
+ Env env(*this);
+
+ env.close();
+ env.close();
+ expect(env.current()->info().seq == 5);
+
+ {
+ // arbitrary text is converted to 0.
+ auto const result = env.rpc("ledger_request", "arbitrary_text");
+ expect(RPC::contains_error(result[jss::result]) &&
+ result[jss::result][jss::error_message] ==
+ "Ledger index too small");
+ }
+
+ {
+ auto const result = env.rpc("ledger_request", "-1");
+ expect(RPC::contains_error(result[jss::result]) &&
+ result[jss::result][jss::error_message] ==
+ "Ledger index too small");
+ }
+
+ {
+ auto const result = env.rpc("ledger_request", "0");
+ expect(RPC::contains_error(result[jss::result]) &&
+ result[jss::result][jss::error_message] ==
+ "Ledger index too small");
+ }
+
+ {
+ auto const result = env.rpc("ledger_request", "1");
+ expect(!RPC::contains_error(result[jss::result]) &&
+ result[jss::result][jss::ledger_index] == 1 &&
+ result[jss::result].isMember(jss::ledger));
+ expect(result[jss::result][jss::ledger].
+ isMember(jss::ledger_hash) &&
+ result[jss::result][jss::ledger]
+ [jss::ledger_hash].isString());
+ }
+
+ {
+ auto const result = env.rpc("ledger_request", "2");
+ expect(!RPC::contains_error(result[jss::result]) &&
+ result[jss::result][jss::ledger_index] == 2 &&
+ result[jss::result].isMember(jss::ledger));
+ expect(result[jss::result][jss::ledger].
+ isMember(jss::ledger_hash) &&
+ result[jss::result][jss::ledger]
+ [jss::ledger_hash].isString());
+ }
+
+ {
+ auto const result = env.rpc("ledger_request", "3");
+ expect(!RPC::contains_error(result[jss::result]) &&
+ result[jss::result][jss::ledger_index] == 3 &&
+ result[jss::result].isMember(jss::ledger));
+ expect(result[jss::result][jss::ledger].
+ isMember(jss::ledger_hash) &&
+ result[jss::result][jss::ledger]
+ [jss::ledger_hash].isString());
+
+ auto const ledgerHash = result[jss::result]
+ [jss::ledger][jss::ledger_hash].asString();
+
+ {
+ // Intentionally shadow `result` here to avoid reuing it.
+ auto const result = env.rpc("ledger_request", ledgerHash);
+ expect(!RPC::contains_error(result[jss::result]) &&
+ result[jss::result][jss::ledger_index] == 3 &&
+ result[jss::result].isMember(jss::ledger));
+ expect(result[jss::result][jss::ledger].
+ isMember(jss::ledger_hash) &&
+ result[jss::result][jss::ledger]
+ [jss::ledger_hash] == ledgerHash);
+ }
+ }
+
+ {
+ std::string ledgerHash(64, 'q');
+
+ auto const result = env.rpc("ledger_request", ledgerHash);
+
+ expect(RPC::contains_error(result[jss::result]) &&
+ result[jss::result][jss::error_message] ==
+ "Invalid field 'ledger_hash'.");
+ }
+
+ {
+ std::string ledgerHash(64, '1');
+
+ auto const result = env.rpc("ledger_request", ledgerHash);
+
+ log << result;
+ expect(!RPC::contains_error(result[jss::result]) &&
+ result[jss::result][jss::have_header] == false);
+ }
+
+ {
+ auto const result = env.rpc("ledger_request", "4");
+ expect(RPC::contains_error(result[jss::result]) &&
+ result[jss::result][jss::error_message] ==
+ "Ledger index too large");
+ }
+
+ {
+ auto const result = env.rpc("ledger_request", "5");
+ expect(RPC::contains_error(result[jss::result]) &&
+ result[jss::result][jss::error_message] ==
+ "Ledger index too large");
+ }
+
+ }
+
+ void run ()
+ {
+ testLedgerRequest ();
+ }
+};
+
+BEAST_DEFINE_TESTSUITE(LedgerRequestRPC,app,ripple);
+
+} // RPC
+} // ripple
+
diff --git a/src/ripple/unity/rpcx.cpp b/src/ripple/unity/rpcx.cpp
index 24c7def4f..8ff4ecc42 100644
--- a/src/ripple/unity/rpcx.cpp
+++ b/src/ripple/unity/rpcx.cpp
@@ -100,5 +100,6 @@
#include
#include
+#include
#include
#include