about summary refs log blame commit diff
path: root/tvix/nix-compat-derive-tests/tests/write_derive.rs
blob: 1ed5dbf7e735dffc80e21e5d0732b2b8176fc60d (plain) (tree)

















































































































































































































































































































































































                                                                                              
use std::fmt;

use nix_compat::nix_daemon::ser::{
    mock::{Builder, Error},
    NixWrite as _,
};
use nix_compat_derive::NixSerialize;

#[derive(Debug, PartialEq, Eq, NixSerialize)]
pub struct UnitTest;

#[derive(Debug, PartialEq, Eq, NixSerialize)]
pub struct EmptyTupleTest();

#[derive(Debug, PartialEq, Eq, NixSerialize)]
pub struct StructTest {
    first: u64,
    second: String,
}

#[derive(Debug, PartialEq, Eq, NixSerialize)]
pub struct TupleTest(u64, String);

#[derive(Debug, PartialEq, Eq, NixSerialize)]
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, NixSerialize)]
pub struct TupleVersionTest(u64, #[nix(version = "25..")] String);

#[derive(Debug, PartialEq, Eq, NixSerialize)]
pub struct TupleVersionDefaultTest(u64, #[nix(version = "..25")] StructVersionTest);

#[tokio::test]
async fn write_unit() {
    let mut mock = Builder::new().build();
    mock.write_value(&UnitTest).await.unwrap();
}

#[tokio::test]
async fn write_empty_tuple() {
    let mut mock = Builder::new().build();
    mock.write_value(&EmptyTupleTest()).await.unwrap();
}

#[tokio::test]
async fn write_struct() {
    let mut mock = Builder::new()
        .write_number(89)
        .write_slice(b"klomp")
        .build();
    mock.write_value(&StructTest {
        first: 89,
        second: String::from("klomp"),
    })
    .await
    .unwrap();
}

#[tokio::test]
async fn write_tuple() {
    let mut mock = Builder::new()
        .write_number(89)
        .write_slice(b"klomp")
        .build();
    mock.write_value(&TupleTest(89, String::from("klomp")))
        .await
        .unwrap();
}

#[tokio::test]
async fn write_struct_version() {
    let mut mock = Builder::new()
        .version((1, 20))
        .write_number(89)
        .write_slice(b"klomp")
        .build();
    mock.write_value(&default_test()).await.unwrap();
}

#[tokio::test]
async fn write_struct_without_version() {
    let mut mock = Builder::new().version((1, 19)).write_number(89).build();
    mock.write_value(&StructVersionTest {
        test: 89,
        hello: String::new(),
    })
    .await
    .unwrap();
}

#[tokio::test]
async fn write_tuple_version() {
    let mut mock = Builder::new()
        .version((1, 26))
        .write_number(89)
        .write_slice(b"klomp")
        .build();
    mock.write_value(&TupleVersionTest(89, "klomp".into()))
        .await
        .unwrap();
}

#[tokio::test]
async fn write_tuple_without_version() {
    let mut mock = Builder::new().version((1, 19)).write_number(89).build();
    mock.write_value(&TupleVersionTest(89, String::new()))
        .await
        .unwrap();
}

#[tokio::test]
async fn write_complex_1() {
    let mut mock = Builder::new()
        .version((1, 19))
        .write_number(999)
        .write_number(666)
        .build();
    mock.write_value(&TupleVersionDefaultTest(
        999,
        StructVersionTest {
            test: 666,
            hello: String::new(),
        },
    ))
    .await
    .unwrap();
}

#[tokio::test]
async fn write_complex_2() {
    let mut mock = Builder::new()
        .version((1, 20))
        .write_number(999)
        .write_number(666)
        .write_slice(b"The quick brown \xF0\x9F\xA6\x8A jumps over 13 lazy \xF0\x9F\x90\xB6.")
        .build();
    mock.write_value(&TupleVersionDefaultTest(
        999,
        StructVersionTest {
            test: 666,
            hello: String::from("The quick brown 🦊 jumps over 13 lazy 🐶."),
        },
    ))
    .await
    .unwrap();
}

#[tokio::test]
async fn write_complex_3() {
    let mut mock = Builder::new().version((1, 25)).write_number(999).build();
    mock.write_value(&TupleVersionDefaultTest(
        999,
        StructVersionTest {
            test: 89,
            hello: String::from("klomp"),
        },
    ))
    .await
    .unwrap();
}

#[tokio::test]
async fn write_complex_4() {
    let mut mock = Builder::new().version((1, 26)).write_number(999).build();
    mock.write_value(&TupleVersionDefaultTest(
        999,
        StructVersionTest {
            test: 89,
            hello: String::from("klomp"),
        },
    ))
    .await
    .unwrap();
}

#[derive(Debug, PartialEq, Eq, NixSerialize)]
#[nix(display)]
struct TestFromStr;

impl fmt::Display for TestFromStr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "test")
    }
}

