1#[derive(Debug, thiserror::Error)]
19pub enum PipelineError {
20 #[error("decode failed: {0}")]
25 Decode(#[from] ff_decode::DecodeError),
26
27 #[error("filter failed: {0}")]
32 Filter(#[from] ff_filter::FilterError),
33
34 #[error("encode failed: {0}")]
39 Encode(#[from] ff_encode::EncodeError),
40
41 #[error("no input specified")]
46 NoInput,
47
48 #[error("no output specified")]
53 NoOutput,
54
55 #[error("secondary input provided without a filter graph")]
60 SecondaryInputWithoutFilter,
61
62 #[error("pipeline cancelled by caller")]
67 Cancelled,
68
69 #[error("i/o error: {0}")]
71 Io(#[from] std::io::Error),
72
73 #[error("no frame available at the requested position")]
79 FrameNotAvailable,
80}
81
82#[cfg(test)]
83mod tests {
84 use std::error::Error;
85
86 use super::PipelineError;
87
88 #[test]
91 fn no_input_should_display_correct_message() {
92 let err = PipelineError::NoInput;
93 assert_eq!(err.to_string(), "no input specified");
94 }
95
96 #[test]
97 fn no_output_should_display_correct_message() {
98 let err = PipelineError::NoOutput;
99 assert_eq!(err.to_string(), "no output specified");
100 }
101
102 #[test]
103 fn cancelled_should_display_correct_message() {
104 let err = PipelineError::Cancelled;
105 assert_eq!(err.to_string(), "pipeline cancelled by caller");
106 }
107
108 #[test]
111 fn decode_should_prefix_inner_message() {
112 let err = PipelineError::Decode(ff_decode::DecodeError::decoding_failed("test error"));
113 assert!(err.to_string().starts_with("decode failed:"));
114 }
115
116 #[test]
117 fn filter_should_prefix_inner_message() {
118 let err = PipelineError::Filter(ff_filter::FilterError::BuildFailed);
119 assert_eq!(
120 err.to_string(),
121 "filter failed: failed to build filter graph"
122 );
123 }
124
125 #[test]
126 fn encode_should_prefix_inner_message() {
127 let err = PipelineError::Encode(ff_encode::EncodeError::Cancelled);
128 assert_eq!(err.to_string(), "encode failed: Encoding cancelled by user");
129 }
130
131 #[test]
134 fn decode_error_should_convert_into_pipeline_error() {
135 let inner = ff_decode::DecodeError::decoding_failed("test error");
136 let err: PipelineError = inner.into();
137 assert!(matches!(err, PipelineError::Decode(_)));
138 }
139
140 #[test]
141 fn filter_error_should_convert_into_pipeline_error() {
142 let inner = ff_filter::FilterError::BuildFailed;
143 let err: PipelineError = inner.into();
144 assert!(matches!(err, PipelineError::Filter(_)));
145 }
146
147 #[test]
148 fn encode_error_should_convert_into_pipeline_error() {
149 let inner = ff_encode::EncodeError::Cancelled;
150 let err: PipelineError = inner.into();
151 assert!(matches!(err, PipelineError::Encode(_)));
152 }
153
154 #[test]
157 fn decode_should_expose_source() {
158 let err = PipelineError::Decode(ff_decode::DecodeError::decoding_failed("test error"));
159 assert!(err.source().is_some());
160 }
161
162 #[test]
163 fn filter_should_expose_source() {
164 let err = PipelineError::Filter(ff_filter::FilterError::BuildFailed);
165 assert!(err.source().is_some());
166 }
167
168 #[test]
169 fn encode_should_expose_source() {
170 let err = PipelineError::Encode(ff_encode::EncodeError::Cancelled);
171 assert!(err.source().is_some());
172 }
173
174 #[test]
175 fn unit_variants_should_have_no_source() {
176 assert!(PipelineError::NoInput.source().is_none());
177 assert!(PipelineError::NoOutput.source().is_none());
178 assert!(PipelineError::Cancelled.source().is_none());
179 }
180
181 #[test]
184 fn io_error_should_convert_into_pipeline_error() {
185 let inner = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
186 let err: PipelineError = inner.into();
187 assert!(matches!(err, PipelineError::Io(_)));
188 }
189
190 #[test]
191 fn io_error_should_display_correct_message() {
192 let inner = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "access denied");
193 let err: PipelineError = inner.into();
194 assert_eq!(err.to_string(), "i/o error: access denied");
195 }
196
197 #[test]
198 fn io_error_should_expose_source() {
199 let inner = std::io::Error::new(std::io::ErrorKind::Other, "some error");
200 let err: PipelineError = inner.into();
201 assert!(err.source().is_some());
202 }
203}