Skip to content

Commit 543a970

Browse files
committed
Unit tests for contract module
1 parent c68c24b commit 543a970

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@ serde_json = { version = "<=1.0.44", optional = true }
3434
[dev-dependencies]
3535
rand = "0.6.5"
3636
serde_json = "<=1.0.44"
37+
bitcoin = { version = "0.23", features = ["use-serde"] }

src/contracts.rs

+103
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,106 @@ impl fmt::Debug for Contract {
216216
write!(f, "Contract({:?})", Content::from_bytes(self.as_bytes()).expect("invariant"))
217217
}
218218
}
219+
220+
#[cfg(test)]
221+
mod test {
222+
use super::*;
223+
use bitcoin::hashes::hex::FromHex;
224+
use std::str::FromStr;
225+
226+
#[test]
227+
fn test_json() {
228+
let correct = r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":8,"ticker":"USDt","version":0}"#;
229+
assert!(Contract::from_bytes(correct.as_bytes()).is_ok());
230+
231+
let invalid = [
232+
// missing precision
233+
r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","ticker":"USDt","version":0}"#,
234+
// precision is string
235+
r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":"no","ticker":"USDt","version":0}"#,
236+
// negative precision
237+
r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":-2,"ticker":"USDt","version":0}"#,
238+
// too high precision
239+
r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":9,"ticker":"USDt","version":0}"#,
240+
// missing ticker
241+
r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":8,"version":0}"#,
242+
// ticker is int
243+
r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":8,"ticker":8,"version":0}"#,
244+
// ticker too long
245+
r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":8,"ticker":"USDtether","version":0}"#,
246+
];
247+
for json in &invalid {
248+
assert!(Contract::from_bytes(json.as_bytes()).is_err(), "invalid JSON was accepted: {}", json);
249+
}
250+
}
251+
252+
#[test]
253+
fn test_tether() {
254+
let json = r#"{"entity":{"domain":"tether.to"},"issuer_pubkey":"0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904","name":"Tether USD","precision":8,"ticker":"USDt","version":0}"#;
255+
let tether_id = AssetId::from_str("ce091c998b83c78bb71a632313ba3760f1763d9cfcffae02258ffa9865a37bd2").unwrap();
256+
let tether_prevout = OutPoint::from_str("9596d259270ef5bac0020435e6d859aea633409483ba64e232b8ba04ce288668:0").unwrap();
257+
let tether_contract_hash = ContractHash::from_hex("3c7f0a53c2ff5b99590620d7f6604a7a3a7bfbaaa6aa61f7bfc7833ca03cde82").unwrap();
258+
259+
let contract = Contract::from_bytes(json.as_bytes()).unwrap();
260+
assert_eq!(contract.contract_hash(), tether_contract_hash);
261+
assert_eq!(contract.asset_id(tether_prevout), tether_id);
262+
263+
assert_eq!(contract.precision(), 8);
264+
assert_eq!(contract.ticker(), "USDt".to_owned());
265+
266+
assert_eq!(contract.property("name").unwrap(), Some("Tether USD".to_owned()));
267+
assert_eq!(contract.property("issuer_pubkey").unwrap(),
268+
Some(bitcoin::PublicKey::from_str("0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904").unwrap()),
269+
);
270+
271+
#[derive(Debug, PartialEq, Eq, Deserialize)]
272+
struct Entity {
273+
pub domain: String,
274+
}
275+
assert_eq!(contract.property("entity").unwrap(),
276+
Some(Entity { domain: "tether.to".into() }),
277+
);
278+
}
279+
280+
#[test]
281+
fn test_cbor_wip() {
282+
#[derive(Debug, PartialEq, Eq, Deserialize, Serialize)]
283+
struct Entity {
284+
pub domain: String,
285+
}
286+
#[derive(Debug, Serialize)]
287+
struct ContractExtraContent {
288+
pub entity: Entity,
289+
pub name: String,
290+
pub issuer_pubkey: bitcoin::PublicKey,
291+
}
292+
293+
let extra = ContractExtraContent {
294+
entity: Entity {
295+
domain: "tether.to".into(),
296+
},
297+
name: "Tether USD".into(),
298+
issuer_pubkey: "0337cceec0beea0232ebe14cba0197a9fbd45fcf2ec946749de920e71434c2b904".parse().unwrap(),
299+
};
300+
let cbor_content: Vec<serde_cbor::Value> = vec![
301+
8.into(),
302+
"USDt".to_owned().into(),
303+
//TODO(stevenroose) optimize this as serde_cbor gets to_value
304+
serde_cbor::from_slice::<serde_cbor::Value>(&serde_cbor::to_vec(&extra).unwrap()).unwrap(),
305+
];
306+
307+
// version byte
308+
let mut buffer = vec![1u8];
309+
serde_cbor::to_writer(&mut buffer, &cbor_content).unwrap();
310+
let contract = Contract::from_bytes(&buffer).unwrap();
311+
312+
assert_eq!(contract.contract_hash(), ContractHash::hash(&buffer));
313+
314+
assert_eq!(contract.precision(), 8);
315+
assert_eq!(contract.ticker(), "USDt".to_owned());
316+
317+
assert_eq!(contract.property("name").unwrap(), Some(extra.name));
318+
assert_eq!(contract.property("issuer_pubkey").unwrap(), Some(extra.issuer_pubkey));
319+
assert_eq!(contract.property("entity").unwrap(), Some(extra.entity));
320+
}
321+
}

0 commit comments

Comments
 (0)