#![allow(unused)]
use crate::args::{ApiMockCmd, Commands, InterfaceCmd, MockCmd, MockGen};
use crate::prelude::*;
use crate::utils::gen_interface::*;
use crate::utils::gen_mock::*;
use crate::utils::parse_func::*;
mod args;
mod error;
mod prelude;
mod utils;
use clap::{Args, Command, Parser};
use walkdir::{DirEntry, WalkDir};
fn generate_interface(cmds: InterfaceCmd) -> Result<()> {
let class_string = find_class_substring(cmds.file.as_str(), cmds.class.as_str()).unwrap();
let functions = find_function_names(&class_string).unwrap();
let template_option = find_class_template(cmds.file.as_str(), cmds.class.as_str());
let opt_str: Option<&str> = template_option.as_deref();
replace_line(functions, &cmds.file, &cmds.class, opt_str).unwrap();
Ok(())
}
fn generate_mock(cmds: MockCmd) -> Result<()> {
let class_string = find_class_substring(cmds.file.as_str(), cmds.class.as_str()).unwrap();
let mut functions = find_function_names(&class_string).unwrap();
let output = match cmds.output {
Some(x) => x,
_ => ".".to_string(),
};
let interface_name = get_interface_name(cmds.class.as_str());
generate_mock_file(
&output,
cmds.file.as_str(),
cmds.class.as_str(),
interface_name.as_str(),
&mut functions,
)?;
Ok(())
}
fn generate_cmock(cmds: ApiMockCmd) -> Result<()> {
let mut functions = find_c_function_names(cmds.file.as_str()).unwrap();
let output_mock = match cmds.output {
Some(x) => x,
_ => "mocks".to_string(),
};
let output_api = match cmds.output_api {
Some(x) => x,
_ => "api_headers".to_string(),
};
generate_cmock_file(&output_mock, &output_api, &cmds.file, &mut functions)?;
Ok(())
}
fn find_file_path(file_name: &str) -> Result<String> {
let path = std::env::current_dir().unwrap();
dbg!(&path);
if cfg!(windows) {
let walker = WalkDir::new(path).into_iter();
for entry in walker {
let entry = entry.unwrap();
let string_path = entry.path().to_str().unwrap();
if string_path.contains(file_name) {
let file_result: Result<&str> = match string_path.rsplit_once("\\") {
Some(val) => Ok(val.1),
_ => continue,
};
let file_path = file_result.unwrap();
match file_path {
_ if file_path == file_name => return Ok(string_path.to_owned()),
_ => continue,
}
}
}
Err(Error::Generic(
format!("error: {file_name} not found").to_owned(),
))
} else {
for entry in WalkDir::new(path).into_iter().filter_map(|e| e.ok()) {
if entry.file_name().to_str().unwrap() == file_name {
return Ok(entry.path().display().to_string());
}
}
Err(Error::Generic(
format!("error: {file_name} not found").to_owned(),
))
}
}
fn main() -> Result<()> {
let mut args = MockGen::parse();
match args.commands {
Commands::Interface(mut command) => {
println!(
"generating interface for class:{} in file: {}",
command.class, command.file
);
command.file = find_file_path(&command.file)?;
generate_interface(command);
}
Commands::Mock(mut command) => {
println!(
"generating mock of class:{} from file:{}",
command.class, command.file
);
command.file = find_file_path(&command.file)?;
generate_mock(command);
}
Commands::ApiMock(mut command) => {
println!("generating c mock of from file:{}", command.file);
command.file = find_file_path(&command.file)?;
generate_cmock(command);
}
Commands::IMock(mut command) => {
println!(
"generating interface and mock of {} from file:{}",
command.class, command.file
);
command.file = find_file_path(&command.file)?;
let interface_cmd = InterfaceCmd {
file: command.file.clone(),
class: command.class.clone(),
};
let mock_cmd = MockCmd {
file: command.file.clone(),
class: command.class.clone(),
output: command.output.clone(),
};
generate_interface(interface_cmd);
generate_mock(mock_cmd);
}
_ => println!("{}", String::from("no arguments")),
};
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::utils::gen_mock::*;
use std::fs;
#[test]
fn test_mock_gen() {
dbg!(generate_mock_string(
"uint16& set_calibration_status(bool value, float32 test, int16_t why)"
));
}
#[test]
fn testing_stm32_files() {
let paths = fs::read_dir("./test_files/c_files").unwrap();
for path in paths {
let cmd = ApiMockCmd {
file: path.as_ref().unwrap().path().to_str().unwrap().to_string(),
output: None,
output_api: None,
};
println!("Name: {}", path.unwrap().path().display());
generate_cmock(cmd);
}
}
#[test]
fn testing_cpp_files() {
let paths = fs::read_dir("./test_files/c_files").unwrap();
todo!("add in tests for regular mocking of classes");
}
use crate::utils::lizard::*;
use serde_json::Value;
use std::env;
use std::path::Path;
use std::process::Command;
#[test]
fn test_lizard_file() {
match env::current_dir() {
Ok(path) => println!("Current directory: {}", path.display()),
Err(e) => eprintln!("Error getting current directory: {}", e),
}
let file_path = "./test_files/lizard/test.cpp";
let function_name = "max_of_two";
let output = Command::new("lizard")
.args(["--csv", file_path])
.output()
.expect("Failed to run lizard");
let output_str = String::from_utf8_lossy(&output.stdout);
let output_str = output_str.replace(r#"\""#, r#"""#);
println!("{}", output_str);
let lizard_metrics = parse_func::parse_lizard_csv(&output_str, function_name).unwrap();
println!(
"Function: {}, NLOC: {}, CCN: {}",
lizard_metrics.function_name, lizard_metrics.nloc, lizard_metrics.cyclomatic_complexity
);
}
}