Skip to content

Commit

Permalink
Test refactoring and additions to support API Testing (#205)
Browse files Browse the repository at this point in the history
* move wallet tests into integration module in advance of further test creation, add v3 API

* rustfmt

* fix return value from incorrect mask supplied

* rustfmt

* rework send request call some

* rustfmt

* more refactoring, turn proxy startup + wallet init into macros

* rustfmt

* move sample requests into subdirectories

* add missing wallet files, change gitignore
  • Loading branch information
yeastplume authored Aug 13, 2019
1 parent f8c316a commit 62d976f
Show file tree
Hide file tree
Showing 16 changed files with 1,011 additions and 671 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,4 @@ target
grin.log
wallet.seed
test_output
wallet*
.idea/
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,10 @@ grin_wallet_util = { path = "./util", version = "2.1.0-beta.1" }

[build-dependencies]
built = "0.3"

[dev-dependencies]
url = "1.7.2"
serde = "1"
serde_derive = "1"
serde_json = "1"
easy-jsonrpc = "0.5.1"
85 changes: 82 additions & 3 deletions controller/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use serde_json;
use std::net::SocketAddr;
use std::sync::Arc;

use crate::apiwallet::{Foreign, ForeignCheckMiddlewareFn, ForeignRpc, Owner, OwnerRpc};
use crate::apiwallet::{Foreign, ForeignCheckMiddlewareFn, ForeignRpc, Owner, OwnerRpc, OwnerRpcS};
use easy_jsonrpc;
use easy_jsonrpc::{Handler, MaybeReply};

Expand Down Expand Up @@ -126,8 +126,6 @@ where
C: NodeClient + 'static,
K: Keychain + 'static,
{
let api_handler_v2 = OwnerAPIHandlerV2::new(wallet.clone());

let mut router = Router::new();
if api_secret.is_some() {
let api_basic_auth =
Expand All @@ -139,10 +137,18 @@ where
router.add_middleware(basic_auth_middleware);
}

let api_handler_v2 = OwnerAPIHandlerV2::new(wallet.clone());

let api_handler_v3 = OwnerAPIHandlerV3::new(wallet.clone());

router
.add_route("/v2/owner", Arc::new(api_handler_v2))
.map_err(|_| ErrorKind::GenericError("Router failed to add route".to_string()))?;

router
.add_route("/v3/owner", Arc::new(api_handler_v3))
.map_err(|_| ErrorKind::GenericError("Router failed to add route".to_string()))?;

// If so configured, add the foreign API to the same port
if owner_api_include_foreign.unwrap_or(false) {
warn!("Starting HTTP Foreign API on Owner server at {}.", addr);
Expand Down Expand Up @@ -277,6 +283,79 @@ where
}
}

/// V3 API Handler/Wrapper for owner functions, which include a secure
/// mode + lifecycle functions
pub struct OwnerAPIHandlerV3<L, C, K>
where
L: WalletLCProvider<'static, C, K> + 'static,
C: NodeClient + 'static,
K: Keychain + 'static,
{
/// Wallet instance
pub wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K> + 'static>>>,
}

impl<L, C, K> OwnerAPIHandlerV3<L, C, K>
where
L: WalletLCProvider<'static, C, K>,
C: NodeClient + 'static,
K: Keychain + 'static,
{
/// Create a new owner API handler for GET methods
pub fn new(
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K> + 'static>>>,
) -> OwnerAPIHandlerV3<L, C, K> {
OwnerAPIHandlerV3 { wallet }
}

fn call_api(
&self,
req: Request<Body>,
api: Owner<'static, L, C, K>,
) -> Box<dyn Future<Item = serde_json::Value, Error = Error> + Send> {
Box::new(parse_body(req).and_then(move |val: serde_json::Value| {
let owner_api_s = &api as &dyn OwnerRpcS;
match owner_api_s.handle_request(val) {
MaybeReply::Reply(r) => ok(r),
MaybeReply::DontReply => {
// Since it's http, we need to return something. We return [] because jsonrpc
// clients will parse it as an empty batch response.
ok(serde_json::json!([]))
}
}
}))
}

fn handle_post_request(&self, req: Request<Body>) -> WalletResponseFuture {
let api = Owner::new(self.wallet.clone());
Box::new(
self.call_api(req, api)
.and_then(|resp| ok(json_response_pretty(&resp))),
)
}
}

impl<L, C, K> api::Handler for OwnerAPIHandlerV3<L, C, K>
where
L: WalletLCProvider<'static, C, K> + 'static,
C: NodeClient + 'static,
K: Keychain + 'static,
{
fn post(&self, req: Request<Body>) -> ResponseFuture {
Box::new(
self.handle_post_request(req)
.and_then(|r| ok(r))
.or_else(|e| {
error!("Request Error: {:?}", e);
ok(create_error_response(e))
}),
)
}

fn options(&self, _req: Request<Body>) -> ResponseFuture {
Box::new(ok(create_ok_response("{}")))
}
}
/// V2 API Handler/Wrapper for foreign functions
pub struct ForeignAPIHandlerV2<L, C, K>
where
Expand Down
21 changes: 13 additions & 8 deletions libwallet/src/api_impl/owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ where

let mut validated = false;
if refresh_from_node {
validated = update_outputs(w, keychain_mask, false);
validated = update_outputs(w, keychain_mask, false)?;
}

Ok((
Expand Down Expand Up @@ -116,7 +116,7 @@ where

let mut validated = false;
if refresh_from_node {
validated = update_outputs(w, keychain_mask, false);
validated = update_outputs(w, keychain_mask, false)?;
}

Ok((
Expand All @@ -141,7 +141,7 @@ where

let mut validated = false;
if refresh_from_node {
validated = update_outputs(w, keychain_mask, false);
validated = update_outputs(w, keychain_mask, false)?;
}

let wallet_info = updater::retrieve_info(&mut *w, &parent_key_id, minimum_confirmations)?;
Expand Down Expand Up @@ -418,7 +418,7 @@ where
K: Keychain + 'a,
{
let parent_key_id = w.parent_key_id();
if !update_outputs(w, keychain_mask, false) {
if !update_outputs(w, keychain_mask, false)? {
return Err(ErrorKind::TransactionCancellationError(
"Can't contact running Grin node. Not Cancelling.",
))?;
Expand Down Expand Up @@ -489,7 +489,7 @@ where
C: NodeClient + 'a,
K: Keychain + 'a,
{
update_outputs(w, keychain_mask, true);
update_outputs(w, keychain_mask, true)?;
w.check_repair(keychain_mask, delete_unconfirmed)
}

Expand Down Expand Up @@ -528,15 +528,20 @@ fn update_outputs<'a, T: ?Sized, C, K>(
w: &mut T,
keychain_mask: Option<&SecretKey>,
update_all: bool,
) -> bool
) -> Result<bool, Error>
where
T: WalletBackend<'a, C, K>,
C: NodeClient + 'a,
K: Keychain + 'a,
{
let parent_key_id = w.parent_key_id();
match updater::refresh_outputs(&mut *w, keychain_mask, &parent_key_id, update_all) {
Ok(_) => true,
Err(_) => false,
Ok(_) => Ok(true),
Err(e) => {
if let ErrorKind::InvalidKeychainMask = e.kind() {
return Err(e);
}
Ok(false)
}
}
}
Loading

0 comments on commit 62d976f

Please sign in to comment.