diff options
author | Brian Olsen <brian@maven-group.org> | 2024-07-22T14·51+0200 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2024-08-25T15·05+0000 |
commit | ced05a2bb6b66d30208520d0791f4fa298c429e2 (patch) | |
tree | d295eb9766db79df8f3053bc5022e24059012f16 /tvix/nix-compat-derive-tests | |
parent | 9af69204787d47cfe551f524d01b1a726971f06e (diff) |
feat(tvix/nix-compat-derive): Add deriver for NixDeserialize r/8586
This adds a nix-compat-derive derive crate that implements a deriver for NixDeserialize implementations. This is to reduce the amount of code needed to implement deserialization for all the types used by the Nix daemon protocol. Change-Id: I484724b550e8a1d5e9adad9555d9dc1374ae95c2 Reviewed-on: https://cl.tvl.fyi/c/depot/+/12022 Autosubmit: Brian Olsen <me@griff.name> Tested-by: BuildkiteCI Reviewed-by: flokli <flokli@flokli.de>
Diffstat (limited to 'tvix/nix-compat-derive-tests')
34 files changed, 756 insertions, 0 deletions
diff --git a/tvix/nix-compat-derive-tests/Cargo.toml b/tvix/nix-compat-derive-tests/Cargo.toml new file mode 100644 index 000000000000..31a334b920f3 --- /dev/null +++ b/tvix/nix-compat-derive-tests/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "nix-compat-derive-tests" +version = "0.1.0" +edition = "2021" + +[features] +compile-tests = [] + +[dev-dependencies] +hex-literal = "0.4.1" +pretty_assertions = "1.4.0" +rstest = "0.19.0" +tokio-test = "0.4.3" +trybuild = "1.0.96" + +[dev-dependencies.nix-compat] +version = "0.1.0" +path = "../nix-compat" +features = ["test", "wire"] + +[dev-dependencies.nix-compat-derive] +version = "0.1.0" +path = "../nix-compat-derive" + +[dev-dependencies.tokio] +version = "^1.38" +features = ["io-util", "macros"] diff --git a/tvix/nix-compat-derive-tests/default.nix b/tvix/nix-compat-derive-tests/default.nix new file mode 100644 index 000000000000..cabe9ad13780 --- /dev/null +++ b/tvix/nix-compat-derive-tests/default.nix @@ -0,0 +1,5 @@ +{ depot, ... }: + +depot.tvix.crates.workspaceMembers.nix-compat-derive-tests.build.override { + runTests = true; +} diff --git a/tvix/nix-compat-derive-tests/tests/read_derive.rs b/tvix/nix-compat-derive-tests/tests/read_derive.rs new file mode 100644 index 000000000000..055d70cf046e --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/read_derive.rs @@ -0,0 +1,417 @@ +use std::str::FromStr; + +use nix_compat::nix_daemon::de::mock::{Builder, Error}; +use nix_compat::nix_daemon::de::NixRead; +use nix_compat_derive::NixDeserialize; + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct UnitTest; + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct EmptyTupleTest(); + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct StructTest { + first: u64, + second: String, +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct TupleTest(u64, String); + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct StructVersionTest { + test: u64, + #[nix(version = "20..")] + hello: String, +} + +fn default_test() -> StructVersionTest { + StructVersionTest { + test: 89, + hello: String::from("klomp"), + } +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct TupleVersionTest(u64, #[nix(version = "25..")] String); + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct TupleVersionDefaultTest( + u64, + #[nix(version = "..25", default = "default_test")] StructVersionTest, +); + +#[tokio::test] +async fn read_unit() { + let mut mock = Builder::new().build(); + let v: UnitTest = mock.read_value().await.unwrap(); + assert_eq!(UnitTest, v); +} + +#[tokio::test] +async fn read_empty_tuple() { + let mut mock = Builder::new().build(); + let v: EmptyTupleTest = mock.read_value().await.unwrap(); + assert_eq!(EmptyTupleTest(), v); +} + +#[tokio::test] +async fn read_struct() { + let mut mock = Builder::new().read_number(89).read_slice(b"klomp").build(); + let v: StructTest = mock.read_value().await.unwrap(); + assert_eq!( + StructTest { + first: 89, + second: String::from("klomp"), + }, + v + ); +} + +#[tokio::test] +async fn read_tuple() { + let mut mock = Builder::new().read_number(89).read_slice(b"klomp").build(); + let v: TupleTest = mock.read_value().await.unwrap(); + assert_eq!(TupleTest(89, String::from("klomp")), v); +} + +#[tokio::test] +async fn read_struct_version() { + let mut mock = Builder::new() + .version((1, 20)) + .read_number(89) + .read_slice(b"klomp") + .build(); + let v: StructVersionTest = mock.read_value().await.unwrap(); + assert_eq!(default_test(), v); +} + +#[tokio::test] +async fn read_struct_without_version() { + let mut mock = Builder::new().version((1, 19)).read_number(89).build(); + let v: StructVersionTest = mock.read_value().await.unwrap(); + assert_eq!( + StructVersionTest { + test: 89, + hello: String::new(), + }, + v + ); +} + +#[tokio::test] +async fn read_tuple_version() { + let mut mock = Builder::new() + .version((1, 26)) + .read_number(89) + .read_slice(b"klomp") + .build(); + let v: TupleVersionTest = mock.read_value().await.unwrap(); + assert_eq!(TupleVersionTest(89, "klomp".into()), v); +} + +#[tokio::test] +async fn read_tuple_without_version() { + let mut mock = Builder::new().version((1, 19)).read_number(89).build(); + let v: TupleVersionTest = mock.read_value().await.unwrap(); + assert_eq!(TupleVersionTest(89, String::new()), v); +} + +#[tokio::test] +async fn read_complex_1() { + let mut mock = Builder::new() + .version((1, 19)) + .read_number(999) + .read_number(666) + .build(); + let v: TupleVersionDefaultTest = mock.read_value().await.unwrap(); + assert_eq!( + TupleVersionDefaultTest( + 999, + StructVersionTest { + test: 666, + hello: String::new() + } + ), + v + ); +} + +#[tokio::test] +async fn read_complex_2() { + let mut mock = Builder::new() + .version((1, 20)) + .read_number(999) + .read_number(666) + .read_slice(b"The quick brown \xF0\x9F\xA6\x8A jumps over 13 lazy \xF0\x9F\x90\xB6.") + .build(); + let v: TupleVersionDefaultTest = mock.read_value().await.unwrap(); + assert_eq!( + TupleVersionDefaultTest( + 999, + StructVersionTest { + test: 666, + hello: String::from("The quick brown 🦊 jumps over 13 lazy 🐶.") + } + ), + v + ); +} + +#[tokio::test] +async fn read_complex_3() { + let mut mock = Builder::new().version((1, 25)).read_number(999).build(); + let v: TupleVersionDefaultTest = mock.read_value().await.unwrap(); + assert_eq!( + TupleVersionDefaultTest( + 999, + StructVersionTest { + test: 89, + hello: String::from("klomp") + } + ), + v + ); +} + +#[tokio::test] +async fn read_complex_4() { + let mut mock = Builder::new().version((1, 26)).read_number(999).build(); + let v: TupleVersionDefaultTest = mock.read_value().await.unwrap(); + assert_eq!( + TupleVersionDefaultTest( + 999, + StructVersionTest { + test: 89, + hello: String::from("klomp") + } + ), + v + ); +} + +#[tokio::test] +async fn read_field_invalid_data() { + let mut mock = Builder::new() + .read_number(666) + .read_slice(b"The quick brown \xED\xA0\x80 jumped.") + .build(); + let err = mock.read_value::<StructTest>().await.unwrap_err(); + assert_eq!( + Error::InvalidData("invalid utf-8 sequence of 1 bytes from index 16".into()), + err + ); +} + +#[tokio::test] +async fn read_field_missing_data() { + let mut mock = Builder::new().read_number(666).build(); + let err = mock.read_value::<StructTest>().await.unwrap_err(); + assert_eq!(Error::MissingData("unexpected end-of-file".into()), err); +} + +#[tokio::test] +async fn read_field_no_data() { + let mut mock = Builder::new().build(); + let err = mock.read_value::<StructTest>().await.unwrap_err(); + assert_eq!(Error::MissingData("unexpected end-of-file".into()), err); +} + +#[tokio::test] +async fn read_field_reader_error_first() { + let mut mock = Builder::new() + .read_number_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<StructTest>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[tokio::test] +async fn read_field_reader_error_later() { + let mut mock = Builder::new() + .read_number(999) + .read_bytes_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<StructTest>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +#[nix(from_str)] +struct TestFromStr; + +impl FromStr for TestFromStr { + type Err = String; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + if s == "test" { + Ok(TestFromStr) + } else { + Err(s.into()) + } + } +} + +#[tokio::test] +async fn read_from_str() { + let mut mock = Builder::new().read_slice(b"test").build(); + let value = mock.read_value::<TestFromStr>().await.unwrap(); + assert_eq!(TestFromStr, value); +} + +#[tokio::test] +async fn read_from_str_invalid_data() { + let mut mock = Builder::new().read_slice(b"wrong string").build(); + let err = mock.read_value::<TestFromStr>().await.unwrap_err(); + assert_eq!(Error::InvalidData("wrong string".into()), err); +} + +#[tokio::test] +async fn read_from_str_invalid_string() { + let mut mock = Builder::new() + .read_slice(b"The quick brown \xED\xA0\x80 jumped.") + .build(); + let err = mock.read_value::<TestFromStr>().await.unwrap_err(); + assert_eq!( + Error::InvalidData("invalid utf-8 sequence of 1 bytes from index 16".into()), + err + ); +} + +#[tokio::test] +async fn read_from_str_reader_error() { + let mut mock = Builder::new() + .read_bytes_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<TestFromStr>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +#[nix(try_from = "u64")] +struct TestTryFromU64; + +impl TryFrom<u64> for TestTryFromU64 { + type Error = u64; + + fn try_from(value: u64) -> Result<TestTryFromU64, Self::Error> { + if value == 42 { + Ok(TestTryFromU64) + } else { + Err(value) + } + } +} + +#[tokio::test] +async fn read_try_from_u64() { + let mut mock = Builder::new().read_number(42).build(); + let value = mock.read_value::<TestTryFromU64>().await.unwrap(); + assert_eq!(TestTryFromU64, value); +} + +#[tokio::test] +async fn read_try_from_u64_invalid_data() { + let mut mock = Builder::new().read_number(666).build(); + let err = mock.read_value::<TestTryFromU64>().await.unwrap_err(); + assert_eq!(Error::InvalidData("666".into()), err); +} + +#[tokio::test] +async fn read_try_from_u64_reader_error() { + let mut mock = Builder::new() + .read_number_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<TestTryFromU64>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +#[nix(from = "u64")] +struct TestFromU64; + +impl From<u64> for TestFromU64 { + fn from(_value: u64) -> TestFromU64 { + TestFromU64 + } +} + +#[tokio::test] +async fn read_from_u64() { + let mut mock = Builder::new().read_number(42).build(); + let value = mock.read_value::<TestFromU64>().await.unwrap(); + assert_eq!(TestFromU64, value); +} + +#[tokio::test] +async fn read_from_u64_reader_error() { + let mut mock = Builder::new() + .read_number_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<TestFromU64>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +enum TestEnum { + #[nix(version = "..=19")] + Pre20(TestTryFromU64), + #[nix(version = "20..")] + Post20(StructVersionTest), +} + +#[tokio::test] +async fn read_enum_19() { + let mut mock = Builder::new().version((1, 19)).read_number(42).build(); + let value = mock.read_value::<TestEnum>().await.unwrap(); + assert_eq!(TestEnum::Pre20(TestTryFromU64), value); +} + +#[tokio::test] +async fn read_enum_20() { + let mut mock = Builder::new() + .version((1, 20)) + .read_number(42) + .read_slice(b"klomp") + .build(); + let value = mock.read_value::<TestEnum>().await.unwrap(); + assert_eq!( + TestEnum::Post20(StructVersionTest { + test: 42, + hello: "klomp".into(), + }), + value + ); +} + +#[tokio::test] +async fn read_enum_reader_error() { + let mut mock = Builder::new() + .version((1, 19)) + .read_number_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<TestEnum>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[tokio::test] +async fn read_enum_invalid_data_19() { + let mut mock = Builder::new().version((1, 19)).read_number(666).build(); + let err = mock.read_value::<TestEnum>().await.unwrap_err(); + assert_eq!(Error::InvalidData("666".into()), err); +} + +#[tokio::test] +async fn read_enum_invalid_data_20() { + let mut mock = Builder::new() + .version((1, 20)) + .read_number(666) + .read_slice(b"The quick brown \xED\xA0\x80 jumped.") + .build(); + let err = mock.read_value::<TestEnum>().await.unwrap_err(); + assert_eq!( + Error::InvalidData("invalid utf-8 sequence of 1 bytes from index 16".into()), + err + ); +} diff --git a/tvix/nix-compat-derive-tests/tests/ui.rs b/tvix/nix-compat-derive-tests/tests/ui.rs new file mode 100644 index 000000000000..6a7bffeaf832 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui.rs @@ -0,0 +1,6 @@ +#[cfg(feature = "compile-tests")] +#[test] +fn ui() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/*.rs"); +} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.rs new file mode 100644 index 000000000000..f77469679999 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.rs @@ -0,0 +1,10 @@ +use nix_compat_derive::NixDeserialize; + +pub struct BadType; + +#[derive(NixDeserialize)] +pub struct Test { + version: BadType, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.stderr new file mode 100644 index 000000000000..12ffdc83c726 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `BadType: NixDeserialize` is not satisfied + --> tests/ui/deserialize_bad_type.rs:7:14 + | +7 | version: BadType, + | ^^^^^^^ the trait `NixDeserialize` is not implemented for `BadType` + | + = help: the following other types implement trait `NixDeserialize`: + BTreeMap<K, V> + String + Test + Vec<T> + bool + bytes::bytes::Bytes + i64 + u64 + usize +note: required by a bound in `try_read_value` + --> $WORKSPACE/nix-compat/src/nix_daemon/de/mod.rs + | + | fn try_read_value<V: NixDeserialize>( + | ^^^^^^^^^^^^^^ required by this bound in `NixRead::try_read_value` diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.rs new file mode 100644 index 000000000000..ab559f2b81c8 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.rs @@ -0,0 +1,13 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub enum Test { + #[nix(version = "..=10")] + Old, + #[nix(version = "15..=17")] + Legacy, + #[nix(version = "50..")] + NewWay, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.stderr new file mode 100644 index 000000000000..8a46d9439e35 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.stderr @@ -0,0 +1,8 @@ +error[E0004]: non-exhaustive patterns: `11_u8..=14_u8` and `18_u8..=49_u8` not covered + --> tests/ui/deserialize_enum_non_exaustive.rs:3:10 + | +3 | #[derive(NixDeserialize)] + | ^^^^^^^^^^^^^^ patterns `11_u8..=14_u8` and `18_u8..=49_u8` not covered + | + = note: the matched value is of type `u8` + = note: this error originates in the derive macro `NixDeserialize` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.rs new file mode 100644 index 000000000000..913b7c4f7e59 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.rs @@ -0,0 +1,7 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +#[nix(from = "u64")] +pub struct Test; + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.stderr new file mode 100644 index 000000000000..0124010cf10c --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.stderr @@ -0,0 +1,5 @@ +error[E0277]: the trait bound `Test: From<u64>` is not satisfied + --> tests/ui/deserialize_from_missing.rs:4:14 + | +4 | #[nix(from = "u64")] + | ^^^^^ the trait `From<u64>` is not implemented for `Test` diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.rs new file mode 100644 index 000000000000..36cd4b153740 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.rs @@ -0,0 +1,20 @@ +use std::str::FromStr; + +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +#[nix(from_str)] +pub struct Test; + +impl FromStr for Test { + type Err = (); + fn from_str(s: &str) -> Result<Self, Self::Err> { + if s == "test" { + Ok(Test) + } else { + Err(()) + } + } +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.stderr new file mode 100644 index 000000000000..8283ed5340f3 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.stderr @@ -0,0 +1,13 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> tests/ui/deserialize_from_str_error_not_display.rs:6:7 + | +6 | #[nix(from_str)] + | ^^^^^^^^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `invalid_data` + --> $WORKSPACE/nix-compat/src/nix_daemon/de/mod.rs + | + | fn invalid_data<T: fmt::Display>(msg: T) -> Self { + | ^^^^^^^^^^^^ required by this bound in `Error::invalid_data` diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.rs new file mode 100644 index 000000000000..a959db57e640 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.rs @@ -0,0 +1,7 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +#[nix(from_str)] +pub struct Test; + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.stderr new file mode 100644 index 000000000000..f68f588011fc --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `Test: FromStr` is not satisfied + --> tests/ui/deserialize_from_str_missing.rs:4:7 + | +4 | #[nix(from_str)] + | ^^^^^^^^ the trait `FromStr` is not implemented for `Test` + | + = help: the following other types implement trait `FromStr`: + IpAddr + Ipv4Addr + Ipv6Addr + NonZero<i128> + NonZero<i16> + NonZero<i32> + NonZero<i64> + NonZero<i8> + and $N others diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.rs new file mode 100644 index 000000000000..e9df62845518 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.rs @@ -0,0 +1,12 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Value(String); + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(version = "20..")] + version: Value, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.stderr new file mode 100644 index 000000000000..5cc2f5974e4c --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `Value: Default` is not satisfied + --> tests/ui/deserialize_missing_default.rs:6:10 + | +6 | #[derive(NixDeserialize)] + | ^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Value` + | + = note: this error originates in the derive macro `NixDeserialize` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Value` with `#[derive(Default)]` + | +4 + #[derive(Default)] +5 | pub struct Value(String); + | diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.rs new file mode 100644 index 000000000000..4f319c069dca --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.rs @@ -0,0 +1,12 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Value(String); + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(version = "20..", default = "Value::make_default")] + version: Value, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.stderr new file mode 100644 index 000000000000..bb9af749128d --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.stderr @@ -0,0 +1,8 @@ +error[E0599]: no function or associated item named `make_default` found for struct `Value` in the current scope + --> tests/ui/deserialize_missing_default_path.rs:8:39 + | +4 | pub struct Value(String); + | ---------------- function or associated item `make_default` not found for this struct +... +8 | #[nix(version = "20..", default = "Value::make_default")] + | ^^^^^^^^^^^^^^^^^^^^^ function or associated item not found in `Value` diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.rs new file mode 100644 index 000000000000..cc2ab5bfbc11 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.rs @@ -0,0 +1,15 @@ +use nix_compat_derive::nix_deserialize_remote; + +pub struct Value(String); +impl From<String> for Value { + fn from(s: String) -> Value { + Value(s) + } +} + +nix_deserialize_remote!( + #[nix()] + Value +); + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.stderr new file mode 100644 index 000000000000..a1c18adc6e48 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.stderr @@ -0,0 +1,5 @@ +error: Missing from_str, from or try_from attribute + --> tests/ui/deserialize_remote_missing_attr.rs:10:25 + | +10 | nix_deserialize_remote!(#[nix()] Value); + | ^^^^^^^^^^^^^^ diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.rs new file mode 100644 index 000000000000..7f8ad6bbfc4e --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.rs @@ -0,0 +1,19 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +#[nix(try_from = "u64")] +pub struct Test; + +impl TryFrom<u64> for Test { + type Error = (); + + fn try_from(value: u64) -> Result<Test, Self::Error> { + if value == 42 { + Ok(Test) + } else { + Err(()) + } + } +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.stderr new file mode 100644 index 000000000000..8e55a3c56189 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.stderr @@ -0,0 +1,13 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> tests/ui/deserialize_try_from_error_not_display.rs:4:18 + | +4 | #[nix(try_from = "u64")] + | ^^^^^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `invalid_data` + --> $WORKSPACE/nix-compat/src/nix_daemon/de/mod.rs + | + | fn invalid_data<T: fmt::Display>(msg: T) -> Self { + | ^^^^^^^^^^^^ required by this bound in `Error::invalid_data` diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.rs new file mode 100644 index 000000000000..899095ae3542 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.rs @@ -0,0 +1,7 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +#[nix(try_from = "u64")] +pub struct Test; + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.stderr new file mode 100644 index 000000000000..9605d1f3378f --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.stderr @@ -0,0 +1,8 @@ +error[E0277]: the trait bound `Test: From<u64>` is not satisfied + --> tests/ui/deserialize_try_from_missing.rs:4:18 + | +4 | #[nix(try_from = "u64")] + | ^^^^^ the trait `From<u64>` is not implemented for `Test`, which is required by `Test: TryFrom<u64>` + | + = note: required for `u64` to implement `Into<Test>` + = note: required for `Test` to implement `TryFrom<u64>` diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.rs b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.rs new file mode 100644 index 000000000000..d87831cecf51 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.rs @@ -0,0 +1,9 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(default = 12)] + version: u8, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.stderr b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.stderr new file mode 100644 index 000000000000..acb1bc2a47bc --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.stderr @@ -0,0 +1,5 @@ +error: expected nix attribute default to be string + --> tests/ui/parse_bad_default.rs:5:21 + | +5 | #[nix(default = 12)] + | ^^ diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.rs b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.rs new file mode 100644 index 000000000000..fbde8ffbc2b0 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.rs @@ -0,0 +1,9 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(default = "12")] + version: u8, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.stderr b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.stderr new file mode 100644 index 000000000000..7628d4c83bea --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.stderr @@ -0,0 +1,5 @@ +error: expected identifier + --> tests/ui/parse_bad_default_path.rs:5:21 + | +5 | #[nix(default = "12")] + | ^^^^ diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.rs b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.rs new file mode 100644 index 000000000000..690e76a20fe6 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.rs @@ -0,0 +1,9 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Test { + #[nix] + version: u8, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.stderr b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.stderr new file mode 100644 index 000000000000..da3d2d9aab47 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.stderr @@ -0,0 +1,5 @@ +error: expected attribute arguments in parentheses: #[nix(...)] + --> tests/ui/parse_bad_nix.rs:5:7 + | +5 | #[nix] + | ^^^ diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.rs b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.rs new file mode 100644 index 000000000000..35b3b05c23e1 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.rs @@ -0,0 +1,9 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(version = 12)] + version: u8, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.stderr b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.stderr new file mode 100644 index 000000000000..48cc817fac9d --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.stderr @@ -0,0 +1,5 @@ +error: expected nix attribute version to be string + --> tests/ui/parse_bad_version.rs:5:21 + | +5 | #[nix(version = 12)] + | ^^ diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.rs b/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.rs new file mode 100644 index 000000000000..9eaa743ed2b6 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.rs @@ -0,0 +1,9 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(version)] + version: u8, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.stderr b/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.stderr new file mode 100644 index 000000000000..79f048e11198 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.stderr @@ -0,0 +1,5 @@ +error: expected `=` + --> tests/ui/parse_mising_version.rs:5:18 + | +5 | #[nix(version)] + | ^ |