Skip to content

Commit

Permalink
NPG 1943 explorer address test (#4078)
Browse files Browse the repository at this point in the history
* first address test

* adding transaction by address tests

* adding more checks

* adding more comments

* adding test for block0

* fix clippy and fmt

* fix clippy

* fix ending line

* fix white space

* fix clippy
  • Loading branch information
kukkok3 authored Sep 1, 2022
1 parent e819875 commit 6d6b1bb
Show file tree
Hide file tree
Showing 10 changed files with 268 additions and 21 deletions.
2 changes: 1 addition & 1 deletion explorer/src/api/graphql/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,7 @@ impl Transaction {
.await;

if block_hashes.is_empty() {
return Err(ApiError::NotFound(format!("transaction not found: {}", &id,)).into());
Err(ApiError::NotFound(format!("transaction not found: {}", &id,)).into())
} else {
Ok(Transaction {
id,
Expand Down
1 change: 1 addition & 0 deletions explorer/src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub struct LogSettings {
/// some code executes before the logs are initialized.
pub type LogInfoMsg = Option<Vec<String>>;

#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, Debug, PartialEq)]
pub struct LogSettingsEntry {
pub level: LevelFilter,
Expand Down
3 changes: 1 addition & 2 deletions jormungandr/src/blockchain/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,7 @@ async fn process_network_block(
Err(Error::MissingParentBlock(parent_hash))
}
PreCheckedHeader::HeaderWithCache { parent_ref, .. } => {
let r = check_and_apply_block(blockchain, parent_ref, block, watch_msg_box).await;
r
check_and_apply_block(blockchain, parent_ref, block, watch_msg_box).await
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion jormungandr/src/jrpc/eth_filter/filters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl EvmFilters {
}
}

#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Eq)]
pub enum FilterType {
Block,
PendingTransaction,
Expand Down
2 changes: 1 addition & 1 deletion jormungandr/src/settings/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct LogSettings {
/// some code executes before the logs are initialized.
pub type LogInfoMsg = Option<Vec<String>>;

#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct LogSettingsEntry {
pub level: LevelFilter,
pub format: LogFormat,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
query TransactionsByAddress($bech32: String!){
tip {
transactionsByAddress(addressBech32: $bech32) {
totalCount
edges {
node {
id
blocks{id date{...blockDate}}
#inputs{amount address{id}} // BUG NPG-2869
#outputs{amount address{id}}
#certificate
}
}
}
}
}

fragment blockDate on BlockDate{
epoch{id}
slot
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ use graphql_client::GraphQLQuery;
)]
pub struct Address;

#[derive(GraphQLQuery)]
#[graphql(
query_path = "resources/explorer/graphql/transactions_by_address.graphql",
schema_path = "resources/explorer/graphql/schema.graphql",
response_derives = "Debug"
)]
pub struct TransactionsByAddress;

#[derive(GraphQLQuery)]
#[graphql(
query_path = "resources/explorer/graphql/allblocks.graphql",
Expand Down
19 changes: 17 additions & 2 deletions testing/jormungandr-automation/src/jormungandr/explorer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ use self::{
data::{
address, all_blocks, all_stake_pools, all_vote_plans, blocks_by_chain_length, epoch,
last_block, settings, stake_pool, transaction_by_id, transaction_by_id_certificates,
Address, AllBlocks, AllStakePools, AllVotePlans, BlocksByChainLength, Epoch, LastBlock,
Settings, StakePool, TransactionById, TransactionByIdCertificates,
transactions_by_address, Address, AllBlocks, AllStakePools, AllVotePlans,
BlocksByChainLength, Epoch, LastBlock, Settings, StakePool, TransactionById,
TransactionByIdCertificates, TransactionsByAddress,
},
};
use crate::testing::configuration::get_explorer_app;
Expand Down Expand Up @@ -325,6 +326,20 @@ impl Explorer {
Ok(response_body)
}

pub fn transactions_address<S: Into<String>>(
&self,
bech32_address: S,
) -> Result<Response<transactions_by_address::ResponseData>, ExplorerError> {
let query = TransactionsByAddress::build_query(transactions_by_address::Variables {
bech32: bech32_address.into(),
});
self.print_request(&query);
let response = self.client.run(query).map_err(ExplorerError::ClientError)?;
let response_body: Response<transactions_by_address::ResponseData> = response.json()?;
self.print_log(&response_body);
Ok(response_body)
}

pub fn current_time(&self) -> BlockDate {
self.last_block().unwrap().block_date()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use super::data::{settings::SettingsSettingsFees, transaction_by_id_certificates::*};
use super::data::{
address::AddressAddress, settings::SettingsSettingsFees, transaction_by_id_certificates::*,
transactions_by_address::TransactionsByAddressTipTransactionsByAddress,
};
use crate::jormungandr::explorer::data::transaction_by_id_certificates::PayloadType as expPayloadType;
use bech32::FromBase32;
use chain_addr::AddressReadable;
Expand All @@ -13,7 +16,8 @@ use chain_impl_mockchain::{
transaction::{AccountIdentifier, InputEnum, Transaction},
vote::PayloadType,
};
use std::num::NonZeroU64;
use jormungandr_lib::interfaces::{Address, FragmentStatus};
use std::{collections::HashMap, num::NonZeroU64};
use thiserror::Error;

#[derive(Debug, Error)]
Expand Down Expand Up @@ -916,6 +920,44 @@ impl ExplorerVerifier {
);
}

pub fn assert_address(address: Address, explorer_address: AddressAddress) {
assert_eq!(address.to_string(), explorer_address.id);
}

pub fn assert_transactions_address(
fragment_statuses: HashMap<String, (&Fragment, &FragmentStatus)>,
explorer_transactions: TransactionsByAddressTipTransactionsByAddress,
) {
if fragment_statuses.is_empty() {
assert!(explorer_transactions.total_count == 0);
} else {
assert_eq!(
fragment_statuses.len() as i64 + 1,
explorer_transactions.total_count
);
};

assert!(explorer_transactions.edges.is_some());

assert_eq!(
fragment_statuses.len(),
explorer_transactions.edges.as_ref().unwrap().len()
);

for edges in explorer_transactions.edges.unwrap().iter() {
let node = &edges.as_ref().unwrap().node;
assert!(fragment_statuses.get(&node.id.to_string()).is_some());
let fragment_status = fragment_statuses.get(&node.id.to_string()).unwrap().1;
assert!(
matches!(fragment_status, FragmentStatus::InABlock { date, block: _ } if
date.epoch() == node.blocks[0].date.epoch.id.parse::<u32>().unwrap() && date.slot() == node.blocks[0].date.slot.parse::<u32>().unwrap()
)
);
let fragment = fragment_statuses.get(&node.id.to_string()).unwrap().0;
assert_eq!(fragment.hash().to_string(), node.id.to_string());
}
}

fn decode_bech32_pk(bech32_public_key: &str) -> PublicKey<Ed25519> {
let (_, data, _variant) = bech32::decode(bech32_public_key).unwrap();
let dat = Vec::from_base32(&data).unwrap();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
use crate::startup;
use assert_fs::TempDir;
use chain_impl_mockchain::{block::BlockDate, fragment::Fragment};
use jormungandr_automation::{
jcli::JCli,
jormungandr::{explorer::configuration::ExplorerParams, ConfigurationBuilder},
jormungandr::{
explorer::{configuration::ExplorerParams, verifier::ExplorerVerifier},
ConfigurationBuilder, Starter,
},
};
use jormungandr_lib::interfaces::ActiveSlotCoefficient;
//TODO still wip
#[ignore]
use jormungandr_lib::interfaces::{ActiveSlotCoefficient, FragmentStatus};
use jortestkit::process::Wait;
use std::{collections::HashMap, time::Duration};
use thor::TransactionHash;

#[test]
pub fn explorer_address_test() {
let _jcli: JCli = Default::default();
let sender = thor::Wallet::default();
let _receiver = thor::Wallet::default();
let _transaction_value = 1_000;
let address_bech32_prefix = "ca".to_string();
let address_bech32_prefix = sender.address().0;

let mut config = ConfigurationBuilder::new();
config.with_consensus_genesis_praos_active_slot_coeff(ActiveSlotCoefficient::MAXIMUM);
Expand All @@ -32,9 +36,166 @@ pub fn explorer_address_test() {
explorer_address.errors.unwrap()
);

assert_eq!(
explorer_address.data.unwrap().address.id,
sender.address().to_string(),
"Addresses is not the same"
ExplorerVerifier::assert_address(sender.address(), explorer_address.data.unwrap().address);
}

#[test]
pub fn explorer_transactions_not_existing_address_test() {
let jcli: JCli = Default::default();
let sender = thor::Wallet::default();
let receiver = thor::Wallet::default();
let test_address = thor::Wallet::default();
let transaction_value = 1_000;
let attempts_number = 20;

let mut config = ConfigurationBuilder::new();
config.with_consensus_genesis_praos_active_slot_coeff(ActiveSlotCoefficient::MAXIMUM);

let (jormungandr, _initial_stake_pools) =
startup::start_stake_pool(&[sender.clone()], &[sender.clone()], &mut config).unwrap();

let transaction = thor::FragmentBuilder::new(
&jormungandr.genesis_block_hash(),
&jormungandr.fees(),
BlockDate::first().next_epoch(),
)
.transaction(&sender, receiver.address(), transaction_value.into())
.unwrap();

let wait = Wait::new(Duration::from_secs(3), attempts_number);

jcli.fragment_sender(&jormungandr)
.send(&transaction.encode())
.assert_in_block_with_wait(&wait);

let explorer_process = jormungandr.explorer(ExplorerParams::default());
let explorer = explorer_process.client();

let explorer_address = explorer
.transactions_address(test_address.address().to_string())
.unwrap();

assert!(
explorer_address.errors.is_none(),
"{:?}",
explorer_address.errors.unwrap()
);
let explorer_transactions_by_address =
explorer_address.data.unwrap().tip.transactions_by_address;

ExplorerVerifier::assert_transactions_address(HashMap::new(), explorer_transactions_by_address);
}

// BUG NPG-2869
// TODO comment out the fields (inputs,outputs, certificate) in transaction_by_address.graphql when the bug is fixed
// add the verifier for those fields (inputs,outputs,certificate) in explorer_verifier
#[test]
pub fn explorer_transactions_address_test() {
let jcli: JCli = Default::default();
let mut sender = thor::Wallet::default();
let receiver = thor::Wallet::default();
let transaction1_value = 1_000;
let transaction2_value = 2_0;
let transaction3_value = 3_0;
let attempts_number = 20;
let temp_dir = TempDir::new().unwrap();
let mut fragments = vec![];

let config = ConfigurationBuilder::default()
.with_funds(vec![sender.to_initial_fund(1_000_000)])
.build(&temp_dir);

let jormungandr = Starter::new()
.temp_dir(temp_dir)
.config(config)
.start()
.expect("Cannot start jormungandr");

let wait = Wait::new(Duration::from_secs(3), attempts_number);

let fragment_builder = thor::FragmentBuilder::new(
&jormungandr.genesis_block_hash(),
&jormungandr.fees(),
BlockDate::first().next_epoch(),
);

let transaction_1 = fragment_builder
.transaction(&sender, receiver.address(), transaction1_value.into())
.unwrap();

jcli.fragment_sender(&jormungandr)
.send(&transaction_1.encode())
.assert_in_block_with_wait(&wait);

fragments.push(&transaction_1);

sender.confirm_transaction();

let transaction_2 = fragment_builder
.transaction(&sender, receiver.address(), transaction2_value.into())
.unwrap();

jcli.fragment_sender(&jormungandr)
.send(&transaction_2.encode())
.assert_in_block_with_wait(&wait);

fragments.push(&transaction_2);

let transaction_3 = fragment_builder
.transaction(&receiver, sender.address(), transaction3_value.into())
.unwrap();

jcli.fragment_sender(&jormungandr)
.send(&transaction_3.encode())
.assert_in_block_with_wait(&wait);

fragments.push(&transaction_3);

let mut fragments_log = jcli.rest().v0().message().logs(jormungandr.rest_uri());

fragments_log.sort();
fragments.sort_by_key(|a| a.hash());

// make and hashmap of tuples of fragment and fragment status
let mut fragments_statuses: HashMap<_, _> = fragments
.iter()
.zip(fragments_log.iter())
.map(|(&a, b)| (a.hash().to_string(), (a, b.status())))
.collect();

let block0 = jormungandr.block0_configuration().to_block();
let block0fragment: &Fragment = block0.fragments().last().unwrap();
let block0_fragment_status = FragmentStatus::InABlock {
date: block0.header().block_date().into(),
block: block0.header().block_content_hash().into(),
};
fragments_statuses.insert(
block0fragment.hash().to_string(),
(block0fragment, &block0_fragment_status),
);

let explorer_process = jormungandr.explorer(ExplorerParams::default());
let explorer = explorer_process.client();

assert!(explorer
.transactions_address(sender.address().to_string())
.is_ok());

let explorer_address = explorer
.transactions_address(sender.address().to_string())
.unwrap();

assert!(
explorer_address.errors.is_none(),
"{:?}",
explorer_address.errors.unwrap()
);

let explorer_transactions_by_address =
explorer_address.data.unwrap().tip.transactions_by_address;

ExplorerVerifier::assert_transactions_address(
fragments_statuses,
explorer_transactions_by_address,
);
}

0 comments on commit 6d6b1bb

Please sign in to comment.