#![cfg(feature = "serde")] use std::num::{NonZeroI32, NonZeroI64}; use snapbox::{assert_data_eq, file}; use watchexec_events::{ filekind::{CreateKind, FileEventKind as EventKind, ModifyKind, RemoveKind, RenameMode}, Event, FileType, Keyboard, ProcessEnd, Source, Tag, }; use watchexec_signals::Signal; fn parse_file(path: &str) -> Vec { serde_json::from_str(&std::fs::read_to_string(path).unwrap()).unwrap() } #[test] fn single() { let single = Event { tags: vec![Tag::Source(Source::Internal)], metadata: Default::default(), }; assert_data_eq!( serde_json::to_string_pretty(&single).unwrap(), file!["snapshots/single.json"], ); assert_eq!( serde_json::from_str::( &std::fs::read_to_string("tests/snapshots/single.json").unwrap() ) .unwrap(), single ); } #[test] fn array() { let array = &[ Event { tags: vec![Tag::Source(Source::Internal)], metadata: Default::default(), }, Event { tags: vec![ Tag::ProcessCompletion(Some(ProcessEnd::Success)), Tag::Process(123), ], metadata: Default::default(), }, Event { tags: vec![Tag::Keyboard(Keyboard::Eof)], metadata: Default::default(), }, ]; assert_data_eq!( serde_json::to_string_pretty(array).unwrap(), file!["snapshots/array.json"], ); assert_eq!(parse_file("tests/snapshots/array.json"), array); } #[test] fn metadata() { let metadata = &[Event { tags: vec![Tag::Source(Source::Internal)], metadata: [ ("Dafan".into(), vec!["Mountain".into()]), ("Lan".into(), vec!["Zhan".into()]), ] .into(), }]; assert_data_eq!( serde_json::to_string_pretty(metadata).unwrap(), file!["snapshots/metadata.json"], ); assert_eq!(parse_file("tests/snapshots/metadata.json"), metadata); } #[test] fn asymmetric() { // asymmetric because these have information loss or missing fields assert_eq!( parse_file("tests/snapshots/asymmetric.json"), &[ Event { tags: vec![ // no filetype field Tag::Path { path: "/foo/bar/baz".into(), file_type: None }, // fs with only simple representation Tag::FileEventKind(EventKind::Create(CreateKind::Any)), // unparsable of a known kind Tag::Unknown, ], metadata: Default::default(), }, Event { tags: vec![ // no simple field Tag::FileEventKind(EventKind::Modify(ModifyKind::Other)), // no disposition field Tag::ProcessCompletion(None) ], metadata: Default::default(), }, ] ); } #[test] fn sources() { let sources = vec![ Event { tags: vec![ Tag::Source(Source::Filesystem), Tag::Source(Source::Keyboard), Tag::Source(Source::Mouse), ], metadata: Default::default(), }, Event { tags: vec![ Tag::Source(Source::Os), Tag::Source(Source::Time), Tag::Source(Source::Internal), ], metadata: Default::default(), }, ]; assert_data_eq!( serde_json::to_string_pretty(&sources).unwrap(), file!["snapshots/sources.json"], ); assert_eq!(parse_file("tests/snapshots/sources.json"), sources); } #[test] fn signals() { let signals = vec![ Event { tags: vec![ Tag::Signal(Signal::Interrupt), Tag::Signal(Signal::User1), Tag::Signal(Signal::ForceStop), ], metadata: Default::default(), }, Event { tags: vec![ Tag::Signal(Signal::Custom(66)), Tag::Signal(Signal::Custom(0)), ], metadata: Default::default(), }, ]; assert_data_eq!( serde_json::to_string_pretty(&signals).unwrap(), file!["snapshots/signals.json"], ); assert_eq!(parse_file("tests/snapshots/signals.json"), signals); } #[test] fn completions() { let completions = vec![ Event { tags: vec![ Tag::ProcessCompletion(None), Tag::ProcessCompletion(Some(ProcessEnd::Success)), Tag::ProcessCompletion(Some(ProcessEnd::Continued)), ], metadata: Default::default(), }, Event { tags: vec![ Tag::ProcessCompletion(Some(ProcessEnd::ExitError(NonZeroI64::new(12).unwrap()))), Tag::ProcessCompletion(Some(ProcessEnd::ExitSignal(Signal::Interrupt))), Tag::ProcessCompletion(Some(ProcessEnd::ExitSignal(Signal::Custom(34)))), Tag::ProcessCompletion(Some(ProcessEnd::ExitStop(NonZeroI32::new(56).unwrap()))), Tag::ProcessCompletion(Some(ProcessEnd::Exception(NonZeroI32::new(78).unwrap()))), ], metadata: Default::default(), }, ]; assert_data_eq!( serde_json::to_string_pretty(&completions).unwrap(), file!["snapshots/completions.json"], ); assert_eq!(parse_file("tests/snapshots/completions.json"), completions); } #[test] fn paths() { let paths = vec![ Event { tags: vec![ Tag::Path { path: "/foo/bar/baz".into(), file_type: Some(FileType::Symlink), }, Tag::FileEventKind(EventKind::Create(CreateKind::File)), ], metadata: Default::default(), }, Event { tags: vec![ Tag::Path { path: "/rename/from/this".into(), file_type: Some(FileType::File), }, Tag::Path { path: "/rename/into/that".into(), file_type: Some(FileType::Other), }, Tag::FileEventKind(EventKind::Modify(ModifyKind::Name(RenameMode::Both))), ], metadata: Default::default(), }, Event { tags: vec![ Tag::Path { path: "/delete/this".into(), file_type: Some(FileType::Dir), }, Tag::Path { path: "/".into(), file_type: None, }, Tag::FileEventKind(EventKind::Remove(RemoveKind::Any)), ], metadata: Default::default(), }, ]; assert_data_eq!( serde_json::to_string_pretty(&paths).unwrap(), file!["snapshots/paths.json"], ); assert_eq!(parse_file("tests/snapshots/paths.json"), paths); }