Skip to content

Commit 233658d

Browse files
author
Nikita Khateev
committed
Merge branch 'feature/nullpay-tests'
2 parents 73eea6e + 5f89a3d commit 233658d

File tree

6 files changed

+270
-135
lines changed

6 files changed

+270
-135
lines changed

libnullpay/src/payment_method.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ pub mod add_request_fees {
6767
let total_payments = _count_total_payments(&outputs_json);
6868

6969
let err = if total_amount >= total_payments + fee {
70+
match parse_req_id_from_request(req_json.clone()) {
71+
Err(ec) => return ec,
72+
_ => ()
73+
};
7074
//we have enough money for this txn, give it back
7175
let seq_no = payment_ledger::add_txn(inputs_json.clone(), outputs_json.clone());
7276

libnullpay/src/services/response_storage.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,19 @@ lazy_static! {
88
}
99

1010
pub fn add_response(request: String, response: String) -> Result<(), ErrorCode> {
11-
let val = str_to_val(request.as_str())?;
12-
let object = val_to_obj(&val)?;
13-
let req_id = get_val_from_obj(object, "reqId")?;
14-
let req_id = val_to_u64(req_id)?;
15-
11+
let req_id = parse_req_id_from_request(request)?;
1612
let mut responses = RESPONSES.lock().unwrap();
1713
responses.insert(req_id.to_string(), response);
1814
Ok(())
1915
}
2016

17+
pub fn parse_req_id_from_request(request: String) -> Result<u64, ErrorCode> {
18+
let val = str_to_val(request.as_str())?;
19+
let object = val_to_obj(&val)?;
20+
let req_id = get_val_from_obj(object, "reqId")?;
21+
val_to_u64(req_id)
22+
}
23+
2124
pub fn get_response(response: &str) -> Result<String, ErrorCode> {
2225
let val = str_to_val(response)?;
2326
let object = val_to_obj(&val)?;

libnullpay/tests/payments.rs

Lines changed: 254 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ extern crate nullpay;
66

77
#[macro_use]
88
extern crate lazy_static;
9-
#[macro_use]
109
extern crate log;
1110

1211
#[macro_use]
@@ -21,6 +20,7 @@ use utils::types::*;
2120
use utils::ledger;
2221
use utils::pool;
2322
use utils::did;
23+
use nullpay::ErrorCode;
2424

2525
use std::collections::HashMap;
2626

@@ -87,7 +87,7 @@ mod high_cases {
8787
let addresses = payments_utils::create_addresses(vec!["{}", "{}"], wallet_handle, PAYMENT_METHOD_NAME);
8888
let mint: Vec<(String, i32, Option<&str>)> = addresses.clone().into_iter().enumerate().map(|(i, addr)| (addr, (i+1) as i32, None)).collect();
8989

90-
payments_utils::mint_tokens(mint, wallet_handle, pool_handle, PAYMENT_METHOD_NAME, SUBMITTER_DID);
90+
payments_utils::mint_tokens(mint, wallet_handle, pool_handle, SUBMITTER_DID);
9191

9292
let (req_utxo_1, payment_method) = payments::build_get_utxo_request(wallet_handle, SUBMITTER_DID, addresses.get(0).unwrap().as_str()).unwrap();
9393
let resp_utxo_1 = ledger::submit_request(pool_handle, req_utxo_1.as_str()).unwrap();
@@ -111,6 +111,24 @@ mod high_cases {
111111
wallet::close_wallet(wallet_handle).unwrap();
112112
test_utils::cleanup_storage();
113113
}
114+
115+
#[test]
116+
pub fn get_utxo_works_for_no_utxo() {
117+
test_utils::cleanup_storage();
118+
plugin::init_plugin();
119+
let wallet_handle = wallet::create_and_open_wallet(POOL_NAME, None).unwrap();
120+
let pool_handle = pool::create_and_open_pool_ledger(POOL_NAME).unwrap();
121+
122+
let nonexistant_addr = "pay:null:no-addr";
123+
let res = payments_utils::get_utxos_with_balance(vec![nonexistant_addr.to_string()], wallet_handle, pool_handle, SUBMITTER_DID);
124+
125+
let res_vec = res.get(nonexistant_addr).unwrap();
126+
assert_eq!(res_vec.len(), 0);
127+
128+
pool::close(pool_handle).unwrap();
129+
wallet::close_wallet(wallet_handle).unwrap();
130+
test_utils::cleanup_storage();
131+
}
114132
}
115133

116134
mod mint {
@@ -132,9 +150,9 @@ mod high_cases {
132150

133151
let outputs = serde_json::to_string(&mint).unwrap();
134152

135-
let (req, payment_method) = payments::build_mint_req(wallet_handle, SUBMITTER_DID, outputs.as_str()).unwrap();
153+
let (req, _) = payments::build_mint_req(wallet_handle, SUBMITTER_DID, outputs.as_str()).unwrap();
136154

137-
let mint_resp = ledger::submit_request(pool_handle, req.as_str()).unwrap();
155+
ledger::submit_request(pool_handle, req.as_str()).unwrap();
138156

139157
let utxos = payments_utils::get_utxos_with_balance(addresses.clone(), wallet_handle, pool_handle,SUBMITTER_DID);
140158

@@ -171,7 +189,7 @@ mod high_cases {
171189
let addresses = payments_utils::create_addresses(vec!["{}", "{}"], wallet_handle, PAYMENT_METHOD_NAME);
172190

173191
let mint: Vec<(String, i32, Option<&str>)> = addresses.clone().into_iter().enumerate().map(|(i, addr)| (addr, ((i+2)*10) as i32, None)).collect();
174-
payments_utils::mint_tokens(mint, wallet_handle, pool_handle, PAYMENT_METHOD_NAME, my_did.as_str());
192+
payments_utils::mint_tokens(mint, wallet_handle, pool_handle, my_did.as_str());
175193

176194
let utxos = payments_utils::get_utxos_with_balance(addresses.clone(), wallet_handle, pool_handle, my_did.as_str());
177195

@@ -188,7 +206,7 @@ mod high_cases {
188206
}];
189207
let outputs = serde_json::to_string(&outputs).unwrap();
190208

191-
let (nym_req_with_fees, payment_method) = payments::add_request_fees(wallet_handle, my_did.as_str(), nym_req.as_str(), inputs.as_str(), outputs.as_str()).unwrap();
209+
let (nym_req_with_fees, _) = payments::add_request_fees(wallet_handle, my_did.as_str(), nym_req.as_str(), inputs.as_str(), outputs.as_str()).unwrap();
192210

193211
let nym_response = ledger::sign_and_submit_request(pool_handle, wallet_handle, trustee_did.as_str(), nym_req_with_fees.as_str()).unwrap();
194212

@@ -200,7 +218,14 @@ mod high_cases {
200218
let new_utxo = created_utxos.get(0).unwrap();
201219
assert_eq!(new_utxo.amount, 19);
202220

203-
//TODO: check that there is 2 UTXO for the second address and 0 UTXO for the first one
221+
let utxo_map = payments_utils::get_utxos_with_balance(addresses.clone(), wallet_handle, pool_handle, SUBMITTER_DID);
222+
let utxo_1 = utxo_map.get(addresses.get(0).unwrap()).unwrap();
223+
assert!(utxo_1.is_empty());
224+
let utxo_2 = utxo_map.get(addresses.get(1).unwrap()).unwrap();
225+
assert_eq!(utxo_2.len(), 2);
226+
let amounts: Vec<i32> = utxo_2.into_iter().map(|info| info.amount).collect();
227+
assert!(amounts.contains(&30));
228+
assert!(amounts.contains(&19));
204229

205230
pool::close(pool_handle).unwrap();
206231
wallet::close_wallet(wallet_handle).unwrap();
@@ -221,7 +246,7 @@ mod high_cases {
221246
let addresses = payments_utils::create_addresses(vec!["{}", "{}"], wallet_handle, PAYMENT_METHOD_NAME);
222247

223248
let mint: Vec<(String, i32, Option<&str>)> = addresses.clone().into_iter().enumerate().map(|(i, addr)| (addr, ((i+2)*10) as i32, None)).collect();
224-
payments_utils::mint_tokens(mint, wallet_handle, pool_handle, PAYMENT_METHOD_NAME, SUBMITTER_DID);
249+
payments_utils::mint_tokens(mint, wallet_handle, pool_handle, SUBMITTER_DID);
225250

226251
let utxos = payments_utils::get_utxos_with_balance(addresses.clone(), wallet_handle, pool_handle, SUBMITTER_DID);
227252

@@ -256,6 +281,22 @@ mod high_cases {
256281

257282
let change_utxo_end = change_utxo.split("_").last().unwrap();
258283
assert!(addresses.get(0).unwrap().to_string().ends_with(change_utxo_end));
284+
285+
let utxo_map = payments_utils::get_utxos_with_balance(addresses.clone(), wallet_handle, pool_handle, SUBMITTER_DID);
286+
let utxo_1 = utxo_map.get(addresses.get(0).unwrap()).unwrap();
287+
assert_eq!(utxo_1.len(), 1);
288+
let amounts: Vec<i32> = utxo_1.into_iter().map(|info| info.amount).collect();
289+
assert!(amounts.contains(&1));
290+
291+
let utxo_2 = utxo_map.get(addresses.get(1).unwrap()).unwrap();
292+
assert_eq!(utxo_2.len(), 2);
293+
let amounts: Vec<i32> = utxo_2.into_iter().map(|info| info.amount).collect();
294+
assert!(amounts.contains(&19));
295+
assert!(amounts.contains(&30));
296+
297+
pool::close(pool_handle).unwrap();
298+
wallet::close_wallet(wallet_handle).unwrap();
299+
test_utils::cleanup_storage();
259300
}
260301
}
261302

@@ -270,7 +311,7 @@ mod high_cases {
270311
let pool_handle = pool::create_and_open_pool_ledger(POOL_NAME).unwrap();
271312

272313
let fees_req = payments::build_set_txn_fees_req(wallet_handle, SUBMITTER_DID, PAYMENT_METHOD_NAME, FEES).unwrap();
273-
let fees_resp = ledger::submit_request(pool_handle, fees_req.as_str()).unwrap();
314+
ledger::submit_request(pool_handle, fees_req.as_str()).unwrap();
274315

275316
let fees_stored = payments_utils::get_request_fees(wallet_handle, pool_handle, SUBMITTER_DID, PAYMENT_METHOD_NAME);
276317

@@ -308,4 +349,208 @@ mod high_cases {
308349
test_utils::cleanup_storage();
309350
}
310351
}
352+
}
353+
354+
mod medium_cases {
355+
use super::*;
356+
357+
mod add_request_fees {
358+
use super::*;
359+
360+
#[test]
361+
pub fn add_request_works_for_insufficient_funds() {
362+
test_utils::cleanup_storage();
363+
plugin::init_plugin();
364+
let wallet_handle = wallet::create_and_open_wallet(POOL_NAME, None).unwrap();
365+
let pool_handle = pool::create_and_open_pool_ledger(POOL_NAME).unwrap();
366+
367+
let (trustee_did, _) = did::create_and_store_my_did(wallet_handle, Some(TRUSTEE_SEED)).unwrap();
368+
let (my_did, my_vk) = did::create_and_store_my_did(wallet_handle, None).unwrap();
369+
let nym_req = ledger::build_nym_request(&trustee_did, &my_did, &my_vk, "aaa", "TRUSTEE").unwrap();
370+
371+
let addresses = payments_utils::create_addresses(vec!["{}", "{}"], wallet_handle, PAYMENT_METHOD_NAME);
372+
373+
let mint: Vec<(String, i32, Option<&str>)> = addresses.clone().into_iter().enumerate().map(|(i, addr)| (addr, i as i32, None)).collect();
374+
payments_utils::mint_tokens(mint, wallet_handle, pool_handle, my_did.as_str());
375+
376+
payments_utils::set_request_fees(wallet_handle, pool_handle, SUBMITTER_DID, PAYMENT_METHOD_NAME, r#"{"1": 10, "101": 10}"#);
377+
378+
let utxos = payments_utils::get_utxos_with_balance(addresses.clone(), wallet_handle, pool_handle, SUBMITTER_DID);
379+
380+
let addr_1 = addresses.get(0).unwrap();
381+
let utxos_1: Vec<String> = utxos.get(addr_1.as_str()).unwrap().into_iter().map(|info| info.input.clone()).collect();
382+
let inputs = serde_json::to_string(&utxos_1).unwrap();
383+
384+
let outputs = vec![UTXOOutput{
385+
payment_address: addresses.get(1).unwrap().to_string(),
386+
amount: 19,
387+
extra: None
388+
}, UTXOOutput {
389+
payment_address: addresses.get(0).unwrap().to_string(),
390+
amount: 1,
391+
extra: None
392+
}];
393+
let outputs = serde_json::to_string(&outputs).unwrap();
394+
395+
let (nym_req_with_fees, payment_method) = payments::add_request_fees(wallet_handle, SUBMITTER_DID, nym_req.as_str(), inputs.as_str(), outputs.as_str()).unwrap();
396+
let nym_resp = ledger::sign_and_submit_request(pool_handle, wallet_handle, trustee_did.as_str(), nym_req_with_fees.as_str()).unwrap();
397+
let nym_resp_parsed_err = payments::parse_response_with_fees(payment_method.as_str(), nym_resp.as_str()).unwrap_err();
398+
399+
assert_eq!(nym_resp_parsed_err, ErrorCode::PaymentInsufficientFundsError);
400+
401+
pool::close(pool_handle).unwrap();
402+
wallet::close_wallet(wallet_handle).unwrap();
403+
test_utils::cleanup_storage();
404+
}
405+
406+
#[test]
407+
pub fn add_request_fees_works_for_request_without_operation() {
408+
test_utils::cleanup_storage();
409+
plugin::init_plugin();
410+
let wallet_handle = wallet::create_and_open_wallet(POOL_NAME, None).unwrap();
411+
let pool_handle = pool::create_and_open_pool_ledger(POOL_NAME).unwrap();
412+
413+
let addresses = payments_utils::create_addresses(vec!["{}", "{}"], wallet_handle, PAYMENT_METHOD_NAME);
414+
let mint: Vec<(String, i32, Option<&str>)> = addresses.clone().into_iter().enumerate().map(|(i, addr)| (addr, i as i32, None)).collect();
415+
payments_utils::mint_tokens(mint, wallet_handle, pool_handle, SUBMITTER_DID);
416+
417+
payments_utils::set_request_fees(wallet_handle, pool_handle, SUBMITTER_DID, PAYMENT_METHOD_NAME, FEES);
418+
419+
let utxos = payments_utils::get_utxos_with_balance(addresses.clone(), wallet_handle, pool_handle, SUBMITTER_DID);
420+
421+
let addr_1 = addresses.get(0).unwrap();
422+
let utxos_1: Vec<String> = utxos.get(addr_1.as_str()).unwrap().into_iter().map(|info| info.input.clone()).collect();
423+
let inputs = serde_json::to_string(&utxos_1).unwrap();
424+
425+
let outputs = vec![UTXOOutput{
426+
payment_address: addresses.get(1).unwrap().to_string(),
427+
amount: 19,
428+
extra: None
429+
}, UTXOOutput {
430+
payment_address: addresses.get(0).unwrap().to_string(),
431+
amount: 1,
432+
extra: None
433+
}];
434+
let outputs = serde_json::to_string(&outputs).unwrap();
435+
436+
let nym_req_err = payments::add_request_fees(wallet_handle, SUBMITTER_DID, EMPTY_OBJECT, inputs.as_str(), outputs.as_str()).unwrap_err();
437+
assert_eq!(nym_req_err, ErrorCode::CommonInvalidStructure);
438+
439+
//IMPORTANT: check that utxo cache stays the same
440+
let utxos_after = payments_utils::get_utxos_with_balance(addresses.clone(), wallet_handle, pool_handle, SUBMITTER_DID);
441+
assert_eq!(utxos, utxos_after);
442+
443+
pool::close(pool_handle).unwrap();
444+
wallet::close_wallet(wallet_handle).unwrap();
445+
test_utils::cleanup_storage();
446+
}
447+
448+
#[test]
449+
pub fn add_request_fees_works_for_request_without_req_id() {
450+
test_utils::cleanup_storage();
451+
plugin::init_plugin();
452+
let wallet_handle = wallet::create_and_open_wallet(POOL_NAME, None).unwrap();
453+
let pool_handle = pool::create_and_open_pool_ledger(POOL_NAME).unwrap();
454+
455+
let addresses = payments_utils::create_addresses(vec!["{}", "{}"], wallet_handle, PAYMENT_METHOD_NAME);
456+
let mint: Vec<(String, i32, Option<&str>)> = addresses.clone().into_iter().enumerate().map(|(i, addr)| (addr, i as i32, None)).collect();
457+
payments_utils::mint_tokens(mint, wallet_handle, pool_handle, SUBMITTER_DID);
458+
459+
payments_utils::set_request_fees(wallet_handle, pool_handle, SUBMITTER_DID, PAYMENT_METHOD_NAME, FEES);
460+
461+
let utxos = payments_utils::get_utxos_with_balance(addresses.clone(), wallet_handle, pool_handle, SUBMITTER_DID);
462+
463+
let addr_1 = addresses.get(0).unwrap();
464+
let utxos_1: Vec<String> = utxos.get(addr_1.as_str()).unwrap().into_iter().map(|info| info.input.clone()).collect();
465+
let inputs = serde_json::to_string(&utxos_1).unwrap();
466+
467+
let outputs = vec![UTXOOutput{
468+
payment_address: addresses.get(1).unwrap().to_string(),
469+
amount: 19,
470+
extra: None
471+
}, UTXOOutput {
472+
payment_address: addresses.get(0).unwrap().to_string(),
473+
amount: 1,
474+
extra: None
475+
}];
476+
let outputs = serde_json::to_string(&outputs).unwrap();
477+
478+
let nym_req_err = payments::add_request_fees(wallet_handle, SUBMITTER_DID, r#"{"reqId": 111}"#, inputs.as_str(), outputs.as_str()).unwrap_err();
479+
assert_eq!(nym_req_err, ErrorCode::CommonInvalidStructure);
480+
481+
//IMPORTANT: check that utxo cache stays the same
482+
let utxos_after = payments_utils::get_utxos_with_balance(addresses.clone(), wallet_handle, pool_handle, SUBMITTER_DID);
483+
assert_eq!(utxos, utxos_after);
484+
485+
pool::close(pool_handle).unwrap();
486+
wallet::close_wallet(wallet_handle).unwrap();
487+
test_utils::cleanup_storage();
488+
}
489+
}
490+
491+
mod fees {
492+
use super::*;
493+
494+
#[test]
495+
pub fn build_set_txn_fees_works_for_invalid_json() {
496+
test_utils::cleanup_storage();
497+
plugin::init_plugin();
498+
let wallet_handle = wallet::create_and_open_wallet(POOL_NAME, None).unwrap();
499+
let pool_handle = pool::create_and_open_pool_ledger(POOL_NAME).unwrap();
500+
501+
let err = payments::build_set_txn_fees_req(wallet_handle, SUBMITTER_DID, PAYMENT_METHOD_NAME, "{1}").unwrap_err();
502+
assert_eq!(err, ErrorCode::CommonInvalidStructure);
503+
504+
pool::close(pool_handle).unwrap();
505+
wallet::close_wallet(wallet_handle).unwrap();
506+
test_utils::cleanup_storage();
507+
}
508+
}
509+
510+
mod payment {
511+
use super::*;
512+
513+
#[test]
514+
pub fn payments_work_for_insufficient_funds() {
515+
test_utils::cleanup_storage();
516+
plugin::init_plugin();
517+
let wallet_handle = wallet::create_and_open_wallet(POOL_NAME, None).unwrap();
518+
let pool_handle = pool::create_and_open_pool_ledger(POOL_NAME).unwrap();
519+
520+
let addresses = payments_utils::create_addresses(vec!["{}", "{}"], wallet_handle, PAYMENT_METHOD_NAME);
521+
522+
let mint: Vec<(String, i32, Option<&str>)> = addresses.clone().into_iter().enumerate().map(|(i, addr)| (addr, ((i+2)*10) as i32, None)).collect();
523+
payments_utils::mint_tokens(mint, wallet_handle, pool_handle, SUBMITTER_DID);
524+
525+
let utxos = payments_utils::get_utxos_with_balance(addresses.clone(), wallet_handle, pool_handle, SUBMITTER_DID);
526+
527+
let addr_1 = addresses.get(0).unwrap();
528+
let utxos_1: Vec<String> = utxos.get(addr_1.as_str()).unwrap().into_iter().map(|info| info.input.clone()).collect();
529+
let inputs = serde_json::to_string(&utxos_1).unwrap();
530+
531+
let outputs = vec![UTXOOutput{
532+
payment_address: addresses.get(1).unwrap().to_string(),
533+
amount: 119,
534+
extra: None
535+
}, UTXOOutput {
536+
payment_address: addresses.get(0).unwrap().to_string(),
537+
amount: 1,
538+
extra: None
539+
}];
540+
let outputs = serde_json::to_string(&outputs).unwrap();
541+
542+
let (payment_req, payment_method) = payments::build_payment_req(wallet_handle, SUBMITTER_DID, inputs.as_str(), outputs.as_str()).unwrap();
543+
let payment_resp = ledger::submit_request(pool_handle, payment_req.as_str()).unwrap();
544+
let payment_err = payments::parse_payment_response(payment_method.as_str(), payment_resp.as_str()).unwrap_err();
545+
assert_eq!(payment_err, ErrorCode::PaymentInsufficientFundsError);
546+
547+
let utxos_after = payments_utils::get_utxos_with_balance(addresses.clone(), wallet_handle, pool_handle, SUBMITTER_DID);
548+
assert_eq!(utxos, utxos_after);
549+
550+
pool::close(pool_handle).unwrap();
551+
wallet::close_wallet(wallet_handle).unwrap();
552+
test_utils::cleanup_storage();
553+
}
554+
}
555+
311556
}

libnullpay/tests/utils/callbacks.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@ lazy_static! {
1414
static ref COMMAND_HANDLE_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
1515
}
1616

17-
lazy_static! {
18-
static ref CLOSURE_CB_MAP: Mutex<HashMap<i32, i32>> = Default::default();
19-
}
20-
2117
pub fn _closure_to_cb_ec() -> (Receiver<ErrorCode>, i32,
2218
Option<extern fn(command_handle: i32,
2319
err: ErrorCode)>) {

0 commit comments

Comments
 (0)