Skip to content

Commit 00162d0

Browse files
test: add comprehensive test coverage
Add 45 new tests covering: - HttpRange parsing errors (empty, wrong unit, missing delimiter, unordered, multi-range, plus-prefixed numbers) - HttpRange edge cases (suffix zero, starting point zero, single byte) - Content-Range parsing errors (empty, wrong unit, missing delimiter, star/star, end >= size) - file_range with all HttpRange variants and boundary conditions - serve_file_with_http_range body slicing, empty body, suffix zero
1 parent 9f04e7b commit 00162d0

1 file changed

Lines changed: 345 additions & 1 deletion

File tree

src/headers/tests.rs

Lines changed: 345 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ mod content_range {
157157

158158
#[cfg(test)]
159159
mod range {
160-
use crate::headers::{OrderedRange, range::HttpRange};
160+
use crate::headers::{OrderedRange, ParseHttpRangeOrContentRangeError, range::HttpRange};
161161

162162
#[test]
163163
fn succesful_starting_parsing() {
@@ -200,4 +200,348 @@ mod range {
200200
fn succesful_suffix_to_string() {
201201
assert_eq!("bytes=-100", &HttpRange::Suffix(100).to_string());
202202
}
203+
204+
#[test]
205+
fn empty_input() {
206+
assert_eq!(
207+
"".parse::<HttpRange>().unwrap_err(),
208+
ParseHttpRangeOrContentRangeError::Empty
209+
);
210+
}
211+
212+
#[test]
213+
fn whitespace_only_input() {
214+
assert_eq!(
215+
" ".parse::<HttpRange>().unwrap_err(),
216+
ParseHttpRangeOrContentRangeError::Empty
217+
);
218+
}
219+
220+
#[test]
221+
fn missing_equals() {
222+
assert_eq!(
223+
"bytes50-100".parse::<HttpRange>().unwrap_err(),
224+
ParseHttpRangeOrContentRangeError::Malformed
225+
);
226+
}
227+
228+
#[test]
229+
fn wrong_unit() {
230+
assert_eq!(
231+
"items=0-10".parse::<HttpRange>().unwrap_err(),
232+
ParseHttpRangeOrContentRangeError::InvalidUnit
233+
);
234+
}
235+
236+
#[test]
237+
fn both_empty() {
238+
assert_eq!(
239+
"bytes=-".parse::<HttpRange>().unwrap_err(),
240+
ParseHttpRangeOrContentRangeError::Malformed
241+
);
242+
}
243+
244+
#[test]
245+
fn unordered_range() {
246+
assert!("bytes=100-50".parse::<HttpRange>().is_err());
247+
}
248+
249+
#[test]
250+
fn plus_prefix_rejected_in_starting_point() {
251+
assert!("bytes=+50-".parse::<HttpRange>().is_err());
252+
}
253+
254+
#[test]
255+
fn plus_prefix_rejected_in_suffix() {
256+
assert!("bytes=-+100".parse::<HttpRange>().is_err());
257+
}
258+
259+
#[test]
260+
fn plus_prefix_rejected_in_range() {
261+
assert!("bytes=+50-100".parse::<HttpRange>().is_err());
262+
assert!("bytes=50-+100".parse::<HttpRange>().is_err());
263+
}
264+
265+
#[test]
266+
fn multi_range_rejected() {
267+
assert!("bytes=0-50, 100-150".parse::<HttpRange>().is_err());
268+
}
269+
270+
#[test]
271+
fn suffix_zero_parsing() {
272+
assert_eq!(
273+
"bytes=-0".parse::<HttpRange>().unwrap(),
274+
HttpRange::Suffix(0)
275+
);
276+
}
277+
278+
#[test]
279+
fn starting_point_zero() {
280+
assert_eq!(
281+
"bytes=0-".parse::<HttpRange>().unwrap(),
282+
HttpRange::StartingPoint(0)
283+
);
284+
}
285+
286+
#[test]
287+
fn range_single_byte() {
288+
assert_eq!(
289+
"bytes=0-0".parse::<HttpRange>().unwrap(),
290+
HttpRange::Range(OrderedRange::new(0..=0).unwrap())
291+
);
292+
}
293+
}
294+
295+
#[cfg(test)]
296+
mod content_range_parsing_errors {
297+
use crate::headers::{ParseHttpRangeOrContentRangeError, content_range::HttpContentRange};
298+
299+
#[test]
300+
fn empty_input() {
301+
assert_eq!(
302+
"".parse::<HttpContentRange>().unwrap_err(),
303+
ParseHttpRangeOrContentRangeError::Empty
304+
);
305+
}
306+
307+
#[test]
308+
fn missing_space() {
309+
assert_eq!(
310+
"bytes10-20/50".parse::<HttpContentRange>().unwrap_err(),
311+
ParseHttpRangeOrContentRangeError::Malformed
312+
);
313+
}
314+
315+
#[test]
316+
fn wrong_unit() {
317+
assert_eq!(
318+
"items 10-20/50".parse::<HttpContentRange>().unwrap_err(),
319+
ParseHttpRangeOrContentRangeError::InvalidUnit
320+
);
321+
}
322+
323+
#[test]
324+
fn missing_slash() {
325+
assert_eq!(
326+
"bytes 10-20".parse::<HttpContentRange>().unwrap_err(),
327+
ParseHttpRangeOrContentRangeError::Malformed
328+
);
329+
}
330+
331+
#[test]
332+
fn star_star() {
333+
assert_eq!(
334+
"bytes */*".parse::<HttpContentRange>().unwrap_err(),
335+
ParseHttpRangeOrContentRangeError::Malformed
336+
);
337+
}
338+
339+
#[test]
340+
fn end_exceeds_size() {
341+
assert_eq!(
342+
"bytes 10-20/15".parse::<HttpContentRange>().unwrap_err(),
343+
ParseHttpRangeOrContentRangeError::MalformedRange
344+
);
345+
}
346+
347+
#[test]
348+
fn end_equals_size() {
349+
assert_eq!(
350+
"bytes 0-20/20".parse::<HttpContentRange>().unwrap_err(),
351+
ParseHttpRangeOrContentRangeError::MalformedRange
352+
);
353+
}
354+
355+
#[test]
356+
fn end_at_boundary() {
357+
assert!("bytes 0-19/20".parse::<HttpContentRange>().is_ok());
358+
}
359+
}
360+
361+
#[cfg(test)]
362+
mod file_range {
363+
use std::num::NonZeroU64;
364+
365+
use crate::{
366+
file_range,
367+
headers::{
368+
OrderedRange,
369+
content_range::{Bound, HttpContentRange},
370+
range::HttpRange,
371+
},
372+
};
373+
374+
fn size(n: u64) -> NonZeroU64 {
375+
NonZeroU64::new(n).unwrap()
376+
}
377+
378+
#[test]
379+
fn no_range_returns_full_file() {
380+
let result = file_range(size(10), None).unwrap();
381+
assert!(result.header().is_none());
382+
assert_eq!(result.range(), &(0..=9));
383+
}
384+
385+
#[test]
386+
fn starting_point_zero() {
387+
let result = file_range(size(10), Some(HttpRange::StartingPoint(0))).unwrap();
388+
assert!(result.header().is_some());
389+
assert_eq!(result.range(), &(0..=9));
390+
}
391+
392+
#[test]
393+
fn starting_point_middle() {
394+
let result = file_range(size(10), Some(HttpRange::StartingPoint(5))).unwrap();
395+
assert_eq!(result.range(), &(5..=9));
396+
}
397+
398+
#[test]
399+
fn starting_point_last_byte() {
400+
let result = file_range(size(10), Some(HttpRange::StartingPoint(9))).unwrap();
401+
assert_eq!(result.range(), &(9..=9));
402+
}
403+
404+
#[test]
405+
fn starting_point_at_size() {
406+
let result = file_range(size(10), Some(HttpRange::StartingPoint(10)));
407+
assert!(result.is_err());
408+
}
409+
410+
#[test]
411+
fn starting_point_beyond_size() {
412+
let result = file_range(size(10), Some(HttpRange::StartingPoint(20)));
413+
assert!(result.is_err());
414+
}
415+
416+
#[test]
417+
fn range_single_byte() {
418+
let range = HttpRange::Range(OrderedRange::new(0..=0).unwrap());
419+
let result = file_range(size(10), Some(range)).unwrap();
420+
assert_eq!(result.range(), &(0..=0));
421+
}
422+
423+
#[test]
424+
fn range_full_file() {
425+
let range = HttpRange::Range(OrderedRange::new(0..=9).unwrap());
426+
let result = file_range(size(10), Some(range)).unwrap();
427+
assert_eq!(result.range(), &(0..=9));
428+
}
429+
430+
#[test]
431+
fn range_end_at_size() {
432+
let range = HttpRange::Range(OrderedRange::new(0..=10).unwrap());
433+
let result = file_range(size(10), Some(range));
434+
assert!(result.is_err());
435+
}
436+
437+
#[test]
438+
fn range_beyond_size() {
439+
let range = HttpRange::Range(OrderedRange::new(0..=50).unwrap());
440+
let result = file_range(size(10), Some(range));
441+
assert!(result.is_err());
442+
}
443+
444+
#[test]
445+
fn suffix_entire_file() {
446+
let result = file_range(size(10), Some(HttpRange::Suffix(10))).unwrap();
447+
assert_eq!(result.range(), &(0..=9));
448+
}
449+
450+
#[test]
451+
fn suffix_last_byte() {
452+
let result = file_range(size(10), Some(HttpRange::Suffix(1))).unwrap();
453+
assert_eq!(result.range(), &(9..=9));
454+
}
455+
456+
#[test]
457+
fn suffix_middle() {
458+
let result = file_range(size(10), Some(HttpRange::Suffix(5))).unwrap();
459+
assert_eq!(result.range(), &(5..=9));
460+
}
461+
462+
#[test]
463+
fn suffix_zero_is_unsatisfiable() {
464+
let result = file_range(size(10), Some(HttpRange::Suffix(0)));
465+
assert!(result.is_err());
466+
}
467+
468+
#[test]
469+
fn suffix_exceeds_size() {
470+
let result = file_range(size(10), Some(HttpRange::Suffix(11)));
471+
assert!(result.is_err());
472+
}
473+
474+
#[test]
475+
fn size_one_no_range() {
476+
let result = file_range(size(1), None).unwrap();
477+
assert_eq!(result.range(), &(0..=0));
478+
}
479+
480+
#[test]
481+
fn size_one_starting_point_zero() {
482+
let result = file_range(size(1), Some(HttpRange::StartingPoint(0))).unwrap();
483+
assert_eq!(result.range(), &(0..=0));
484+
}
485+
486+
#[test]
487+
fn size_one_suffix_one() {
488+
let result = file_range(size(1), Some(HttpRange::Suffix(1))).unwrap();
489+
assert_eq!(result.range(), &(0..=0));
490+
}
491+
492+
#[test]
493+
fn content_range_header_present_for_range_request() {
494+
let result = file_range(size(10), Some(HttpRange::StartingPoint(0))).unwrap();
495+
let header = result.header().unwrap();
496+
assert_eq!(
497+
header,
498+
HttpContentRange::Bound(Bound::new(0..=9, Some(10)).unwrap())
499+
);
500+
}
501+
}
502+
503+
#[cfg(test)]
504+
mod serve_file {
505+
use bytes::Bytes;
506+
507+
use crate::{headers::range::HttpRange, serve_file_with_http_range};
508+
509+
#[test]
510+
fn no_range_returns_full_body() {
511+
let body = Bytes::from_static(b"hello world");
512+
let result = serve_file_with_http_range(body.clone(), None).unwrap();
513+
assert_eq!(result.body(), &body);
514+
assert!(result.header().is_none());
515+
}
516+
517+
#[test]
518+
fn range_slices_body() {
519+
let body = Bytes::from_static(b"hello world");
520+
let range = Some(HttpRange::StartingPoint(6));
521+
let result = serve_file_with_http_range(body, range).unwrap();
522+
assert_eq!(result.body(), &Bytes::from_static(b"world"));
523+
assert!(result.header().is_some());
524+
}
525+
526+
#[test]
527+
fn suffix_slices_from_end() {
528+
let body = Bytes::from_static(b"hello world");
529+
let range = Some(HttpRange::Suffix(5));
530+
let result = serve_file_with_http_range(body, range).unwrap();
531+
assert_eq!(result.body(), &Bytes::from_static(b"world"));
532+
}
533+
534+
#[test]
535+
fn empty_body_is_unsatisfiable() {
536+
let body = Bytes::new();
537+
let result = serve_file_with_http_range(body, None);
538+
assert!(result.is_err());
539+
}
540+
541+
#[test]
542+
fn suffix_zero_is_unsatisfiable() {
543+
let body = Bytes::from_static(b"hello");
544+
let result = serve_file_with_http_range(body, Some(HttpRange::Suffix(0)));
545+
assert!(result.is_err());
546+
}
203547
}

0 commit comments

Comments
 (0)