Skip to content

Commit

Permalink
[feature] #4116: Add test for plain == scale encoded verification for…
Browse files Browse the repository at this point in the history
… status request (#4284)

* [feature] add test for json == scale verification

Signed-off-by: VAmuzing <amuzik95@gmail.com>
  • Loading branch information
VAmuzing authored Mar 13, 2024
1 parent 7014f53 commit be0e67f
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 6 deletions.
16 changes: 12 additions & 4 deletions client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,18 @@ impl TransactionResponseHandler {
pub struct StatusResponseHandler;

impl StatusResponseHandler {
fn handle(resp: &Response<Vec<u8>>) -> Result<Status> {
pub(crate) fn handle(resp: &Response<Vec<u8>>) -> Result<Status> {
let slice = Self::handle_raw(resp)?;
serde_json::from_slice(slice).wrap_err("Failed to decode body")
}

fn handle_raw(resp: &Response<Vec<u8>>) -> Result<&Vec<u8>> {
if resp.status() != StatusCode::OK {
return Err(ResponseReport::with_msg("Unexpected status response", resp)
.unwrap_or_else(core::convert::identity)
.into());
}
serde_json::from_slice(resp.body()).wrap_err("Failed to decode body")
Ok(resp.body())
}
}

Expand Down Expand Up @@ -1029,9 +1034,12 @@ impl Client {
/// # Errors
/// Fails if sending request or decoding fails
pub fn get_status(&self) -> Result<Status> {
let req = self.prepare_status_request::<DefaultRequestBuilder>();
let req = self
.prepare_status_request::<DefaultRequestBuilder>()
.header(http::header::ACCEPT, "application/x-parity-scale");
let resp = req.build()?.send()?;
StatusResponseHandler::handle(&resp)
let scaled_resp = StatusResponseHandler::handle_raw(&resp).cloned()?;
DecodeAll::decode_all(&mut scaled_resp.as_slice()).map_err(|err| eyre!("{err}"))
}

/// Prepares http-request to implement [`Self::get_status`] on your own.
Expand Down
14 changes: 14 additions & 0 deletions client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@ mod query_builder;

/// Module containing sample configurations for tests and benchmarks.
pub mod samples {
use eyre::Result;
use iroha_telemetry::metrics::Status;
use url::Url;

use crate::{
client::{Client, StatusResponseHandler},
config::{
Config, DEFAULT_TRANSACTION_NONCE, DEFAULT_TRANSACTION_STATUS_TIMEOUT,
DEFAULT_TRANSACTION_TIME_TO_LIVE,
},
crypto::KeyPair,
data_model::ChainId,
http_default::DefaultRequestBuilder,
};

/// Get sample client configuration.
Expand All @@ -36,6 +40,16 @@ pub mod samples {
transaction_add_nonce: DEFAULT_TRANSACTION_NONCE,
}
}

/// Gets network status seen from the peer in json format
///
/// # Errors
/// Fails if sending request or decoding fails
pub fn get_status_json(client: &Client) -> Result<Status> {
let req = client.prepare_status_request::<DefaultRequestBuilder>();
let resp = req.build()?.send()?;
StatusResponseHandler::handle(&resp)
}
}

pub use iroha_crypto as crypto;
Expand Down
1 change: 1 addition & 0 deletions client/tests/integration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ mod queries;
mod roles;
mod set_parameter;
mod sorting;
mod status_response;
mod transfer_asset;
mod triggers;
mod tx_chain_id;
Expand Down
57 changes: 57 additions & 0 deletions client/tests/integration/status_response.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use std::str::FromStr as _;

use eyre::Result;
use iroha_client::{data_model::prelude::*, samples::get_status_json};
use iroha_telemetry::metrics::Status;
use test_network::*;

fn status_eq_excluding_uptime_and_queue(lhs: &Status, rhs: &Status) -> bool {
lhs.peers == rhs.peers
&& lhs.blocks == rhs.blocks
&& lhs.txs_accepted == rhs.txs_accepted
&& lhs.txs_rejected == rhs.txs_rejected
&& lhs.view_changes == rhs.view_changes
}

#[test]
fn json_and_scale_statuses_equality() -> Result<()> {
let (_rt, network, client) = Network::start_test_with_runtime(2, Some(11_200));
wait_for_genesis_committed(&network.clients(), 0);

let json_status_zero = get_status_json(&client).unwrap();

let scale_status_zero_decoded = client.get_status().unwrap();

assert!(
status_eq_excluding_uptime_and_queue(&json_status_zero, &scale_status_zero_decoded),
"get_status() result is not equal to decoded get_status_scale_encoded()"
);

let coins = ["xor", "btc", "eth", "doge"];

let domain_id: DomainId = "test_domain".parse().expect("Should be valid");
let account_id = AccountId::new(domain_id, "test_account".parse().expect("Should be valid"));

for coin in coins {
let asset_definition_id = AssetDefinitionId::from_str(&format!("{coin}#wonderland"))?;
let create_asset =
Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone()));
let mint_asset = Mint::asset_numeric(
1234u32,
AssetId::new(asset_definition_id, account_id.clone()),
);
let instructions: [InstructionBox; 2] = [create_asset.into(), mint_asset.into()];
client.submit_all(instructions)?;
}

let json_status_coins = get_status_json(&client).unwrap();

let scale_status_coins_decoded = client.get_status().unwrap();

assert!(
status_eq_excluding_uptime_and_queue(&json_status_coins, &scale_status_coins_decoded),
"get_status() result is not equal to decoded get_status_scale_encoded()"
);

Ok(())
}
15 changes: 13 additions & 2 deletions telemetry/src/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{
time::{Duration, SystemTime},
};

use parity_scale_codec::{Compact, Encode};
use parity_scale_codec::{Compact, Decode, Encode};
use prometheus::{
core::{AtomicU64, GenericGauge, GenericGaugeVec},
Encoder, Histogram, HistogramOpts, HistogramVec, IntCounter, IntCounterVec, Opts, Registry,
Expand All @@ -32,8 +32,19 @@ impl Encode for Uptime {
}
}

impl Decode for Uptime {
fn decode<I: parity_scale_codec::Input>(
input: &mut I,
) -> Result<Self, parity_scale_codec::Error> {
let (secs, nanos) = <(Compact<u64>, u32)>::decode(input)?;
Ok(Self(
Duration::from_secs(secs.0) + Duration::from_nanos(nanos.into()),
))
}
}

/// Response body for GET status request
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, Encode)]
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, Encode, Decode)]
pub struct Status {
/// Number of currently connected peers excluding the reporting peer
#[codec(compact)]
Expand Down

0 comments on commit be0e67f

Please sign in to comment.