Skip to content

Commit

Permalink
test: mock fs using tempfile crate
Browse files Browse the repository at this point in the history
Signed-off-by: WoodenMaiden <[email protected]>
  • Loading branch information
WoodenMaiden committed Oct 30, 2023
1 parent 108cc7d commit 26de47b
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 50 deletions.
2 changes: 1 addition & 1 deletion agent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ name = "agent_lib"
path = "lib/src/lib.rs"

[dev-dependencies]
rand = "0.8.5"
tempfile = "3.8.1"
37 changes: 36 additions & 1 deletion agent/lib/src/runner_engine/model.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
use std::path::PathBuf;
use anyhow::Result;
use std::{
fs::File,
io::{Read, Write},
path::Path,
path::PathBuf,
};

use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -49,3 +55,32 @@ impl CodeReturn {
}
}
}

/// A trait responsible for CRU operations on files and dir
/// Mainly used in tests to mock file operations
trait FileHandler: Read + Write {
fn create<P: AsRef<Path>>(path: P) -> Result<Self>
where
Self: Sized;
fn read<P: AsRef<Path>>(path: P) -> Result<Self>
where
Self: Sized;
}

impl FileHandler for File {
fn create<P: AsRef<Path>>(path: P) -> Result<Self>
where
Self: Sized,
{
let file = File::create(path)?;
Ok(file)
}

fn read<P: AsRef<Path>>(path: P) -> Result<Self>
where
Self: Sized,
{
let file = File::open(path)?;
Ok(file)
}
}
93 changes: 45 additions & 48 deletions agent/lib/src/runner_engine/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ use std::{
process::Command,
};

/// The path where the workspace will be created
const WORKSPACE_PATH: &str = "/tmp";

/// The RunnerEngine API
/// The RunnerEngine API, responsible for running a request message
#[derive(Clone, Debug)]
pub struct RunnerEngine {
/// the request message
pub request_message: ExecuteRequest,
/// The root path of the workspace
pub root_path: PathBuf,
}

impl RunnerEngine {
/// Create a new instance of RunnerEngine
/// Create a new instance of RunnerEngine and set the root path to your system's temp folder/directory
///
/// # Arguments
///
Expand All @@ -29,7 +30,27 @@ impl RunnerEngine {
///
/// * `Self` - The new instance of RunnerEngine
pub fn new(request_message: ExecuteRequest) -> Self {
Self { request_message }
Self {
request_message,
root_path: std::env::temp_dir(),
}
}

/// Create a new instance of RunnerEngine that uses another root path than /tmp
///
/// # Arguments
///
/// * `request_message` - The request message
/// * `root_path` - The root path of the workspace
///
/// # Returns
///
/// * `Self` - The new instance of RunnerEngine
pub fn new_with_path(request_message: ExecuteRequest, root_path: &str) -> Self {
Self {
request_message,
root_path: PathBuf::from(root_path),
}
}

/// Create the workspace for the code execution
Expand All @@ -42,14 +63,13 @@ impl RunnerEngine {

// Create a vector of FileModel and a root path
let mut file_models: Vec<FileModel> = Vec::new();
let root_path = PathBuf::from(WORKSPACE_PATH);

self.request_message.files.iter().for_each(|file| {
let mut file_path = PathBuf::from(&file.filename);
file_path.pop();

// Add `/tmp` before each path
file_path = root_path.join(file_path);
file_path = self.root_path.join(file_path);

// Take the file name and add it to the vector of files
let file_name = Path::file_name(Path::new(&file.filename));
Expand Down Expand Up @@ -169,7 +189,7 @@ impl RunnerEngine {

let child_process = Command::new("/bin/sh")
.args(["-c", command])
.current_dir(WORKSPACE_PATH)
.current_dir(self.root_path.clone())
.output()
.map_err(|e| anyhow!("Failed to spawn command : {}", e))?;

Expand All @@ -194,42 +214,17 @@ mod tests {
use crate::api::grpc_definitions::{ExecuteRequestStep, FileModel};

use super::*;
use rand::random;
use std::fs::File;
use std::io::Read;

/// Generate a random string
///
/// # Arguments
///
/// * `len` - The length of the string
///
/// # Returns
///
/// * `String` - The random string
fn native_rand_string(len: usize) -> String {
let chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
let mut string = String::new();

for _ in 0..len {
string.push(
chars
.chars()
.nth(random::<usize>() % (chars.len() - 1))
.unwrap(),
);
}

string
}

#[test]
fn run_one_works_with_ouputs_and_code() {
let res = RunnerEngine::new(ExecuteRequest {
let res = RunnerEngine::new(ExecuteRequest {
id: "".to_string(),
files: vec![],
steps: vec![]
}).run_one("echo -n 'This is stdout' && echo -n 'This is stderr' >&2 && exit 1");
files: vec![],
steps: vec![],
})
.run_one("echo -n 'This is stdout' && echo -n 'This is stderr' >&2 && exit 1");

assert!(res.is_ok());

Expand Down Expand Up @@ -269,24 +264,24 @@ mod tests {
assert_eq!(res.steps[0].stderr, "This is stderr\n");
assert_eq!(res.steps[0].stdout, "This is stdout\n");

println!("{:?}", res.steps[1]);
assert_eq!(res.steps[1].exit_code, 1);
assert_eq!(res.steps[1].stderr, "This is stderr\n");
assert!(res.steps[1].stdout.is_empty());

assert_eq!(res.id, "4bf68974-c315-4c41-aee2-3dc2920e76e9");
}

/// Test the execution of a command with a workspace
#[test]
fn workspace_created_sucessfully() {
let mut base_dir = PathBuf::from(WORKSPACE_PATH);
base_dir.push(native_rand_string(20));
base_dir.push("main.sh");
let path = base_dir.into_os_string().into_string().unwrap();
let tempdir = tempfile::tempdir();
let temp_dir = &tempdir.unwrap();
let path = temp_dir.path();

let filename = path.join("main.sh").to_str().unwrap().to_string();

let files: Vec<FileModel> = vec![FileModel {
filename: path.clone(),
filename: filename.clone(),
content: "Hello World!".to_string(),
}];
let steps: Vec<ExecuteRequestStep> = Vec::new();
Expand All @@ -296,12 +291,14 @@ mod tests {
steps,
};

RunnerEngine::new(request_data).create_workspace().unwrap();
RunnerEngine::new_with_path(request_data, path.as_os_str().to_str().unwrap())
.create_workspace()
.unwrap();

assert!(Path::new(&path).exists());

//Check that the file contains the specified content
let mut file = File::open(&path).unwrap();
let mut file = File::open(filename).unwrap();
let mut buffer = [0; 12];
file.read_exact(&mut buffer[..]).unwrap();

Expand Down

0 comments on commit 26de47b

Please sign in to comment.