Skip to content

Commit

Permalink
basic explorer transaction scenario test
Browse files Browse the repository at this point in the history
  • Loading branch information
ecioppettini committed Oct 9, 2019
1 parent 5ddbe91 commit 9161927
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 3 deletions.
1 change: 1 addition & 0 deletions jormungandr-scenario-tests/src/lib.rs
Expand Up @@ -7,6 +7,7 @@ pub mod node;
mod programs; mod programs;
#[macro_use] #[macro_use]
pub mod scenario; pub mod scenario;
mod graphql;
mod slog; mod slog;
pub mod style; pub mod style;
mod wallet; mod wallet;
Expand Down
103 changes: 102 additions & 1 deletion jormungandr-scenario-tests/src/main.rs
Expand Up @@ -55,7 +55,45 @@ fn main() {


introduction(&context); introduction(&context);


scenario_2(context.derive()); // FIXME: Can be abstracted as a macro? Maybe a procedural one (attributes?)
let tests = vec![
Test {
func: Box::new(move |context| explorer_get_transaction(context)),
name: "test explorer transaction".to_owned(),
ignore: false,
},
Test {
func: Box::new(move |context| scenario_1(context)),
name: "scenario 1".to_owned(),
ignore: false,
},
Test {
func: Box::new(move |context| scenario_2(context)),
name: "scenario 2".to_owned(),
ignore: true,
},
];

for test in tests.iter().filter(|t| !t.ignore) {
let context = context.derive();
match std::panic::catch_unwind(std::panic::AssertUnwindSafe(move || (test.func)(context))) {
Ok(()) => println!("{} PASSED", test.name),
Err(e) => {
println!("{} FAILED", test.name);

let msg = e
.downcast_ref::<String>()
.map(|e| &**e)
.or_else(|| e.downcast_ref::<&'static str>().map(|e| *e))
.unwrap_or("Unknown");

println!("Cause: {}", msg);

// Return a non 0 exit status
std::process::exit(1);
}
}
}
} }


