forked from Jon-Becker/heimdall-rs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_cfg.rs
143 lines (124 loc) · 4.88 KB
/
test_cfg.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#[cfg(test)]
mod integration_tests {
use memory_stats::memory_stats;
use std::path::PathBuf;
use heimdall_cfg::{cfg, CfgArgs, CfgArgsBuilder};
use petgraph::dot::Dot;
use serde_json::Value;
#[tokio::test]
async fn test_cfg_simple() {
let rpc_url = std::env::var("RPC_URL").unwrap_or_else(|_| {
println!("RPC_URL not set, skipping test");
std::process::exit(0);
});
let result = heimdall_cfg::cfg(CfgArgs {
target: String::from("0x1bf797219482a29013d804ad96d1c6f84fba4c45"),
rpc_url,
default: true,
color_edges: false,
output: String::from(""),
name: String::from(""),
timeout: 10000,
})
.await
.expect("failed to generate cfg");
let output: String = format!("{}", Dot::with_config(&result.graph, &[]));
for line in &[
String::from("0 [ label = \"0x01 PUSH20 0x1bf797219482a29013d804ad96d1c6f84fba4c45\\l0x16 ADDRESS \\l0x17 EQ \\l0x18 PUSH1 0x80\\l0x1a PUSH1 0x40\\l0x1c MSTORE \\l0x1d PUSH1 0x04\\l0x1f CALLDATASIZE \\l0x20 LT \\l0x21 PUSH2 0x58\\l0x24 JUMPI \\l\" ]"),
String::from("0 -> 13 []")
] {
output.contains(line);
}
}
#[tokio::test]
async fn test_cfg_complex() {
let rpc_url = std::env::var("RPC_URL").unwrap_or_else(|_| {
println!("RPC_URL not set, skipping test");
std::process::exit(0);
});
let result = heimdall_cfg::cfg(CfgArgs {
target: String::from("0xE90d8Fb7B79C8930B5C8891e61c298b412a6e81a"),
rpc_url,
default: true,
color_edges: false,
output: String::from(""),
name: String::from(""),
timeout: 10000,
})
.await
.expect("failed to generate cfg");
let output = format!("{}", Dot::with_config(&result.graph, &[]));
for line in &[String::from("\"0x039f JUMPDEST \\l0x03a0 STOP \\l\"")] {
assert!(output.contains(line))
}
}
#[tokio::test]
#[ignore]
async fn heavy_integration_test() {
let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.parent()
.expect("no parent")
.parent()
.expect("no parent")
.to_owned();
// if the ./largest1k directory does not exist, download it from https://jbecker.dev/data/largest1k.tar.gz
let dataset_dir = root_dir.join("largest1k");
if !dataset_dir.exists() {
eprintln!("dataset not found in root, skipping test");
std::process::exit(0);
}
// list files in root_dir
let contracts = std::fs::read_dir(dataset_dir)
.expect("failed to read dataset directory")
.map(|res| {
// HashMap from filename (without extension) to bytecode (from serde_json::Value)
res.map(|e| {
let path = e.path();
let filename = path
.file_stem()
.expect("no file stem")
.to_str()
.expect("no file stem")
.to_owned();
// read contents as json and parse to serde_json::Value
let contents_json: Value = serde_json::from_str(
&std::fs::read_to_string(path).expect("failed to read file"),
)
.expect("failed to parse json");
let bytecode = contents_json["code"].as_str().expect("no bytecode").to_owned();
(filename, bytecode)
})
})
.collect::<Result<Vec<_>, std::io::Error>>()
.expect("failed to collect files");
let mut success_count = 0;
let mut fail_count = 0;
for (contract_address, bytecode) in contracts {
println!("Generating Cfg for contract {contract_address}");
let args = CfgArgsBuilder::new()
.target(bytecode)
.timeout(10000)
.build()
.expect("failed to build args");
match cfg(args).await {
Ok(_) => {
success_count += 1;
}
Err(_) => {
fail_count += 1;
}
};
if let Some(usage) = memory_stats() {
println!("Current physical memory usage: {}", usage.physical_mem);
println!("Current virtual memory usage: {}", usage.virtual_mem);
} else {
println!("Couldn't get the current memory usage :(");
}
}
// assert 99% success rate
assert!(
success_count as f64 / (success_count + fail_count) as f64 > 0.99,
"success rate is less than 99%"
);
}
}