diff --git a/src/cmd/describegpt.rs b/src/cmd/describegpt.rs index 2ce85729b..dfac8e090 100644 --- a/src/cmd/describegpt.rs +++ b/src/cmd/describegpt.rs @@ -391,6 +391,7 @@ pub fn run(argv: &[&str]) -> CliResult<()> { )?; // safety: we just checked that there is at least one input file let arg_input = work_input[0] + .canonicalize()? .clone() .into_os_string() .into_string() @@ -404,15 +405,18 @@ pub fn run(argv: &[&str]) -> CliResult<()> { return fail!("Error: --all option cannot be specified with other inference flags."); } + // Get qsv executable's path + let root = env::current_exe().unwrap(); + // Get stats from qsv stats on input file with --everything flag eprintln!("Generating stats from {arg_input} using qsv stats --everything..."); - let Ok(stats) = Command::new("qsv") + let Ok(stats) = Command::new(root.clone()) .arg("stats") .arg("--everything") .arg(arg_input.clone()) .output() else { - return fail!("Error: Unable to parse stats as &str."); + return fail!("Error: Error while generating stats."); }; // Parse the stats as &str @@ -422,8 +426,8 @@ pub fn run(argv: &[&str]) -> CliResult<()> { // Get frequency from qsv frequency on input file eprintln!("Generating frequency from {arg_input} using qsv frequency..."); - let Ok(frequency) = Command::new("qsv").arg("frequency").arg(arg_input).output() else { - return fail!("Error: Unable to get frequency from qsv."); + let Ok(frequency) = Command::new(root).arg("frequency").arg(arg_input).output() else { + return fail!("Error: Error while generating frequency."); }; // Parse the frequency as &str diff --git a/tests/test_describegpt.rs b/tests/test_describegpt.rs index f4bcb7474..0b4e1de37 100644 --- a/tests/test_describegpt.rs +++ b/tests/test_describegpt.rs @@ -1,8 +1,12 @@ -use crate::{qcheck, workdir::Workdir, CsvData}; +use crate::workdir::Workdir; +// Providing an invalid API key with --openai-key without +// the environment variable set should result in an error #[test] -fn count_simple() { - let wrk = Workdir::new("count_simple"); +// #[ignore = "Requires environment variable to NOT be set."] +fn describegpt_invalid_api_key() { + let wrk = Workdir::new("describegpt"); + // Create a CSV file with sample data wrk.create_indexed( "in.csv", vec![ @@ -12,172 +16,110 @@ fn count_simple() { svec!["gamma", "37"], ], ); - let mut cmd = wrk.command("count"); - cmd.arg("in.csv"); - let got: String = wrk.stdout(&mut cmd); - let expected = "3"; - assert_eq!(got, expected.to_string()); + // Run the command + let mut cmd = wrk.command("describegpt"); + cmd.arg("in.csv") + .arg("--all") + .arg("--json") + .args(["--openai-key", "INVALIDKEY"]) + .args(["--max-tokens", "1000"]); + + // Error message + let got_stderr = wrk.output_stderr(&mut cmd); + // Check that we receive the correct error message + assert!(got_stderr.contains("Incorrect API key provided: INVALIDKEY")); } +// Verify --user-agent is passed to OpenAI #[test] -fn count_width() { - let wrk = Workdir::new("count_width"); +#[ignore = "Requires environment variable to be set."] +fn describegpt_user_agent() { + let wrk = Workdir::new("describegpt"); + // Create a CSV file with sample data wrk.create_indexed( "in.csv", vec![ svec!["letter", "number"], svec!["alpha", "13"], svec!["beta", "24"], + svec!["gamma", "37"], ], ); - let mut cmd = wrk.command("count"); - cmd.arg("--width").arg("in.csv"); - let got: String = wrk.stdout(&mut cmd); - let expected = "2;9"; - assert_eq!(got, expected.to_string()); + // Run the command + let mut cmd = wrk.command("describegpt"); + cmd.arg("in.csv") + .arg("--all") + .arg("--json") + .args([ + "--user-agent", + "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", + ]) + .args(["--max-tokens", "1000"]); + + // Check that the command ran successfully + wrk.assert_success(&mut cmd); } +// Valid use of describegpt #[test] -fn count_comments() { - let wrk = Workdir::new("count_comments"); +#[ignore = "Requires environment variable to be set."] +fn describegpt_valid() { + let wrk = Workdir::new("describegpt"); - wrk.create( + // Create a CSV file with sample data + wrk.create_indexed( "in.csv", vec![ - svec!["# this is a comment", ""], - svec!["# next comment", ""], svec!["letter", "number"], svec!["alpha", "13"], svec!["beta", "24"], - svec!["# comment here too!", "24"], + svec!["gamma", "37"], ], ); - let mut cmd = wrk.command("count"); - cmd.arg("in.csv").env("QSV_COMMENT_CHAR", "#"); - - let got: String = wrk.stdout(&mut cmd); - let expected = "2"; - assert_eq!(got, expected.to_string()); -} - -/// This tests whether `qsv count` gets the right answer. -/// -/// It does some simple case analysis to handle whether we want to test counts -/// in the presence of headers and/or indexes. -fn prop_count_len( - name: &str, - rows: CsvData, - headers: bool, - idx: bool, - noheaders_env: bool, - human_readable: bool, -) -> bool { - let mut expected_count = rows.len(); - if headers && expected_count > 0 { - expected_count -= 1; - } - - let wrk = Workdir::new(name); - if idx { - wrk.create_indexed("in.csv", rows); - } else { - wrk.create("in.csv", rows); - } - - let mut cmd = wrk.command("count"); - if !headers { - cmd.arg("--no-headers"); - } - if noheaders_env { - cmd.env("QSV_NO_HEADERS", "1"); - } - if human_readable { - cmd.arg("--human-readable"); - } - cmd.arg("in.csv"); - if human_readable { - use thousands::Separable; + // Run the command + let mut cmd = wrk.command("describegpt"); + cmd.arg("in.csv") + .arg("--all") + .args(["--max-tokens", "1000"]); - let got_count: String = wrk.stdout(&mut cmd); - let expected_count_commas = expected_count.separate_with_commas(); - - rassert_eq!(got_count, expected_count_commas) - } else { - let got_count: usize = wrk.stdout(&mut cmd); - rassert_eq!(got_count, expected_count) - } -} - -#[test] -fn prop_count() { - fn p(rows: CsvData) -> bool { - prop_count_len("prop_count", rows, false, false, false, false) - } - qcheck(p as fn(CsvData) -> bool); + // Check that the command ran successfully + wrk.assert_success(&mut cmd); } +// Valid use of describegpt with --json #[test] -fn prop_count_human_readable() { - fn p(rows: CsvData) -> bool { - prop_count_len("prop_count", rows, false, false, false, true) - } - qcheck(p as fn(CsvData) -> bool); -} - -#[test] -fn prop_count_headers() { - fn p(rows: CsvData) -> bool { - prop_count_len("prop_count_headers", rows, true, false, false, false) - } - qcheck(p as fn(CsvData) -> bool); -} +#[ignore = "Requires environment variable to be set."] +fn describegpt_valid_json() { + let wrk = Workdir::new("describegpt"); -#[test] -fn prop_count_headers_human_readable() { - fn p(rows: CsvData) -> bool { - prop_count_len("prop_count_headers", rows, true, false, false, true) - } - qcheck(p as fn(CsvData) -> bool); -} - -#[test] -fn prop_count_indexed() { - fn p(rows: CsvData) -> bool { - prop_count_len("prop_count_indexed", rows, false, true, false, false) - } - qcheck(p as fn(CsvData) -> bool); -} - -#[test] -fn prop_count_indexed_headers() { - fn p(rows: CsvData) -> bool { - prop_count_len("prop_count_indexed_headers", rows, true, true, false, false) - } - qcheck(p as fn(CsvData) -> bool); -} + // Create a CSV file with sample data + wrk.create_indexed( + "in.csv", + vec![ + svec!["letter", "number"], + svec!["alpha", "13"], + svec!["beta", "24"], + svec!["gamma", "37"], + ], + ); -#[test] -fn prop_count_noheaders_env() { - fn p(rows: CsvData) -> bool { - prop_count_len("prop_count_noheaders_env", rows, false, false, true, false) + // Run the command + let mut cmd = wrk.command("describegpt"); + cmd.arg("in.csv") + .arg("--all") + .arg("--json") + .args(["--max-tokens", "1000"]); + + // Check that the output is valid JSON + let got = wrk.stdout::(&mut cmd); + match serde_json::from_str::(&got) { + Ok(_) => (), + Err(e) => assert!(false, "Error parsing JSON: {e}"), } - qcheck(p as fn(CsvData) -> bool); -} -#[test] -fn prop_count_noheaders_indexed_env() { - fn p(rows: CsvData) -> bool { - prop_count_len( - "prop_count_noheaders_indexed_env", - rows, - false, - true, - true, - false, - ) - } - qcheck(p as fn(CsvData) -> bool); + // Check that the command ran successfully + wrk.assert_success(&mut cmd); } diff --git a/tests/tests.rs b/tests/tests.rs index bc613f7e0..f2ef12b7e 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -42,6 +42,7 @@ mod test_combos; mod test_comments; mod test_count; mod test_dedup; +mod test_describegpt; mod test_diff; #[cfg(any(feature = "feature_capable", feature = "lite"))] mod test_enumerate;