fn introduction<R: rand_core::RngCore>(context: &Context<R>) { fn introduction<R: rand_core::RngCore>(context: &Context<R>) {
Expand Down Expand Up @@ -197,3 +235,66 @@ pub fn scenario_2(mut context: Context<ChaChaRng>) {


controller.finalize(); controller.finalize();
} }

pub fn explorer_get_transaction(mut context: Context<ChaChaRng>) {
let scenario_settings = prepare_scenario! {
"Testing the explorer",
&mut context,
topology [
"Leader1",
]
blockchain {
consensus = GenesisPraos,
number_of_slots_per_epoch = 60,
slot_duration = 1,
leaders = [ "Leader1" ],
initials = [
account "unassigned1" with 500_000_000,
account "unassigned2" with 100_000_000,
account "delegated1" with 2_000_000_000 delegates to "Leader1",
],
}
};

let mut controller = scenario_settings.build(context).unwrap();

let leader1 = controller.spawn_node("Leader1", true).unwrap();
thread::sleep(Duration::from_secs(1));

controller.monitor_nodes();

let mut wallet1 = controller.wallet("unassigned1").unwrap();
let wallet2 = controller.wallet("delegated1").unwrap();

let check = controller
.wallet_send_to(&mut wallet1, &wallet2, &leader1, 5_000.into())
.unwrap();

let id = check.fragment_id;

thread::sleep(Duration::from_secs(1));

let leader_status = leader1.wait_fragment(Duration::from_secs(2), check);

if let Ok(status) = leader_status {
if status.is_in_a_block() {
wallet1.confirm_transaction();
assert!(
leader1.get_explorer_transaction(id).is_ok(),
"transaction not found in explorer"
);
}
}

thread::sleep(Duration::from_secs(1));

leader1.shutdown().unwrap();

controller.finalize();
}

pub struct Test {
pub func: Box<dyn Fn(Context<ChaChaRng>)>,
pub name: String,
pub ignore: bool,
}
43 changes: 41 additions & 2 deletions jormungandr-scenario-tests/src/node.rs
@@ -1,12 +1,15 @@
use crate::graphql::{ExplorerTransaction, GraphQLQuery, GraphQLResponse};
use crate::{scenario::settings::NodeSetting, style, Context, NodeAlias}; use crate::{scenario::settings::NodeSetting, style, Context, NodeAlias};
use bawawa::{Control, Process}; use bawawa::{Control, Process};
use chain_impl_mockchain::{ use chain_impl_mockchain::{
block::{Block, HeaderHash}, block::{Block, HeaderHash},
fragment::{Fragment, FragmentId}, fragment::{Fragment, FragmentId},
}; };
use indicatif::ProgressBar; use indicatif::ProgressBar;
use jormungandr_lib::crypto::hash::Hash;
use jormungandr_lib::interfaces::{FragmentLog, FragmentStatus}; use jormungandr_lib::interfaces::{FragmentLog, FragmentStatus};
use rand_core::RngCore; use rand_core::RngCore;
use std::convert::TryFrom;
use std::{ use std::{
collections::HashMap, collections::HashMap,
path::PathBuf, path::PathBuf,
Expand All @@ -21,6 +24,7 @@ error_chain! {
Io(std::io::Error); Io(std::io::Error);
Reqwest(reqwest::Error); Reqwest(reqwest::Error);
BlockFormatError(chain_core::mempack::ReadError); BlockFormatError(chain_core::mempack::ReadError);
JsonError(serde_json::error::Error);
} }


errors { errors {
Expand Down Expand Up @@ -55,7 +59,8 @@ error_chain! {
} }


pub struct MemPoolCheck { pub struct MemPoolCheck {
fragment_id: FragmentId, // FIXME: Probably this shouldn't be pub, maybe as_ref?
pub fragment_id: FragmentId,
} }


pub enum NodeBlock0 { pub enum NodeBlock0 {
Expand Down Expand Up @@ -117,7 +122,7 @@ impl NodeController {
self.status() == Status::Running self.status() == Status::Running
} }


fn post(&self, path: &str, body: Vec<u8>) -> Result<reqwest::Response> { fn post(&self, path: &str, body: impl Into<reqwest::Body>) -> Result<reqwest::Response> {
self.progress_bar.log_info(format!("POST '{}'", path)); self.progress_bar.log_info(format!("POST '{}'", path));


let client = reqwest::Client::new(); let client = reqwest::Client::new();
Expand All @@ -136,6 +141,23 @@ impl NodeController {
} }
} }


fn query_explorer(&self, query: GraphQLQuery) -> Result<reqwest::Response> {
let client = reqwest::Client::new();
let res = client
.post(&format!("{}", self.base_explorer_url()))
.json(&query)
.send();

match res {
Err(err) => {
self.progress_bar
.log_err(format!("Failed to send request {}", &err));
Err(err.into())
}
Ok(r) => Ok(r),
}
}

fn get(&self, path: &str) -> Result<reqwest::Response> { fn get(&self, path: &str) -> Result<reqwest::Response> {
self.progress_bar.log_info(format!("GET '{}'", path)); self.progress_bar.log_info(format!("GET '{}'", path));


Expand All @@ -153,6 +175,13 @@ impl NodeController {
format!("http://{}/api/v0", self.settings.config.rest.listen.clone()) format!("http://{}/api/v0", self.settings.config.rest.listen.clone())
} }


fn base_explorer_url(&self) -> String {
format!(
"http://{}/explorer/graphql",
self.settings.config.rest.listen.clone()
)
}

pub fn send_fragment(&self, fragment: Fragment) -> Result<MemPoolCheck> { pub fn send_fragment(&self, fragment: Fragment) -> Result<MemPoolCheck> {
use chain_core::property::Fragment as _; use chain_core::property::Fragment as _;
use chain_core::property::Serialize as _; use chain_core::property::Serialize as _;
Expand Down Expand Up @@ -264,6 +293,16 @@ impl NodeController {
} }
} }


pub fn get_explorer_transaction(&self, fragment_id: FragmentId) -> Result<ExplorerTransaction> {
let query = ExplorerTransaction::build_query(fragment_id);

let response = self.query_explorer(query);

let response: GraphQLResponse = serde_json::from_str(&response?.text()?)?;

ExplorerTransaction::try_from(response).map_err(|e| e.into())
}

pub fn shutdown(&self) -> Result<bool> { pub fn shutdown(&self) -> Result<bool> {
let result = self.get("shutdown")?.text()?; let result = self.get("shutdown")?.text()?;


Expand Down
8 changes: 8 additions & 0 deletions jormungandr-scenario-tests/src/scenario/settings.rs
Expand Up @@ -47,6 +47,8 @@ pub struct NodeConfig {
pub rest: Rest, pub rest: Rest,


pub p2p: P2pConfig, pub p2p: P2pConfig,

pub explorer: Explorer,
} }


#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
Expand All @@ -64,6 +66,11 @@ pub struct P2pConfig {
pub trusted_peers: Vec<poldercast::Address>, pub trusted_peers: Vec<poldercast::Address>,
} }


#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Explorer {
pub enabled: bool,
}

/// Node Secret(s) /// Node Secret(s)
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct NodeSecret { pub struct NodeSecret {
Expand Down Expand Up @@ -404,6 +411,7 @@ impl NodeConfig {
NodeConfig { NodeConfig {
rest: Rest::prepare(context), rest: Rest::prepare(context),
p2p: P2pConfig::prepare(context), p2p: P2pConfig::prepare(context),
explorer: Explorer { enabled: true },
} }
} }
} }
Expand Down

0 comments on commit 9161927

Please sign in to comment.