mirror of
https://github.com/nushell/nushell.git
synced 2025-08-17 22:59:52 +02:00
Add test support crate for plugin developers (#12259)
# Description Adds a `nu-plugin-test-support` crate with an interface that supports testing plugins. Unlike in reality, these plugins run in the same process on separate threads. This will allow testing aspects of the plugin internal state and handling serialized plugin custom values easily. We still serialize their custom values and all of the engine to plugin logic is still in play, so from a logical perspective this should still expose any bugs that would have been caused by that. The only difference is that it doesn't run in a different process, and doesn't try to serialize everything to the final wire format for stdin/stdout. TODO still: - [x] Clean up warnings about private types exposed in trait definition - [x] Automatically deserialize plugin custom values in the result so they can be inspected - [x] Automatic plugin examples test function - [x] Write a bit more documentation - [x] More tests - [x] Add MIT License file to new crate # User-Facing Changes Plugin developers get a nice way to test their plugins. # Tests + Formatting Run the tests with `cargo test -p nu-plugin-test-support -- --show-output` to see some examples of what the failing test output for examples can look like. I used the `difference` crate (MIT licensed) to make it look nice. - 🟢 `toolkit fmt` - 🟢 `toolkit clippy` - 🟢 `toolkit test` - 🟢 `toolkit test stdlib` # After Submitting - [ ] Add a section to the book about testing - [ ] Test some of the example plugins this way - [ ] Add example tests to nu_plugin_template so plugin developers have something to start with
This commit is contained in:
@@ -192,7 +192,10 @@ impl CustomValueOp {
|
||||
}
|
||||
|
||||
/// Any data sent to the plugin
|
||||
///
|
||||
/// Note: exported for internal use, not public.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[doc(hidden)]
|
||||
pub enum PluginInput {
|
||||
/// This must be the first message. Indicates supported protocol
|
||||
Hello(ProtocolInfo),
|
||||
|
@@ -20,7 +20,10 @@ mod tests;
|
||||
/// appropriate [`PluginSource`](crate::plugin::PluginSource), ensuring that only
|
||||
/// [`PluginCustomData`] is contained within any values sent, and that the `source` of any
|
||||
/// values sent matches the plugin it is being sent to.
|
||||
///
|
||||
/// This is not a public API.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[doc(hidden)]
|
||||
pub struct PluginCustomValue {
|
||||
#[serde(flatten)]
|
||||
shared: SerdeArc<SharedContent>,
|
||||
@@ -197,12 +200,9 @@ impl PluginCustomValue {
|
||||
})
|
||||
})?;
|
||||
|
||||
// Envs probably should be passed here, but it's likely that the plugin is already running
|
||||
let empty_envs = std::iter::empty::<(&str, &str)>();
|
||||
|
||||
source
|
||||
.persistent(span)
|
||||
.and_then(|p| p.get(|| Ok(empty_envs)))
|
||||
.and_then(|p| p.get_plugin(None))
|
||||
.map_err(wrap_err)
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ impl PluginCustomValue {
|
||||
}
|
||||
|
||||
/// Add a [`PluginSource`] to all [`PluginCustomValue`]s within a value, recursively.
|
||||
pub(crate) fn add_source(value: &mut Value, source: &Arc<PluginSource>) {
|
||||
pub fn add_source(value: &mut Value, source: &Arc<PluginSource>) {
|
||||
// This can't cause an error.
|
||||
let _: Result<(), Infallible> = value.recurse_mut(&mut |value| {
|
||||
let span = value.span();
|
||||
@@ -318,7 +318,7 @@ impl PluginCustomValue {
|
||||
|
||||
/// Convert all plugin-native custom values to [`PluginCustomValue`] within the given `value`,
|
||||
/// recursively. This should only be done on the plugin side.
|
||||
pub(crate) fn serialize_custom_values_in(value: &mut Value) -> Result<(), ShellError> {
|
||||
pub fn serialize_custom_values_in(value: &mut Value) -> Result<(), ShellError> {
|
||||
value.recurse_mut(&mut |value| {
|
||||
let span = value.span();
|
||||
match value {
|
||||
@@ -344,7 +344,7 @@ impl PluginCustomValue {
|
||||
|
||||
/// Convert all [`PluginCustomValue`]s to plugin-native custom values within the given `value`,
|
||||
/// recursively. This should only be done on the plugin side.
|
||||
pub(crate) fn deserialize_custom_values_in(value: &mut Value) -> Result<(), ShellError> {
|
||||
pub fn deserialize_custom_values_in(value: &mut Value) -> Result<(), ShellError> {
|
||||
value.recurse_mut(&mut |value| {
|
||||
let span = value.span();
|
||||
match value {
|
||||
|
Reference in New Issue
Block a user