#[tokio::test]
async fn write_display() {
    let mut mock = Builder::new().write_display("test").build();
    mock.write_value(&TestFromStr).await.unwrap();
}

#[derive(Debug, PartialEq, Eq, NixSerialize)]
#[nix(display = "TestFromStr2::display")]
struct TestFromStr2;
struct TestFromStrDisplay;

impl fmt::Display for TestFromStrDisplay {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "test")
    }
}
impl TestFromStr2 {
    fn display(&self) -> TestFromStrDisplay {
        TestFromStrDisplay
    }
}

#[tokio::test]
async fn write_display_path() {
    let mut mock = Builder::new().write_display("test").build();
    mock.write_value(&TestFromStr2).await.unwrap();
}

#[derive(Clone, Debug, PartialEq, Eq, NixSerialize)]
#[nix(try_into = "u64")]
struct TestTryFromU64(u64);

impl TryFrom<TestTryFromU64> for u64 {
    type Error = u64;

    fn try_from(value: TestTryFromU64) -> Result<Self, Self::Error> {
        if value.0 != 42 {
            Ok(value.0)
        } else {
            Err(value.0)
        }
    }
}

#[tokio::test]
async fn write_try_into_u64() {
    let mut mock = Builder::new().write_number(666).build();
    mock.write_value(&TestTryFromU64(666)).await.unwrap();
}

#[tokio::test]
async fn write_try_into_u64_invalid_data() {
    let mut mock = Builder::new().build();
    let err = mock.write_value(&TestTryFromU64(42)).await.unwrap_err();
    assert_eq!(Error::UnsupportedData("42".into()), err);
}

#[derive(Clone, Debug, PartialEq, Eq, NixSerialize)]
#[nix(into = "u64")]
struct TestFromU64;

impl From<TestFromU64> for u64 {
    fn from(_value: TestFromU64) -> u64 {
        42
    }
}

#[tokio::test]
async fn write_into_u64() {
    let mut mock = Builder::new().write_number(42).build();
    mock.write_value(&TestFromU64).await.unwrap();
}

#[derive(Debug, PartialEq, Eq, NixSerialize)]
enum TestEnum {
    #[nix(version = "..=19")]
    Pre20(TestFromU64, #[nix(version = "10..")] u64),
    #[nix(version = "20..=29")]
    Post20(StructVersionTest),
    #[nix(version = "30..=39")]
    Post30,
    #[nix(version = "40..")]
    Post40 {
        msg: String,
        #[nix(version = "45..")]
        level: u64,
    },
}

#[tokio::test]
async fn write_enum_9() {
    let mut mock = Builder::new().version((1, 9)).write_number(42).build();
    mock.write_value(&TestEnum::Pre20(TestFromU64, 666))
        .await
        .unwrap();
}

#[tokio::test]
async fn write_enum_19() {
    let mut mock = Builder::new()
        .version((1, 19))
        .write_number(42)
        .write_number(666)
        .build();
    mock.write_value(&TestEnum::Pre20(TestFromU64, 666))
        .await
        .unwrap();
}

#[tokio::test]
async fn write_enum_20() {
    let mut mock = Builder::new()
        .version((1, 20))
        .write_number(666)
        .write_slice(b"klomp")
        .build();
    mock.write_value(&TestEnum::Post20(StructVersionTest {
        test: 666,
        hello: "klomp".into(),
    }))
    .await
    .unwrap();
}

#[tokio::test]
async fn write_enum_30() {
    let mut mock = Builder::new().version((1, 30)).build();
    mock.write_value(&TestEnum::Post30).await.unwrap();
}

#[tokio::test]
async fn write_enum_40() {
    let mut mock = Builder::new()
        .version((1, 40))
        .write_slice(b"hello world")
        .build();
    mock.write_value(&TestEnum::Post40 {
        msg: "hello world".into(),
        level: 9001,
    })
    .await
    .unwrap();
}

#[tokio::test]
async fn write_enum_45() {
    let mut mock = Builder::new()
        .version((1, 45))
        .write_slice(b"hello world")
        .write_number(9001)
        .build();
    mock.write_value(&TestEnum::Post40 {
        msg: "hello world".into(),
        level: 9001,
    })
    .await
    .unwrap();
}

#[tokio::test]
async fn write_wrong_enum() {
    let mut mock = Builder::new().version((1, 30)).build();
    let err = mock
        .write_value(&TestEnum::Post40 {
            msg: "hello world".into(),
            level: 9001,
        })
        .await
        .unwrap_err();
    assert_eq!(
        err,
        Error::InvalidEnum("Post40 is not valid for version 1.30".into())
    )
}