nushell/crates/nu-command/tests/format_conversions/msgpack.rs
Devyn Cairns adf38c7c76
Msgpack commands (#12664)
# Description

I thought about bringing `nu_plugin_msgpack` in, but that is MPL with a
clause that prevents other licenses, so rather than adapt that code I
decided to take a crack at just doing it straight from `rmp` to `Value`
without any `rmpv` in the middle. It seems like it's probably faster,
though I can't say for sure how much with the plugin overhead.

@IanManske I started on a `Read` implementation for `RawStream` but just
specialized to `from msgpack` here, but I'm thinking after release maybe
we can polish it up and make it a real one. It works!

# User-Facing Changes
New commands:

- `from msgpack`
- `from msgpackz`
- `to msgpack`
- `to msgpackz`

# Tests + Formatting
Pretty thorough tests added for the format deserialization, with a
roundtrip for serialization. Some example tests too for both `from
msgpack` and `to msgpack`.

- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`


# After Submitting
- [ ] update release notes
2024-04-26 06:23:16 -05:00

160 lines
4.1 KiB
Rust

use nu_test_support::{nu, playground::Playground};
use pretty_assertions::assert_eq;
fn msgpack_test(fixture_name: &str, commands: Option<&str>) -> nu_test_support::Outcome {
let path_to_generate_nu = nu_test_support::fs::fixtures()
.join("formats")
.join("msgpack")
.join("generate.nu");
let mut outcome = None;
Playground::setup(&format!("msgpack test {}", fixture_name), |dirs, _| {
assert!(nu!(
cwd: dirs.test(),
format!(
"nu -n '{}' '{}'",
path_to_generate_nu.display(),
fixture_name
),
)
.status
.success());
outcome = Some(nu!(
cwd: dirs.test(),
collapse_output: false,
commands.map(|c| c.to_owned()).unwrap_or_else(|| format!("open {fixture_name}.msgpack"))
));
});
outcome.expect("failed to get outcome")
}
fn msgpack_nuon_test(fixture_name: &str, opts: &str) {
let path_to_nuon = nu_test_support::fs::fixtures()
.join("formats")
.join("msgpack")
.join(format!("{fixture_name}.nuon"));
let sample_nuon = std::fs::read_to_string(path_to_nuon).expect("failed to open nuon file");
let outcome = msgpack_test(
fixture_name,
Some(&format!(
"open --raw {fixture_name}.msgpack | from msgpack {opts} | to nuon --indent 4"
)),
);
assert!(outcome.status.success());
assert!(outcome.err.is_empty());
assert_eq!(
sample_nuon.replace("\r\n", "\n"),
outcome.out.replace("\r\n", "\n")
);
}
#[test]
fn sample() {
msgpack_nuon_test("sample", "");
}
#[test]
fn sample_roundtrip() {
let path_to_sample_nuon = nu_test_support::fs::fixtures()
.join("formats")
.join("msgpack")
.join("sample.nuon");
let sample_nuon =
std::fs::read_to_string(&path_to_sample_nuon).expect("failed to open sample.nuon");
let outcome = nu!(
collapse_output: false,
format!(
"open '{}' | to msgpack | from msgpack | to nuon --indent 4",
path_to_sample_nuon.display()
)
);
assert!(outcome.status.success());
assert!(outcome.err.is_empty());
assert_eq!(
sample_nuon.replace("\r\n", "\n"),
outcome.out.replace("\r\n", "\n")
);
}
#[test]
fn objects() {
msgpack_nuon_test("objects", "--objects");
}
#[test]
fn max_depth() {
let outcome = msgpack_test("max-depth", None);
assert!(!outcome.status.success());
assert!(outcome.err.contains("exceeded depth limit"));
}
#[test]
fn non_utf8() {
let outcome = msgpack_test("non-utf8", None);
assert!(!outcome.status.success());
assert!(outcome.err.contains("utf-8"));
}
#[test]
fn empty() {
let outcome = msgpack_test("empty", None);
assert!(!outcome.status.success());
assert!(outcome.err.contains("fill whole buffer"));
}
#[test]
fn eof() {
let outcome = msgpack_test("eof", None);
assert!(!outcome.status.success());
assert!(outcome.err.contains("fill whole buffer"));
}
#[test]
fn after_eof() {
let outcome = msgpack_test("after-eof", None);
assert!(!outcome.status.success());
assert!(outcome.err.contains("after end of"));
}
#[test]
fn reserved() {
let outcome = msgpack_test("reserved", None);
assert!(!outcome.status.success());
assert!(outcome.err.contains("Reserved"));
}
#[test]
fn u64_too_large() {
let outcome = msgpack_test("u64-too-large", None);
assert!(!outcome.status.success());
assert!(outcome.err.contains("integer too big"));
}
#[test]
fn non_string_map_key() {
let outcome = msgpack_test("non-string-map-key", None);
assert!(!outcome.status.success());
assert!(outcome.err.contains("string key"));
}
#[test]
fn timestamp_wrong_length() {
let outcome = msgpack_test("timestamp-wrong-length", None);
assert!(!outcome.status.success());
assert!(outcome.err.contains("Unknown MessagePack extension"));
}
#[test]
fn other_extension_type() {
let outcome = msgpack_test("other-extension-type", None);
assert!(!outcome.status.success());
assert!(outcome.err.contains("Unknown MessagePack extension"));
}