+
+// Verifies that Logger::list_recordings() shows an empty listing
+// if there are no recordings.
+#[test]
+fn list_recordings0() {
+ let pipe = Pipe::new();
+
+ let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
+
+ let mut ls_buffer_space = [0u8; 4096];
+ let mut ls_buffer = Buffer::alloc();
+
+ let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
+
+ ls_buffer.init(ls_buffer_space.as_mut_ptr(),
+ ls_buffer_space.len(),
+ flush_write_buffer,
+ user_data);
+
+ let mut fake_storage = FakeStorage::new();
+
+ let mut logger = Logger::new(&mut fake_storage);
+ logger.init();
+
+ logger.list_recordings(&mut ls_buffer);
+
+ let mut file = unsafe { std::fs::File::from_raw_fd(pipe.read_fd()) };
+
+ let mut listing_raw = [0u8; 256];
+
+ // There are no recordings, so there's no data in the pipe either.
+ assert!(file.read(&mut listing_raw).is_err());
+}
+
+// Verifies that Logger::list_recordings() shows a listing
+// of a single recording in the very first sector.
+#[test]
+fn list_recordings1() {
+ let pipe = Pipe::new();
+
+ let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
+
+ let mut ls_buffer_space = [0u8; 4096];
+ let mut ls_buffer = Buffer::alloc();
+
+ let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
+
+ ls_buffer.init(ls_buffer_space.as_mut_ptr(),
+ ls_buffer_space.len(),
+ flush_write_buffer,
+ user_data);
+
+ let mut fake_storage = FakeStorage::new();
+
+ // Mark first sector as in use.
+ let recording0 = [
+ // Header:
+ 0x01, 0x00, 0x01, 0x00,
+ 0xa2, 0xdb, 0x14, 0x5e,
+ ];
+
+ fake_storage.expected[0..recording0.len()].copy_from_slice(&recording0);
+ fake_storage.actual[0..recording0.len()].copy_from_slice(&recording0);
+
+ let mut logger = Logger::new(&mut fake_storage);
+ logger.init();
+
+ logger.list_recordings(&mut ls_buffer);
+
+ let mut file = unsafe { std::fs::File::from_raw_fd(pipe.read_fd()) };
+
+ let mut listing_raw = [0u8; 256];
+ let num_bytes_read = file.read(&mut listing_raw).unwrap();
+
+ let expected_bytes = b"\
+2020-01-07 19:27:30 4K 1\n";
+
+ assert_eq!(String::from_utf8(expected_bytes.to_vec()).unwrap(),
+ String::from_utf8(listing_raw[0..num_bytes_read].to_vec()).unwrap());
+}
+
+// Verifies that Logger::list_recordings() handles sectors holding
+// additional recording data.
+#[test]
+fn list_recording1_multi_sector() {
+ let pipe = Pipe::new();
+
+ let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
+
+ let mut ls_buffer_space = [0u8; 4096];
+ let mut ls_buffer = Buffer::alloc();
+
+ let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
+
+ ls_buffer.init(ls_buffer_space.as_mut_ptr(),
+ ls_buffer_space.len(),
+ flush_write_buffer,
+ user_data);
+
+ let mut fake_storage = FakeStorage::new();
+
+ // The first sector starts recording 1.
+ let header0 = [
+ // Header:
+ 0x01, 0x00, 0x01, 0x00,
+ 0x75, 0x18, 0x17, 0x5e,
+ ];
+
+ // The second sector has additional data for recording 1.
+ let header1 = [
+ 0x03, 0x00, 0x01, 0x00,
+ ];
+
+ fake_storage.actual[0..header0.len()].copy_from_slice(&header0);
+ fake_storage.actual[4096..4096 + header1.len()].copy_from_slice(&header1);
+
+ let mut logger = Logger::new(&mut fake_storage);
+ logger.init();
+
+ logger.list_recordings(&mut ls_buffer);
+
+ let mut file = unsafe { std::fs::File::from_raw_fd(pipe.read_fd()) };
+
+ let mut listing_raw = [0u8; 4096];
+ let num_bytes_read = file.read(&mut listing_raw).unwrap();
+
+ let expected_bytes = b"\
+2020-01-09 12:11:33 8K 1\n";
+
+ assert_eq!(String::from_utf8(expected_bytes.to_vec()).unwrap(),
+ String::from_utf8(listing_raw[0..num_bytes_read].to_vec()).unwrap());
+}
+
+// Verifies that Logger::remove_recording() reports an error if there is no
+// recording with the given ID.
+#[test]
+fn remove_recording0() {
+ let mut fake_storage = FakeStorage::new();
+
+ let mut logger = Logger::new(&mut fake_storage);
+ logger.init();
+
+ let result = logger.remove_recording(42);
+ assert_eq!(LoggerError::NoSuchRecording, result.unwrap_err());
+}
+
+// Verifies that Logger::remove_recording() clears consecutive sectors
+// belonging to the recording identified by the given ID.
+#[test]
+fn remove_recording1() {
+ let mut fake_storage = FakeStorage::new();
+
+ // Mark first sector as in use.
+ let header0 = [
+ 0x01, 0x00, 0x01, 0x00,
+ 0xa2, 0xdb, 0x14, 0x5e,
+ ];
+
+ // Mark second sector as in use by the same recording.
+ let header1 = [
+ 0x03, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ ];
+
+ // Mark third sector as in use by another recording.
+ let header2 = [
+ 0x01, 0x00, 0x02, 0x00,
+ 0xa2, 0xdb, 0x14, 0x5f,
+ ];
+
+ fake_storage.actual[0..header0.len()].copy_from_slice(&header0);
+ fake_storage.actual[4096..4096 + header1.len()].copy_from_slice(&header1);
+ fake_storage.actual[8192..8192 + header2.len()].copy_from_slice(&header2);
+
+ let mut logger = Logger::new(&mut fake_storage);
+ logger.init();
+
+ assert!(logger.remove_recording(1).is_ok());
+
+ let cleared = [
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ ];
+
+ fake_storage.expected[0..cleared.len()].copy_from_slice(&cleared);
+ fake_storage.expected[4096..4096 + header1.len()].copy_from_slice(&cleared);
+ fake_storage.expected[8192..8192 + header2.len()].copy_from_slice(&header2);
+
+ assert_eq!(fake_storage.expected, fake_storage.actual);
+}