Skip to content

Commit ebb08e8

Browse files
committed
[#198]: use command runner downstream & tests
1 parent dc188aa commit ebb08e8

11 files changed

Lines changed: 888 additions & 219 deletions

File tree

‎cli/src/errors.rs‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,18 @@ impl fmt::Display for CliError {
122122
}
123123
}
124124
}
125+
126+
# [cfg(test)]
127+
mod tests {
128+
use super::*;
129+
130+
#[test]
131+
fn test_display_base_error() {
132+
let err = CliError::BaseError {
133+
reason: "some reason".to_string(),
134+
};
135+
let err_str = format!("{}", err);
136+
assert!(err_str.contains("An error occured. Reason:"));
137+
assert!(err_str.contains("some reason"));
138+
}
139+
}

‎cli/src/essential.rs‎

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::command_runner::{CommandRunner, RealCommandRunner};
12
use crate::errors::CliError;
23
use std::borrow::Cow;
34
use std::thread;
@@ -130,10 +131,17 @@ pub fn update_cli() -> Result<(), CliError> {
130131
//
131132
// This function returns the latest version of the CLI from the crates.io registry
132133
pub fn get_latest_cfcli_version() -> Result<String, CliError> {
133-
let output = Command::new("cargo")
134-
.args(["search", "cortexflow-cli", "--limit", "1"])
135-
.output()
136-
.expect("Error");
134+
get_latest_cfcli_version_with(&RealCommandRunner)
135+
}
136+
137+
fn get_latest_cfcli_version_with(runner: &dyn CommandRunner) -> Result<String, CliError> {
138+
let args = [
139+
"search".to_string(),
140+
"cortexflow-cli".to_string(),
141+
"--limit".to_string(),
142+
"1".to_string(),
143+
];
144+
let output = runner.run("cargo", &args).expect("Error");
137145

138146
if !output.status.success() {
139147
return Err(CliError::InstallerError {
@@ -410,10 +418,18 @@ pub async fn update_configmap(config_struct: MetadataConfigFile) -> Result<(), C
410418

411419
#[cfg(test)]
412420
mod tests {
413-
use crate::essential::extract_version_from_output;
421+
use crate::command_runner::test_support::StubCommandRunner;
422+
use crate::essential::{create_configs, extract_version_from_output, get_latest_cfcli_version_with};
423+
424+
#[test]
425+
fn creates_an_empty_blocklist_configuration() {
426+
let configs = create_configs();
427+
428+
assert_eq!(configs.blocklist, vec![String::new()]);
429+
}
414430

415431
#[test]
416-
fn test_version_extraction() {
432+
fn extracts_the_version_from_cargo_search_output() {
417433
let command_stdout = String::from(
418434
r#"cortexflow-cli = "0.1.4-test_123"
419435
# CortexFlow command line interface made to interact with the CortexBrain core components...
@@ -423,4 +439,19 @@ mod tests {
423439
let extracted_command = extract_version_from_output(command_stdout.into());
424440
assert_eq!(extracted_command, "0.1.4-test_123");
425441
}
442+
443+
#[test]
444+
fn get_latest_cfcli_version_returns_parsed_version_on_success() {
445+
let runner = StubCommandRunner::success(
446+
r#"cortexflow-cli = "0.1.5" # CortexFlow command line interface"#,
447+
);
448+
let version = get_latest_cfcli_version_with(&runner);
449+
assert_eq!(version.unwrap(), "0.1.5");
450+
}
451+
452+
#[test]
453+
fn get_latest_cfcli_version_errors_on_command_failure() {
454+
let runner = StubCommandRunner::failure("network unreachable");
455+
assert!(get_latest_cfcli_version_with(&runner).is_err());
456+
}
426457
}

‎cli/src/install.rs‎

Lines changed: 93 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::command_runner::{CommandRunner, RealCommandRunner};
12
use crate::errors::CliError;
23
use crate::essential::{BASE_COMMAND, connect_to_client, create_config_file, create_configs};
34
use clap::{Args, Subcommand};
@@ -453,13 +454,16 @@ fn rm_installation_files(file_to_remove: InstallationType) -> Result<(), CliErro
453454
// Returns a CliError if something fails
454455

455456
fn download_file(src: &str) -> Result<(), CliError> {
456-
let output =
457-
Command::new("wget")
458-
.args([src])
459-
.output()
460-
.map_err(|e| CliError::InstallerError {
461-
reason: e.to_string(),
462-
})?;
457+
download_file_with(&RealCommandRunner, src)
458+
}
459+
460+
fn download_file_with(runner: &dyn CommandRunner, src: &str) -> Result<(), CliError> {
461+
let args = [src.to_string()];
462+
let output = runner
463+
.run("wget", &args)
464+
.map_err(|e| CliError::InstallerError {
465+
reason: e.to_string(),
466+
})?;
463467

464468
if !output.status.success() {
465469
return Err(CliError::InstallerError {
@@ -486,6 +490,13 @@ fn download_file(src: &str) -> Result<(), CliError> {
486490
// Returns an CliError if something fails
487491

488492
fn rm_file(file_to_remove: &str) -> Result<(), CliError> {
493+
// rm -f never fails for a missing file, so check existence first
494+
if !std::path::Path::new(file_to_remove).exists() {
495+
return Err(CliError::InstallerError {
496+
reason: format!("File not found: {}", file_to_remove),
497+
});
498+
}
499+
489500
let output = Command::new("rm")
490501
.args(["-f", file_to_remove])
491502
.output()
@@ -508,3 +519,78 @@ fn rm_file(file_to_remove: &str) -> Result<(), CliError> {
508519
thread::sleep(Duration::from_secs(2));
509520
Ok(())
510521
}
522+
523+
#[cfg(test)]
524+
mod tests {
525+
use super::*;
526+
527+
#[test]
528+
fn test_rm_file() {
529+
let file_name = "test_file.txt";
530+
std::fs::write(file_name, "test content").unwrap();
531+
assert!(rm_file(file_name).is_ok());
532+
assert!(!std::path::Path::new(file_name).exists());
533+
}
534+
535+
#[test]
536+
fn test_download_file_with_success() {
537+
let runner = crate::command_runner::test_support::StubCommandRunner::success("");
538+
assert!(download_file_with(&runner, "https://example.com/file.yaml").is_ok());
539+
}
540+
541+
#[test]
542+
fn test_download_file_with_command_failure() {
543+
let runner = crate::command_runner::test_support::StubCommandRunner::failure("404 Not Found");
544+
assert!(download_file_with(&runner, "https://example.com/missing.yaml").is_err());
545+
}
546+
547+
#[test]
548+
fn test_download_file_with_io_error() {
549+
let runner = crate::command_runner::test_support::StubCommandRunner::io_error();
550+
assert!(download_file_with(&runner, "https://example.com/file.yaml").is_err());
551+
}
552+
553+
#[test]
554+
fn test_rm_file_failure() {
555+
let file_name = "non_existent_file.txt";
556+
assert!(rm_file(file_name).is_err());
557+
}
558+
559+
#[test]
560+
fn test_rm_file_cleanup_only() {
561+
let file_name = "test_file.txt";
562+
std::fs::write(file_name, "test content").unwrap();
563+
// Clean up without removing
564+
rm_file(file_name).unwrap();
565+
}
566+
567+
#[test]
568+
fn test_rm_file_failure_cleanup() {
569+
let file_name = "non_existent_file.txt";
570+
// Attempt to clean up a non-existent file
571+
assert!(rm_file(file_name).is_err());
572+
}
573+
574+
#[test]
575+
fn test_rm_file_success_cleanup() {
576+
let file_name = "test_file.txt";
577+
std::fs::write(file_name, "test content").unwrap();
578+
// Clean up a file that exists
579+
assert!(rm_file(file_name).is_ok());
580+
}
581+
582+
#[test]
583+
fn test_rm_file_success_cleanup_only() {
584+
let file_name = "test_file.txt";
585+
std::fs::write(file_name, "test content").unwrap();
586+
// Clean up a file that exists
587+
assert!(rm_file(file_name).is_ok());
588+
}
589+
590+
#[test]
591+
fn test_rm_file_failure_cleanup_only() {
592+
let file_name = "non_existent_file.txt";
593+
// Attempt to clean up a non-existent file
594+
assert!(rm_file(file_name).is_err());
595+
}
596+
}

0 commit comments

Comments
 (0)