efficiency_benchmark/
lib.rs1use std::env::set_current_dir;
2use std::fs::{copy, create_dir_all, metadata, read_dir, remove_dir_all, remove_file, File};
3use std::io::{BufRead, BufReader, stdout, Write, stdin};
4use std::process::{Command, exit, Stdio};
5use std::sync::mpsc::{channel, Receiver, Sender};
6use std::thread::{self, sleep};
7use std::time::Duration;
8use battery::{Manager, State};
9use colored::Colorize;
10use chrono::Local;
11
12pub fn bench(repo_url: &str, build_command: &str, source_dir: &str, build_dir: &str, repo_exists: bool) -> impl Iterator<Item = String> {
24 let (sender, receiver): (Sender<String>, Receiver<String>) = channel();
25 let repo_url = repo_url.to_owned();
26 let build_command = build_command.to_owned();
27 let source_dir = source_dir.to_owned();
28 let build_dir = build_dir.to_owned();
29 thread::spawn(move || {
30 if !repo_exists {
31 let mut command = Command::new("git")
32 .arg("clone")
33 .arg("--progress")
34 .arg(&repo_url)
35 .arg("--recursive")
36 .arg(&source_dir)
37 .stdout(Stdio::piped())
38 .spawn()
39 .expect("failed to clone repository");
40
41 let reader = BufReader::new(command.stdout.take().expect("failed to get stderr"));
42 for line in reader.lines() {
43 match line {
44 Ok(line) => {
45 sender.send(line.clone()).unwrap(); },
47 Err(_) => {},
48 }
49 }
50
51 command.wait().expect("failed to wait for command");
52 }
53
54 if metadata(&build_dir).is_ok() {
55 remove_dir_all(&build_dir).unwrap();
56 }
57
58
59 if is_plugged(false) {
60 sender.send("Please unplug the system to start the benchmarking".to_string()).unwrap();
61 loop {
62 if !is_plugged(true){
63 break;
64 }
65 sleep(Duration::from_secs(1));
66 }
67 }
68
69 let current_time = Local::now().format("%d-%m-%Y_%H:%M").to_string();
70 let logfile = &format!("benchmark-{}.log", current_time);
71 if metadata(logfile).is_ok() {
72 remove_file(logfile).unwrap();
73 }
74
75 loop {
76 sender.send("Copying repo".to_string()).unwrap();
78 copy_directory(&source_dir, &build_dir).expect("failed to copy src directory");
79
80 set_current_dir(&build_dir).unwrap();
81
82 sender.send("Building".to_string()).unwrap();
84 execute_build_command(&build_command);
85
86 set_current_dir("../").unwrap();
88 remove_dir_all(&build_dir).unwrap();
89
90 sender.send("Build successful!".to_string()).unwrap();
92
93 add_one(logfile);
94 }
95 });
96
97 receiver.into_iter()
98}
99
100
101fn add_one(logfile: &str) {
102
103 if !metadata(logfile).is_ok() {
104 let mut file = File::create(logfile).unwrap();
105 file.write_all("0".as_bytes()).unwrap();
106 }
107
108 let mut reader = BufReader::new(File::open(logfile).unwrap());
109 let mut score = Vec::new(); reader.read_until(b'\n', &mut score).unwrap();
111 let score = String::from_utf8_lossy(&score).parse::<u32>().unwrap(); let score = score + 1; let mut file = File::create(logfile).unwrap();
114 file.write_all(score.to_string().as_bytes()).unwrap();
115 println!("Current Score: {}", score);
116 sleep(Duration::from_secs(1));
117}
118
119pub fn get_battery_percentage() -> u8 {
122 let manager = Manager::new().unwrap().batteries().unwrap();
123 let battery = match manager.into_iter().next(){
124 Some(battery) => battery.unwrap(),
125 None => {
126 return 100 as u8;
127 },
128
129 };
130 let percentage = battery.state_of_charge().value * 100.0;
131 return percentage as u8;
132}
133
134pub fn is_plugged(has_asked: bool) -> bool {
139 let manager = Manager::new().unwrap().batteries().unwrap();
140 let battery = match manager.into_iter().next() {
141 Some(battery) => battery,
142 None => {
143 if !has_asked {
144 println!("[{}] This benchmark is meant for laptops", "WARNING".red());
145 println!("[{}] This benchmark will infinitely loop compiling something until it runs out of battery", "WARNING".red());
146 print!("Would you like to continue anyway? [Y/N] ");
147 stdout().flush().unwrap();
148 let mut input = String::new();
149 stdin().read_line(&mut input).unwrap();
150 if input.trim().to_lowercase() != "y" {
151 exit(1);
152 }
153 }
154 return false;
155 },
156 };
157 let state = battery.unwrap().state();
158 match state {
159 State::Charging => { return true; },
160 State::Full => { return true; },
161 _ => { return false; },
162 }
163}
164
165pub fn execute_build_command(command: &str) -> Receiver<String> {
166 let (sender, receiver) = channel();
167
168 let iterator = command.split_whitespace();
169 let mut command = Command::new(iterator.clone().next().unwrap());
170 for arg in iterator.skip(1) {
171 command.arg(arg);
172 }
173 let mut process = command
174 .stdout(Stdio::piped())
175 .spawn()
176 .expect("failed to build repository");
177 thread::spawn(move || {
178 let reader = BufReader::new(process.stdout.take().expect("failed to get stdout"));
179 for line in reader.lines() {
180 match line {
181 Ok(line) => {
182 sender.send(line.clone()).unwrap();
183 },
184 Err(_) => {},
185 }
186 }
187 });
188
189 receiver
190}
191
192fn copy_directory(source: &str, destination: &str) -> std::io::Result<()> {
193 create_dir_all(destination)?;
194
195 for entry in read_dir(source)? {
196 let entry = entry?;
197 let entry_type = entry.file_type()?;
198 let entry_path = entry.path();
199 let destination_path = format!("{}/{}", destination, entry_path.file_name().unwrap().to_string_lossy());
200
201 if entry_type.is_dir() {
202 copy_directory(&entry_path.to_string_lossy(), &destination_path)?;
203 } else {
204 copy(&entry_path, &destination_path)?;
205 }
206 }
207
208 Ok(())
209}
210
211pub fn get_highest_score(app_dir: &str) -> u32 {
212 if metadata(app_dir).is_err() {
213 create_dir_all(app_dir).unwrap();
214 }
215 let mut highest_score = 0;
216 for entry in read_dir(app_dir).unwrap() {
217 let entry = entry.unwrap();
218 if entry.file_type().unwrap().is_file() && entry.file_name().to_string_lossy().starts_with("benchmark"){
219 let file = File::open(entry.path()).unwrap();
220 let mut reader = BufReader::new(file);
221 let mut score = Vec::new();
222 reader.read_until(b'\n', &mut score).unwrap();
223 let score = match String::from_utf8_lossy(&score).parse::<u32>(){
224 Ok(score) => score,
225 Err(_) => 0,
226
227 };
228 if score > highest_score {
229 highest_score = score;
230 }
231 }
232
233 }
234 highest_score
235}
236
237pub fn get_latest_score(app_dir: &str) -> u32 {
238 if metadata(app_dir).is_err() {
239 create_dir_all(app_dir).unwrap();
240 }
241 let mut latest_date = String::new();
242 let mut latest_time = String::new();
243 for entry in read_dir(app_dir).unwrap() {
244 let entry = entry.unwrap();
245 if entry.file_type().unwrap().is_file() {
246 if entry.file_name().to_string_lossy().starts_with("benchmark") {
247 let date = entry.file_name().to_str().unwrap().to_owned();
248 let date = date.replace("benchmark-", "");
249 let date = date.replace(".log", "");
250 let parts = date.split("_").collect::<Vec<&str>>();
251 let time = parts[1].to_owned();
252 let date = parts[0].to_owned();
253 if date > latest_date {
254 latest_date = date;
255 latest_time = time;
256 } else if date == latest_date {
257 if time > latest_time {
258 latest_time = time;
259 }
260 }
261
262
263
264 }
265 }
266 }
267 #[cfg(unix)]
268 let logfile = &format!("{}/benchmark-{}_{}.log",app_dir, latest_date, latest_time);
269 #[cfg(windows)]
270 let logfile = &format!("{}\\benchmark-{}_{}.log",app_dir, latest_date, latest_time);
271 if metadata(logfile).is_ok() {
272 let file = File::open(logfile).unwrap();
273 let mut reader = BufReader::new(file);
274 let mut score = Vec::new();
275 reader.read_until(b'\n', &mut score).unwrap();
276 let score = match String::from_utf8_lossy(&score).parse::<u32>(){
277 Ok(score) => score,
278 Err(_) => 0,
279 };
280 return score;
281 }
282 0
283}