nushell/tests/plugins/registry_file.rs
Devyn Cairns 25cbcb511d
Rename plugin cache file ⇒ plugin registry file (#12634)
# Description
So far this seems like the winner of my poll on what the name should be.
I'll take this off draft once the poll expires, if this is indeed the
winner.
2024-04-24 17:40:39 -05:00

475 lines
15 KiB
Rust

use std::{fs::File, path::PathBuf};
use nu_protocol::{PluginRegistryFile, PluginRegistryItem, PluginRegistryItemData};
use nu_test_support::{fs::Stub, nu, nu_with_plugins, playground::Playground};
fn example_plugin_path() -> PathBuf {
nu_test_support::commands::ensure_plugins_built();
let bins_path = nu_test_support::fs::binaries();
nu_path::canonicalize_with(
if cfg!(windows) {
"nu_plugin_example.exe"
} else {
"nu_plugin_example"
},
bins_path,
)
.expect("nu_plugin_example not found")
}
#[test]
fn plugin_add_then_restart_nu() {
let result = nu_with_plugins!(
cwd: ".",
plugins: [],
&format!("
plugin add '{}'
(
^$nu.current-exe
--config $nu.config-path
--env-config $nu.env-path
--plugin-config $nu.plugin-path
--commands 'plugin list | get name | to json --raw'
)
", example_plugin_path().display())
);
assert!(result.status.success());
assert_eq!(r#"["example"]"#, result.out);
}
#[test]
fn plugin_add_in_nu_plugin_dirs_const() {
let example_plugin_path = example_plugin_path();
let dirname = example_plugin_path.parent().expect("no parent");
let filename = example_plugin_path
.file_name()
.expect("no file_name")
.to_str()
.expect("not utf-8");
let result = nu_with_plugins!(
cwd: ".",
plugins: [],
&format!(
r#"
$env.NU_PLUGIN_DIRS = null
const NU_PLUGIN_DIRS = ['{0}']
plugin add '{1}'
(
^$nu.current-exe
--config $nu.config-path
--env-config $nu.env-path
--plugin-config $nu.plugin-path
--commands 'plugin list | get name | to json --raw'
)
"#,
dirname.display(),
filename
)
);
assert!(result.status.success());
assert_eq!(r#"["example"]"#, result.out);
}
#[test]
fn plugin_add_in_nu_plugin_dirs_env() {
let example_plugin_path = example_plugin_path();
let dirname = example_plugin_path.parent().expect("no parent");
let filename = example_plugin_path
.file_name()
.expect("no file_name")
.to_str()
.expect("not utf-8");
let result = nu_with_plugins!(
cwd: ".",
plugins: [],
&format!(
r#"
$env.NU_PLUGIN_DIRS = ['{0}']
plugin add '{1}'
(
^$nu.current-exe
--config $nu.config-path
--env-config $nu.env-path
--plugin-config $nu.plugin-path
--commands 'plugin list | get name | to json --raw'
)
"#,
dirname.display(),
filename
)
);
assert!(result.status.success());
assert_eq!(r#"["example"]"#, result.out);
}
#[test]
fn plugin_add_to_custom_path() {
let example_plugin_path = example_plugin_path();
Playground::setup("plugin add to custom path", |dirs, _playground| {
let result = nu!(
cwd: dirs.test(),
&format!("
plugin add --plugin-config test-plugin-file.msgpackz '{}'
", example_plugin_path.display())
);
assert!(result.status.success());
let contents = PluginRegistryFile::read_from(
File::open(dirs.test().join("test-plugin-file.msgpackz"))
.expect("failed to open plugin file"),
None,
)
.expect("failed to read plugin file");
assert_eq!(1, contents.plugins.len());
assert_eq!("example", contents.plugins[0].name);
})
}
#[test]
fn plugin_rm_then_restart_nu() {
let example_plugin_path = example_plugin_path();
Playground::setup("plugin rm from custom path", |dirs, playground| {
playground.with_files(vec![
Stub::FileWithContent("config.nu", ""),
Stub::FileWithContent("env.nu", ""),
]);
let file = File::create(dirs.test().join("test-plugin-file.msgpackz"))
.expect("failed to create file");
let mut contents = PluginRegistryFile::new();
contents.upsert_plugin(PluginRegistryItem {
name: "example".into(),
filename: example_plugin_path,
shell: None,
data: PluginRegistryItemData::Valid { commands: vec![] },
});
contents.upsert_plugin(PluginRegistryItem {
name: "foo".into(),
// this doesn't exist, but it should be ok
filename: dirs.test().join("nu_plugin_foo"),
shell: None,
data: PluginRegistryItemData::Valid { commands: vec![] },
});
contents
.write_to(file, None)
.expect("failed to write plugin file");
assert_cmd::Command::new(nu_test_support::fs::executable_path())
.current_dir(dirs.test())
.args([
"--no-std-lib",
"--config",
"config.nu",
"--env-config",
"env.nu",
"--plugin-config",
"test-plugin-file.msgpackz",
"--commands",
"plugin rm example",
])
.assert()
.success()
.stderr("");
assert_cmd::Command::new(nu_test_support::fs::executable_path())
.current_dir(dirs.test())
.args([
"--no-std-lib",
"--config",
"config.nu",
"--env-config",
"env.nu",
"--plugin-config",
"test-plugin-file.msgpackz",
"--commands",
"plugin list | get name | to json --raw",
])
.assert()
.success()
.stdout("[\"foo\"]\n");
})
}
#[test]
fn plugin_rm_not_found() {
let result = nu_with_plugins!(
cwd: ".",
plugins: [],
r#"
plugin rm example
"#
);
assert!(!result.status.success());
assert!(result.err.contains("example"));
}
#[test]
fn plugin_rm_from_custom_path() {
let example_plugin_path = example_plugin_path();
Playground::setup("plugin rm from custom path", |dirs, _playground| {
let file = File::create(dirs.test().join("test-plugin-file.msgpackz"))
.expect("failed to create file");
let mut contents = PluginRegistryFile::new();
contents.upsert_plugin(PluginRegistryItem {
name: "example".into(),
filename: example_plugin_path,
shell: None,
data: PluginRegistryItemData::Valid { commands: vec![] },
});
contents.upsert_plugin(PluginRegistryItem {
name: "foo".into(),
// this doesn't exist, but it should be ok
filename: dirs.test().join("nu_plugin_foo"),
shell: None,
data: PluginRegistryItemData::Valid { commands: vec![] },
});
contents
.write_to(file, None)
.expect("failed to write plugin file");
let result = nu!(
cwd: dirs.test(),
"plugin rm --plugin-config test-plugin-file.msgpackz example",
);
assert!(result.status.success());
assert!(result.err.trim().is_empty());
// Check the contents after running
let contents = PluginRegistryFile::read_from(
File::open(dirs.test().join("test-plugin-file.msgpackz")).expect("failed to open file"),
None,
)
.expect("failed to read file");
assert!(!contents.plugins.iter().any(|p| p.name == "example"));
// Shouldn't remove anything else
assert!(contents.plugins.iter().any(|p| p.name == "foo"));
})
}
#[test]
fn plugin_rm_using_filename() {
let example_plugin_path = example_plugin_path();
Playground::setup("plugin rm using filename", |dirs, _playground| {
let file = File::create(dirs.test().join("test-plugin-file.msgpackz"))
.expect("failed to create file");
let mut contents = PluginRegistryFile::new();
contents.upsert_plugin(PluginRegistryItem {
name: "example".into(),
filename: example_plugin_path.clone(),
shell: None,
data: PluginRegistryItemData::Valid { commands: vec![] },
});
contents.upsert_plugin(PluginRegistryItem {
name: "foo".into(),
// this doesn't exist, but it should be ok
filename: dirs.test().join("nu_plugin_foo"),
shell: None,
data: PluginRegistryItemData::Valid { commands: vec![] },
});
contents
.write_to(file, None)
.expect("failed to write plugin file");
let result = nu!(
cwd: dirs.test(),
&format!(
"plugin rm --plugin-config test-plugin-file.msgpackz '{}'",
example_plugin_path.display()
)
);
assert!(result.status.success());
assert!(result.err.trim().is_empty());
// Check the contents after running
let contents = PluginRegistryFile::read_from(
File::open(dirs.test().join("test-plugin-file.msgpackz")).expect("failed to open file"),
None,
)
.expect("failed to read file");
assert!(!contents.plugins.iter().any(|p| p.name == "example"));
// Shouldn't remove anything else
assert!(contents.plugins.iter().any(|p| p.name == "foo"));
})
}
/// Running nu with a test plugin file that fails to parse on one plugin should just cause a warning
/// but the others should be loaded
#[test]
fn warning_on_invalid_plugin_item() {
let example_plugin_path = example_plugin_path();
Playground::setup("warning on invalid plugin item", |dirs, playground| {
playground.with_files(vec![
Stub::FileWithContent("config.nu", ""),
Stub::FileWithContent("env.nu", ""),
]);
let file = File::create(dirs.test().join("test-plugin-file.msgpackz"))
.expect("failed to create file");
let mut contents = PluginRegistryFile::new();
contents.upsert_plugin(PluginRegistryItem {
name: "example".into(),
filename: example_plugin_path,
shell: None,
data: PluginRegistryItemData::Valid { commands: vec![] },
});
contents.upsert_plugin(PluginRegistryItem {
name: "badtest".into(),
// this doesn't exist, but it should be ok
filename: dirs.test().join("nu_plugin_badtest"),
shell: None,
data: PluginRegistryItemData::Invalid,
});
contents
.write_to(file, None)
.expect("failed to write plugin file");
let result = assert_cmd::Command::new(nu_test_support::fs::executable_path())
.current_dir(dirs.test())
.args([
"--no-std-lib",
"--config",
"config.nu",
"--env-config",
"env.nu",
"--plugin-config",
"test-plugin-file.msgpackz",
"--commands",
"plugin list | get name | to json --raw",
])
.output()
.expect("failed to run nu");
let out = String::from_utf8_lossy(&result.stdout).trim().to_owned();
let err = String::from_utf8_lossy(&result.stderr).trim().to_owned();
println!("=== stdout\n{out}\n=== stderr\n{err}");
// The code should still execute successfully
assert!(result.status.success());
// The "example" plugin should be unaffected
assert_eq!(r#"["example"]"#, out);
// The warning should be in there
assert!(err.contains("registered plugin data"));
assert!(err.contains("badtest"));
})
}
#[test]
fn plugin_use_error_not_found() {
Playground::setup("plugin use error not found", |dirs, playground| {
playground.with_files(vec![
Stub::FileWithContent("config.nu", ""),
Stub::FileWithContent("env.nu", ""),
]);
// Make an empty msgpackz
let file = File::create(dirs.test().join("plugin.msgpackz"))
.expect("failed to open plugin.msgpackz");
PluginRegistryFile::default()
.write_to(file, None)
.expect("failed to write empty registry file");
let output = assert_cmd::Command::new(nu_test_support::fs::executable_path())
.current_dir(dirs.test())
.args(["--config", "config.nu"])
.args(["--env-config", "env.nu"])
.args(["--plugin-config", "plugin.msgpackz"])
.args(["--commands", "plugin use custom_values"])
.output()
.expect("failed to run nu");
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("Plugin not found"));
})
}
#[test]
fn plugin_add_and_then_use() {
let example_plugin_path = example_plugin_path();
let result = nu_with_plugins!(
cwd: ".",
plugins: [],
&format!(r#"
plugin add '{}'
(
^$nu.current-exe
--config $nu.config-path
--env-config $nu.env-path
--plugin-config $nu.plugin-path
--commands 'plugin use example; plugin list | get name | to json --raw'
)
"#, example_plugin_path.display())
);
assert!(result.status.success());
assert_eq!(r#"["example"]"#, result.out);
}
#[test]
fn plugin_add_and_then_use_by_filename() {
let example_plugin_path = example_plugin_path();
let result = nu_with_plugins!(
cwd: ".",
plugins: [],
&format!(r#"
plugin add '{0}'
(
^$nu.current-exe
--config $nu.config-path
--env-config $nu.env-path
--plugin-config $nu.plugin-path
--commands 'plugin use '{0}'; plugin list | get name | to json --raw'
)
"#, example_plugin_path.display())
);
assert!(result.status.success());
assert_eq!(r#"["example"]"#, result.out);
}
#[test]
fn plugin_add_then_use_with_custom_path() {
let example_plugin_path = example_plugin_path();
Playground::setup("plugin add to custom path", |dirs, _playground| {
let result_add = nu!(
cwd: dirs.test(),
&format!("
plugin add --plugin-config test-plugin-file.msgpackz '{}'
", example_plugin_path.display())
);
assert!(result_add.status.success());
let result_use = nu!(
cwd: dirs.test(),
r#"
plugin use --plugin-config test-plugin-file.msgpackz example
plugin list | get name | to json --raw
"#
);
assert!(result_use.status.success());
assert_eq!(r#"["example"]"#, result_use.out);
})
}