|  | #![deny(rust_2018_idioms)] | 
|  |  | 
|  | use std::io::{Read, Seek, SeekFrom, Write}; | 
|  |  | 
|  | use tempfile::{spooled_tempfile, SpooledTempFile}; | 
|  |  | 
|  | #[test] | 
|  | fn test_automatic_rollover() { | 
|  | let mut t = spooled_tempfile(10); | 
|  | let mut buf = Vec::new(); | 
|  |  | 
|  | assert!(!t.is_rolled()); | 
|  | assert_eq!(t.stream_position().unwrap(), 0); | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 0); | 
|  | assert_eq!(buf.as_slice(), b""); | 
|  | buf.clear(); | 
|  |  | 
|  | assert_eq!(t.write(b"abcde").unwrap(), 5); | 
|  |  | 
|  | assert!(!t.is_rolled()); | 
|  | assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0); | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 5); | 
|  | assert_eq!(buf.as_slice(), b"abcde"); | 
|  |  | 
|  | assert_eq!(t.write(b"fghijklmno").unwrap(), 10); | 
|  |  | 
|  | assert_eq!(t.stream_position().unwrap(), 15); | 
|  | assert!(t.is_rolled()); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_explicit_rollover() { | 
|  | let mut t = SpooledTempFile::new(100); | 
|  | assert_eq!(t.write(b"abcdefghijklmnopqrstuvwxyz").unwrap(), 26); | 
|  | assert_eq!(t.stream_position().unwrap(), 26); | 
|  | assert!(!t.is_rolled()); | 
|  |  | 
|  | // roll over explicitly | 
|  | assert!(t.roll().is_ok()); | 
|  | assert!(t.is_rolled()); | 
|  | assert_eq!(t.stream_position().unwrap(), 26); | 
|  |  | 
|  | let mut buf = Vec::new(); | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 0); | 
|  | assert_eq!(buf.as_slice(), b""); | 
|  | buf.clear(); | 
|  |  | 
|  | assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0); | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 26); | 
|  | assert_eq!(buf.as_slice(), b"abcdefghijklmnopqrstuvwxyz"); | 
|  | assert_eq!(t.stream_position().unwrap(), 26); | 
|  | } | 
|  |  | 
|  | // called by test_seek_{buffer, file} | 
|  | // assumes t is empty and offset is 0 to start | 
|  | fn test_seek(t: &mut SpooledTempFile) { | 
|  | assert_eq!(t.write(b"abcdefghijklmnopqrstuvwxyz").unwrap(), 26); | 
|  |  | 
|  | assert_eq!(t.stream_position().unwrap(), 26); // tell() | 
|  | assert_eq!(t.seek(SeekFrom::Current(-1)).unwrap(), 25); | 
|  | assert_eq!(t.seek(SeekFrom::Current(1)).unwrap(), 26); | 
|  | assert_eq!(t.seek(SeekFrom::Current(1)).unwrap(), 27); | 
|  | assert_eq!(t.seek(SeekFrom::Current(-27)).unwrap(), 0); | 
|  | assert!(t.seek(SeekFrom::Current(-1)).is_err()); | 
|  | assert!(t.seek(SeekFrom::Current(-1245)).is_err()); | 
|  |  | 
|  | assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0); | 
|  | assert_eq!(t.seek(SeekFrom::Start(1)).unwrap(), 1); | 
|  | assert_eq!(t.seek(SeekFrom::Start(26)).unwrap(), 26); | 
|  | assert_eq!(t.seek(SeekFrom::Start(27)).unwrap(), 27); | 
|  | // // these are build errors | 
|  | // assert!(t.seek(SeekFrom::Start(-1)).is_err()); | 
|  | // assert!(t.seek(SeekFrom::Start(-1000)).is_err()); | 
|  |  | 
|  | assert_eq!(t.seek(SeekFrom::End(0)).unwrap(), 26); | 
|  | assert_eq!(t.seek(SeekFrom::End(-1)).unwrap(), 25); | 
|  | assert_eq!(t.seek(SeekFrom::End(-26)).unwrap(), 0); | 
|  | assert!(t.seek(SeekFrom::End(-27)).is_err()); | 
|  | assert!(t.seek(SeekFrom::End(-99)).is_err()); | 
|  | assert_eq!(t.seek(SeekFrom::End(1)).unwrap(), 27); | 
|  | assert_eq!(t.seek(SeekFrom::End(1)).unwrap(), 27); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_seek_buffer() { | 
|  | let mut t = spooled_tempfile(100); | 
|  | test_seek(&mut t); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_seek_file() { | 
|  | let mut t = SpooledTempFile::new(10); | 
|  | test_seek(&mut t); | 
|  | } | 
|  |  | 
|  | fn test_seek_read(t: &mut SpooledTempFile) { | 
|  | assert_eq!(t.write(b"abcdefghijklmnopqrstuvwxyz").unwrap(), 26); | 
|  |  | 
|  | let mut buf = Vec::new(); | 
|  |  | 
|  | // we're at the end | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 0); | 
|  | assert_eq!(buf.as_slice(), b""); | 
|  | buf.clear(); | 
|  |  | 
|  | // seek to start, read whole thing | 
|  | assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0); | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 26); | 
|  | assert_eq!(buf.as_slice(), b"abcdefghijklmnopqrstuvwxyz"); | 
|  | buf.clear(); | 
|  |  | 
|  | // now we're at the end again | 
|  | assert_eq!(t.stream_position().unwrap(), 26); // tell() | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 0); | 
|  | assert_eq!(buf.as_slice(), b""); | 
|  | buf.clear(); | 
|  |  | 
|  | // seek to somewhere in the middle, read a bit | 
|  | assert_eq!(t.seek(SeekFrom::Start(5)).unwrap(), 5); | 
|  | let mut buf = [0; 5]; | 
|  | assert!(t.read_exact(&mut buf).is_ok()); | 
|  | assert_eq!(buf, *b"fghij"); | 
|  |  | 
|  | // read again from current spot | 
|  | assert_eq!(t.stream_position().unwrap(), 10); // tell() | 
|  | assert!(t.read_exact(&mut buf).is_ok()); | 
|  | assert_eq!(buf, *b"klmno"); | 
|  |  | 
|  | let mut buf = [0; 15]; | 
|  | // partial read | 
|  | assert_eq!(t.read(&mut buf).unwrap(), 11); | 
|  | assert_eq!(buf[0..11], *b"pqrstuvwxyz"); | 
|  |  | 
|  | // try to read off the end: UnexpectedEof | 
|  | assert!(t.read_exact(&mut buf).is_err()); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_seek_read_buffer() { | 
|  | let mut t = spooled_tempfile(100); | 
|  | test_seek_read(&mut t); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_seek_read_file() { | 
|  | let mut t = SpooledTempFile::new(10); | 
|  | test_seek_read(&mut t); | 
|  | } | 
|  |  | 
|  | fn test_overwrite_middle(t: &mut SpooledTempFile) { | 
|  | assert_eq!(t.write(b"abcdefghijklmnopqrstuvwxyz").unwrap(), 26); | 
|  |  | 
|  | assert_eq!(t.seek(SeekFrom::Start(10)).unwrap(), 10); | 
|  | assert_eq!(t.write(b"0123456789").unwrap(), 10); | 
|  | assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0); | 
|  |  | 
|  | let mut buf = Vec::new(); | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 26); | 
|  | assert_eq!(buf.as_slice(), b"abcdefghij0123456789uvwxyz"); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_overwrite_middle_of_buffer() { | 
|  | let mut t = spooled_tempfile(100); | 
|  | test_overwrite_middle(&mut t); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_overwrite_middle_of_file() { | 
|  | let mut t = SpooledTempFile::new(10); | 
|  | test_overwrite_middle(&mut t); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_overwrite_and_extend_buffer() { | 
|  | let mut t = spooled_tempfile(100); | 
|  | assert_eq!(t.write(b"abcdefghijklmnopqrstuvwxyz").unwrap(), 26); | 
|  | assert_eq!(t.seek(SeekFrom::End(-5)).unwrap(), 21); | 
|  | assert_eq!(t.write(b"0123456789").unwrap(), 10); | 
|  | assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0); | 
|  | let mut buf = Vec::new(); | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 31); | 
|  | assert_eq!(buf.as_slice(), b"abcdefghijklmnopqrstu0123456789"); | 
|  | assert!(!t.is_rolled()); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_overwrite_and_extend_rollover() { | 
|  | let mut t = SpooledTempFile::new(20); | 
|  | assert_eq!(t.write(b"abcdefghijklmno").unwrap(), 15); | 
|  | assert!(!t.is_rolled()); | 
|  | assert_eq!(t.seek(SeekFrom::End(-5)).unwrap(), 10); | 
|  | assert_eq!(t.stream_position().unwrap(), 10); // tell() | 
|  | assert!(!t.is_rolled()); | 
|  | assert_eq!(t.write(b"0123456789)!@#$%^&*(").unwrap(), 20); | 
|  | assert!(t.is_rolled()); | 
|  | assert_eq!(t.stream_position().unwrap(), 30); // tell() | 
|  | let mut buf = Vec::new(); | 
|  | assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0); | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 30); | 
|  | assert_eq!(buf.as_slice(), b"abcdefghij0123456789)!@#$%^&*("); | 
|  | } | 
|  |  | 
|  | fn test_sparse(t: &mut SpooledTempFile) { | 
|  | assert_eq!(t.write(b"abcde").unwrap(), 5); | 
|  | assert_eq!(t.seek(SeekFrom::Current(5)).unwrap(), 10); | 
|  | assert_eq!(t.write(b"klmno").unwrap(), 5); | 
|  | assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0); | 
|  | let mut buf = Vec::new(); | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 15); | 
|  | assert_eq!(buf.as_slice(), b"abcde\0\0\0\0\0klmno"); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_sparse_buffer() { | 
|  | let mut t = spooled_tempfile(100); | 
|  | test_sparse(&mut t); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_sparse_file() { | 
|  | let mut t = SpooledTempFile::new(1); | 
|  | test_sparse(&mut t); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_sparse_write_rollover() { | 
|  | let mut t = spooled_tempfile(10); | 
|  | assert_eq!(t.write(b"abcde").unwrap(), 5); | 
|  | assert!(!t.is_rolled()); | 
|  | assert_eq!(t.seek(SeekFrom::Current(5)).unwrap(), 10); | 
|  | assert!(!t.is_rolled()); | 
|  | assert_eq!(t.write(b"klmno").unwrap(), 5); | 
|  | assert!(t.is_rolled()); | 
|  | assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0); | 
|  | let mut buf = Vec::new(); | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 15); | 
|  | assert_eq!(buf.as_slice(), b"abcde\0\0\0\0\0klmno"); | 
|  | } | 
|  |  | 
|  | fn test_set_len(t: &mut SpooledTempFile) { | 
|  | let mut buf: Vec<u8> = Vec::new(); | 
|  |  | 
|  | assert_eq!(t.write(b"abcdefghijklmnopqrstuvwxyz").unwrap(), 26); | 
|  |  | 
|  | // truncate to 10 bytes | 
|  | assert!(t.set_len(10).is_ok()); | 
|  |  | 
|  | // position should not have moved | 
|  | assert_eq!(t.stream_position().unwrap(), 26); // tell() | 
|  |  | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 0); | 
|  | assert_eq!(buf.as_slice(), b""); | 
|  | assert_eq!(t.stream_position().unwrap(), 26); // tell() | 
|  | buf.clear(); | 
|  |  | 
|  | // read whole thing | 
|  | assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0); | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 10); | 
|  | assert_eq!(buf.as_slice(), b"abcdefghij"); | 
|  | buf.clear(); | 
|  |  | 
|  | // set_len to expand beyond the end | 
|  | assert!(t.set_len(40).is_ok()); | 
|  | assert_eq!(t.stream_position().unwrap(), 10); // tell() | 
|  | assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0); | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 40); | 
|  | assert_eq!( | 
|  | buf.as_slice(), | 
|  | &b"abcdefghij\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"[..] | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_set_len_buffer() { | 
|  | let mut t = spooled_tempfile(100); | 
|  | test_set_len(&mut t); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_set_len_file() { | 
|  | let mut t = spooled_tempfile(100); | 
|  | test_set_len(&mut t); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_set_len_rollover() { | 
|  | let mut buf: Vec<u8> = Vec::new(); | 
|  |  | 
|  | let mut t = spooled_tempfile(10); | 
|  | assert_eq!(t.write(b"abcde").unwrap(), 5); | 
|  | assert!(!t.is_rolled()); | 
|  | assert_eq!(t.stream_position().unwrap(), 5); // tell() | 
|  |  | 
|  | assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0); | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 5); | 
|  | assert_eq!(buf.as_slice(), b"abcde"); | 
|  | assert_eq!(t.stream_position().unwrap(), 5); // tell() | 
|  | buf.clear(); | 
|  |  | 
|  | assert!(t.set_len(20).is_ok()); | 
|  | assert!(t.is_rolled()); | 
|  | assert_eq!(t.stream_position().unwrap(), 5); // tell() | 
|  | assert_eq!(t.seek(SeekFrom::Start(0)).unwrap(), 0); | 
|  | assert_eq!(t.read_to_end(&mut buf).unwrap(), 20); | 
|  | assert_eq!(buf.as_slice(), b"abcde\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_write_overflow() { | 
|  | let mut t = spooled_tempfile(10); | 
|  | t.seek(SeekFrom::Start(u64::MAX)).unwrap(); | 
|  | assert!(t.write(b"abcde").is_err()); | 
|  | } | 
|  |  | 
|  | #[cfg(target_pointer_width = "32")] | 
|  | #[test] | 
|  | fn test_set_len_truncation() { | 
|  | let mut t = spooled_tempfile(100); | 
|  | assert!(t.set_len(usize::MAX as u64 + 5).is_ok()); | 
|  | assert!(t.is_rolled()); | 
|  | } |