improved test execution
This commit is contained in:
parent
7f694cd6c2
commit
6ef3993f8f
6 changed files with 93 additions and 56 deletions
|
@ -14,6 +14,7 @@ pub struct Config {
|
||||||
main_file: String,
|
main_file: String,
|
||||||
test_file: String,
|
test_file: String,
|
||||||
includes: Vec<String>,
|
includes: Vec<String>,
|
||||||
|
fascist_mode: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
|
@ -24,6 +25,7 @@ impl Config {
|
||||||
main_file: "main.c".into(),
|
main_file: "main.c".into(),
|
||||||
test_file: "test.c".into(),
|
test_file: "test.c".into(),
|
||||||
includes: vec![],
|
includes: vec![],
|
||||||
|
fascist_mode: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +63,10 @@ impl Config {
|
||||||
&self.includes
|
&self.includes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fascist_mode(&self) -> bool {
|
||||||
|
self.fascist_mode
|
||||||
|
}
|
||||||
|
|
||||||
fn try_get(path: &Path) -> Option<Self> {
|
fn try_get(path: &Path) -> Option<Self> {
|
||||||
let path = path.to_path_buf().apply(|p| p.push(Self::CONFIG_FILE_NAME));
|
let path = path.to_path_buf().apply(|p| p.push(Self::CONFIG_FILE_NAME));
|
||||||
fs::read_to_string(path)
|
fs::read_to_string(path)
|
||||||
|
|
19
src/main.rs
19
src/main.rs
|
@ -63,6 +63,18 @@ fn append_includes(list: &mut Vec<String>) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compilation_args() -> Vec<String> {
|
||||||
|
let mut args = vec![
|
||||||
|
"-Wall".to_string(),
|
||||||
|
"-Wextra".to_string(),
|
||||||
|
"-std=c99".to_string(),
|
||||||
|
];
|
||||||
|
if Config::get_current().fascist_mode() {
|
||||||
|
args.push("-Werror".to_string());
|
||||||
|
}
|
||||||
|
args
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args: Arguments = Parser::parse();
|
let args: Arguments = Parser::parse();
|
||||||
|
|
||||||
|
@ -70,7 +82,8 @@ fn main() {
|
||||||
Commands::check { files } => check::main(files),
|
Commands::check { files } => check::main(files),
|
||||||
Commands::run { mut files } => {
|
Commands::run { mut files } => {
|
||||||
append_includes(&mut files);
|
append_includes(&mut files);
|
||||||
run::main(files);
|
let args = compilation_args();
|
||||||
|
run::main(files, args);
|
||||||
}
|
}
|
||||||
Commands::test {
|
Commands::test {
|
||||||
capture,
|
capture,
|
||||||
|
@ -78,12 +91,14 @@ fn main() {
|
||||||
tests,
|
tests,
|
||||||
} => {
|
} => {
|
||||||
append_includes(&mut files);
|
append_includes(&mut files);
|
||||||
|
let args = compilation_args();
|
||||||
let tests = (!tests.is_empty()).then_some(tests);
|
let tests = (!tests.is_empty()).then_some(tests);
|
||||||
test::main(capture, files, tests)
|
test::main(capture, files, tests)
|
||||||
}
|
}
|
||||||
Commands::watch { mut files } => {
|
Commands::watch { mut files } => {
|
||||||
append_includes(&mut files);
|
append_includes(&mut files);
|
||||||
watch::main(files)
|
let args = compilation_args();
|
||||||
|
watch::main(files, args)
|
||||||
}
|
}
|
||||||
Commands::init { path } => config::create(path),
|
Commands::init { path } => config::create(path),
|
||||||
}
|
}
|
||||||
|
|
21
src/run.rs
21
src/run.rs
|
@ -1,21 +1,21 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
tasks::{CompileTask, RunTask},
|
tasks::{CompileTask, RunTask},
|
||||||
utils::{log_failure, log_success},
|
utils::{log_failure, log_process, log_success},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main(files: Vec<String>) -> Option<()> {
|
pub fn main(files: Vec<String>, flags: Vec<String>) -> Option<()> {
|
||||||
let source_file = files.into_iter().map(|f| f.into()).collect();
|
let source_file = files.into_iter().map(|f| f.into()).collect();
|
||||||
let compiled = CompileTask::new(source_file)
|
log_process("compiling");
|
||||||
.with_flag("-Wall")
|
let mut task = CompileTask::new(source_file);
|
||||||
.with_flag("-Wextra")
|
for flag in flags {
|
||||||
.with_flag("-std=c99")
|
task = task.with_flag(flag);
|
||||||
.run()
|
}
|
||||||
.map(Option::from)
|
let compiled = task.run().map(Option::from).unwrap_or_else(|_| {
|
||||||
.unwrap_or_else(|_| {
|
|
||||||
log_failure("compilation failed");
|
log_failure("compilation failed");
|
||||||
None
|
None
|
||||||
})?;
|
})?;
|
||||||
log_success("compilation successful");
|
log_success("finished");
|
||||||
|
log_process("running");
|
||||||
RunTask::new(compiled)
|
RunTask::new(compiled)
|
||||||
.run()
|
.run()
|
||||||
.map(Option::from)
|
.map(Option::from)
|
||||||
|
@ -23,6 +23,5 @@ pub fn main(files: Vec<String>) -> Option<()> {
|
||||||
log_failure("process failure");
|
log_failure("process failure");
|
||||||
None
|
None
|
||||||
})?;
|
})?;
|
||||||
log_success("process exited successfully");
|
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
34
src/tasks.rs
34
src/tasks.rs
|
@ -2,8 +2,6 @@ use std::{
|
||||||
fs,
|
fs,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
process::{Command, ExitStatus},
|
process::{Command, ExitStatus},
|
||||||
thread,
|
|
||||||
time::Duration,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
|
@ -14,6 +12,7 @@ pub struct CompileTask {
|
||||||
files: Vec<PathBuf>,
|
files: Vec<PathBuf>,
|
||||||
addition: Vec<String>,
|
addition: Vec<String>,
|
||||||
flags: Vec<String>,
|
flags: Vec<String>,
|
||||||
|
verbose: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: split compile & compile raw
|
// TODO: split compile & compile raw
|
||||||
|
@ -24,6 +23,7 @@ impl CompileTask {
|
||||||
files,
|
files,
|
||||||
addition: vec![],
|
addition: vec![],
|
||||||
flags: vec![],
|
flags: vec![],
|
||||||
|
verbose: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,11 @@ impl CompileTask {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_verbose(mut self) -> Self {
|
||||||
|
self.verbose = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run(self) -> Result<PathBuf, ExitStatus> {
|
pub fn run(self) -> Result<PathBuf, ExitStatus> {
|
||||||
let proc_source = self.gen_source();
|
let proc_source = self.gen_source();
|
||||||
let mut sources = self.files.clone();
|
let mut sources = self.files.clone();
|
||||||
|
@ -60,30 +65,46 @@ impl CompileTask {
|
||||||
.args(["-o", output_path_ref])
|
.args(["-o", output_path_ref])
|
||||||
.args(self.flags.clone())
|
.args(self.flags.clone())
|
||||||
.args(sources.iter().map(|s| s.to_str().unwrap()));
|
.args(sources.iter().map(|s| s.to_str().unwrap()));
|
||||||
|
if self.verbose {
|
||||||
log_command_run(&command);
|
log_command_run(&command);
|
||||||
log_separator_top();
|
log_separator_top();
|
||||||
|
}
|
||||||
let status = command.status().unwrap();
|
let status = command.status().unwrap();
|
||||||
|
if self.verbose {
|
||||||
log_separator_bottom();
|
log_separator_bottom();
|
||||||
thread::sleep(Duration::from_millis(100));
|
}
|
||||||
status.success().then_some(output_path).ok_or(status)
|
status.success().then_some(output_path).ok_or(status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RunTask {
|
pub struct RunTask {
|
||||||
file: PathBuf,
|
file: PathBuf,
|
||||||
|
verbose: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RunTask {
|
impl RunTask {
|
||||||
pub fn new(file: PathBuf) -> Self {
|
pub fn new(file: PathBuf) -> Self {
|
||||||
Self { file }
|
Self {
|
||||||
|
file,
|
||||||
|
verbose: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_verbose(mut self) -> Self {
|
||||||
|
self.verbose = true;
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(self) -> Result<(), ExitStatus> {
|
pub fn run(self) -> Result<(), ExitStatus> {
|
||||||
let mut command = Command::new(self.file);
|
let mut command = Command::new(self.file);
|
||||||
|
if self.verbose {
|
||||||
log_command_run(&command);
|
log_command_run(&command);
|
||||||
log_separator_top();
|
log_separator_top();
|
||||||
|
}
|
||||||
let status = command.status().unwrap();
|
let status = command.status().unwrap();
|
||||||
|
if self.verbose {
|
||||||
log_separator_bottom();
|
log_separator_bottom();
|
||||||
|
}
|
||||||
if status.success() {
|
if status.success() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
@ -100,10 +121,11 @@ impl GenTask {
|
||||||
pub fn new(content: String) -> Self {
|
pub fn new(content: String) -> Self {
|
||||||
Self { content }
|
Self { content }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(self) -> PathBuf {
|
pub fn run(self) -> PathBuf {
|
||||||
let output_path = tmp_file_path().apply(|o| o.set_extension("c"));
|
let output_path = tmp_file_path().apply(|o| o.set_extension("c"));
|
||||||
fs::write(&output_path, &self.content).unwrap();
|
let content = self.content.clone();
|
||||||
dbg!(fs::read_to_string(&output_path).unwrap());
|
fs::write(&output_path, &content).unwrap();
|
||||||
output_path
|
output_path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
16
src/test.rs
16
src/test.rs
|
@ -1,6 +1,9 @@
|
||||||
use std::fs;
|
use std::{fs, thread, time::Duration};
|
||||||
|
|
||||||
use crate::tasks::{CompileTask, GenTask, RunTask};
|
use crate::{
|
||||||
|
tasks::{CompileTask, GenTask, RunTask},
|
||||||
|
utils::{log_failure, log_process},
|
||||||
|
};
|
||||||
|
|
||||||
pub fn main(_capture: bool, files: Vec<String>, _test: Option<Vec<String>>) {
|
pub fn main(_capture: bool, files: Vec<String>, _test: Option<Vec<String>>) {
|
||||||
// let includes = files
|
// let includes = files
|
||||||
|
@ -13,14 +16,19 @@ pub fn main(_capture: bool, files: Vec<String>, _test: Option<Vec<String>>) {
|
||||||
let content = fs::read_to_string(&path).unwrap();
|
let content = fs::read_to_string(&path).unwrap();
|
||||||
let tests = find_tests(content);
|
let tests = find_tests(content);
|
||||||
for test in tests {
|
for test in tests {
|
||||||
|
log_process(&format!("running '{test}'"));
|
||||||
let content = gen_test_main(fs::canonicalize(&path).unwrap().to_str().unwrap(), &test);
|
let content = gen_test_main(fs::canonicalize(&path).unwrap().to_str().unwrap(), &test);
|
||||||
let generated_code = GenTask::new(content).run();
|
let generated_code = GenTask::new(content).run();
|
||||||
|
|
||||||
|
thread::sleep(Duration::from_millis(100));
|
||||||
|
|
||||||
// compile with all files
|
// compile with all files
|
||||||
//let files = includes.clone().apply(|v| v.insert(0, generated_code));
|
//let files = includes.clone().apply(|v| v.insert(0, generated_code));
|
||||||
let generated_bin = CompileTask::new(vec![generated_code]).run().unwrap();
|
let generated_bin = CompileTask::new(vec![generated_code]).run().unwrap();
|
||||||
// run
|
// run
|
||||||
RunTask::new(generated_bin).run().unwrap();
|
if let Err(_) = RunTask::new(generated_bin).run() {
|
||||||
|
log_failure("test failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +46,7 @@ pub fn gen_test_main(path: &str, test: &str) -> String {
|
||||||
"
|
"
|
||||||
void ____test();
|
void ____test();
|
||||||
|
|
||||||
int main() {{
|
int main(int _argc, char** _argv) {{
|
||||||
____test();
|
____test();
|
||||||
return 0;
|
return 0;
|
||||||
}}
|
}}
|
||||||
|
|
35
src/watch.rs
35
src/watch.rs
|
@ -8,41 +8,28 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Repeater {
|
pub struct Repeater {
|
||||||
files: Vec<String>,
|
op: Box<dyn Fn()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Repeater {
|
impl Repeater {
|
||||||
pub fn new(files: Vec<String>) -> Self {
|
pub fn new(op: impl Fn() + 'static) -> Self {
|
||||||
Self { files }
|
let op = Box::new(op);
|
||||||
|
Self { op }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn repeat(&self) -> Option<()> {
|
pub fn repeat(&self) -> Option<()> {
|
||||||
let binary = CompileTask::new(self.files.clone().into_iter().map(|f| f.into()).collect())
|
(self.op)();
|
||||||
.run()
|
log_process("waiting for changes...");
|
||||||
.map(Option::from)
|
|
||||||
.unwrap_or_else(|_| {
|
|
||||||
log_failure("failed compilation");
|
|
||||||
None
|
|
||||||
})?;
|
|
||||||
|
|
||||||
log_success("compilation successful");
|
|
||||||
RunTask::new(binary)
|
|
||||||
.run()
|
|
||||||
.map(Option::from)
|
|
||||||
.unwrap_or_else(|_| {
|
|
||||||
log_failure("task failure");
|
|
||||||
None
|
|
||||||
})?;
|
|
||||||
|
|
||||||
log_success("task successful");
|
|
||||||
log_process("waiting for changes before re run");
|
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main(files: Vec<String>) {
|
pub fn main(files: Vec<String>, args: Vec<String>) {
|
||||||
log_process(&format!("watching files '{files:?}'"));
|
log_process(&format!("watching files '{files:?}'"));
|
||||||
let repeater = Repeater::new(files.clone());
|
let passed = files.clone();
|
||||||
|
let repeater = Repeater::new(move || {
|
||||||
|
crate::run::main(passed.clone(), args.clone());
|
||||||
|
});
|
||||||
repeater.repeat();
|
repeater.repeat();
|
||||||
|
|
||||||
let (send, rec) = mpsc::channel();
|
let (send, rec) = mpsc::channel();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue