feat: Add tokens balance check and component diff
This commit is contained in:
@@ -1,36 +1,19 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use colored::Colorize;
|
||||
use hex::FromHex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Represents a hexadecimal byte string: Check if we already have a default impl for this
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(from = "String", into = "String")]
|
||||
pub struct HexBytes(Vec<u8>);
|
||||
|
||||
impl From<String> for HexBytes {
|
||||
fn from(s: String) -> Self {
|
||||
let s = s
|
||||
.trim_start_matches("0x")
|
||||
.to_lowercase();
|
||||
HexBytes(Vec::from_hex(s).unwrap_or_default())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HexBytes> for String {
|
||||
fn from(val: HexBytes) -> Self {
|
||||
format!("0x{}", hex::encode(val.0))
|
||||
}
|
||||
}
|
||||
use similar::{ChangeTag, TextDiff};
|
||||
use tycho_core::{dto::ProtocolComponent, Bytes};
|
||||
|
||||
/// Represents a ProtocolComponent with its main attributes
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct ProtocolComponentExpectation {
|
||||
pub id: String,
|
||||
pub tokens: Vec<HexBytes>,
|
||||
pub tokens: Vec<Bytes>,
|
||||
#[serde(default)]
|
||||
pub static_attributes: HashMap<String, HexBytes>,
|
||||
pub creation_tx: HexBytes,
|
||||
pub static_attributes: HashMap<String, Bytes>,
|
||||
pub creation_tx: Bytes,
|
||||
}
|
||||
|
||||
/// Represents a ProtocolComponent with test configuration
|
||||
@@ -42,6 +25,98 @@ pub struct ProtocolComponentWithTestConfig {
|
||||
pub skip_simulation: bool,
|
||||
}
|
||||
|
||||
impl ProtocolComponentExpectation {
|
||||
pub fn compare(&self, other: &ProtocolComponent, colorize_output: bool) -> Option<String> {
|
||||
let mut diffs = Vec::new();
|
||||
|
||||
// Compare id
|
||||
if self.id != other.id {
|
||||
let diff = self.format_diff("id", &self.id, &other.id, colorize_output);
|
||||
diffs.push(format!("Field 'id' mismatch for {}:\n{}", self.id, diff));
|
||||
}
|
||||
|
||||
// Compare tokens
|
||||
if self.tokens != other.tokens {
|
||||
let self_tokens = format!("{:?}", self.tokens);
|
||||
let other_tokens = format!("{:?}", other.tokens);
|
||||
let diff = self.format_diff("tokens", &self_tokens, &other_tokens, colorize_output);
|
||||
diffs.push(format!("Field 'tokens' mismatch for {}:\n{}", self.id, diff));
|
||||
}
|
||||
|
||||
// Compare static_attributes
|
||||
for (key, value) in &self.static_attributes {
|
||||
let other_value = other.static_attributes.get(key);
|
||||
match other_value {
|
||||
Some(other_value) => {
|
||||
if value != other_value {
|
||||
let self_value = format!("{:?}", value);
|
||||
let other_value = format!("{:?}", other_value);
|
||||
let diff = self.format_diff(
|
||||
"static_attributes",
|
||||
&self_value,
|
||||
&other_value,
|
||||
colorize_output,
|
||||
);
|
||||
diffs.push(format!(
|
||||
"Field 'static_attributes' mismatch for {}:\n{}",
|
||||
self.id, diff
|
||||
));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
diffs.push(format!(
|
||||
"Field 'static_attributes' mismatch for {}: Key '{}' not found",
|
||||
self.id, key
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Compare creation_tx
|
||||
if self.creation_tx != other.creation_tx {
|
||||
let self_tx = format!("{}", self.creation_tx.clone());
|
||||
let other_tx = format!("{}", other.creation_tx.clone());
|
||||
let diff = self.format_diff("creation_tx", &self_tx, &other_tx, colorize_output);
|
||||
diffs.push(format!("Field 'creation_tx' mismatch for {}:\n{}", self.id, diff));
|
||||
}
|
||||
|
||||
if diffs.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(diffs.join("\n"))
|
||||
}
|
||||
}
|
||||
fn format_diff(&self, _field_name: &str, left: &str, right: &str, colorize: bool) -> String {
|
||||
let diff = TextDiff::from_lines(left, right);
|
||||
|
||||
let mut result = String::new();
|
||||
for change in diff.iter_all_changes() {
|
||||
let formatted = match change.tag() {
|
||||
ChangeTag::Delete => {
|
||||
if colorize {
|
||||
format!("{}", format!("-{}", change.value().trim_end()).red())
|
||||
} else {
|
||||
format!("-{}", change.value().trim_end())
|
||||
}
|
||||
}
|
||||
ChangeTag::Insert => {
|
||||
if colorize {
|
||||
format!("{}", format!("+{}", change.value().trim_end()).green())
|
||||
} else {
|
||||
format!("+{}", change.value().trim_end())
|
||||
}
|
||||
}
|
||||
ChangeTag::Equal => {
|
||||
format!(" {}", change.value().trim_end())
|
||||
}
|
||||
};
|
||||
result.push_str(&formatted);
|
||||
result.push('\n');
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fn default_false() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user