2 * Copyright (c) 2020 Tilman Sauerbeck (tilman at code-monkey de)
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 use std::io::{Read, Write};
25 use std::os::unix::io::FromRawFd;
26 use common::buffer::{Buffer, BufferUserData};
28 use common::storage::{Storage, Error};
29 use common::logger::{MEMORY_SIZE, Logger, Error as LoggerError};
37 fn new() -> FakeStorage {
39 expected: vec![0xff; MEMORY_SIZE].into_boxed_slice(),
40 actual: vec![0xff; MEMORY_SIZE].into_boxed_slice(),
45 impl Storage for FakeStorage {
46 fn size(&self) -> usize {
50 fn read(&self, address: usize, buffer: &mut [u8]) {
51 for i in 0..buffer.len() {
52 buffer[i] = self.actual[address + i];
56 fn write(&mut self, address: usize, buffer: &[u8; 4096]) -> Result<(), Error> {
57 if (address & 4095) != 0 {
58 return Err(Error::UnalignedAddress);
61 for i in 0..buffer.len() {
62 self.actual[address + i] = buffer[i];
69 self.actual = vec![0xff; MEMORY_SIZE].into_boxed_slice();
79 let mut pipe_fd = [-1i32; 2];
83 fn pipe2(pipefd: *mut i32, flags: i32) -> i32;
86 const O_NONBLOCK : i32 = 0x800;
88 pipe2(pipe_fd.as_mut_ptr(), O_NONBLOCK);
96 fn read_fd(&self) -> i32 {
100 fn write_fd(&self) -> i32 {
105 // Runs a couple of recordings on fully erased flash memory.
107 fn first_recording() {
108 let mut fake_storage = FakeStorage::new();
110 let mut logger = Logger::new(&mut fake_storage);
113 let tap = gps::TimeAndPos {
115 unix_time: 1478026311,
120 let recording_id = logger.start_recording(&tap);
121 assert_eq!(1, recording_id);
123 let sectors_written = logger.stop_recording(&tap);
124 assert_eq!(1, sectors_written);
128 0x01, 0x00, 0x01, 0x00,
129 0x47, 0xe4, 0x18, 0x58,
134 0x9c, 0x8d, 0x99, 0x07,
135 0x9e, 0x8d, 0x99, 0x07,
138 0xff, 0xff, 0xff, 0xff, 0x0f,
145 let end = start + expected.len();
146 fake_storage.expected[start..end].copy_from_slice(&expected);
148 assert_eq!(fake_storage.expected, fake_storage.actual);
152 fn second_recording() {
153 let mut fake_storage = FakeStorage::new();
155 // Mark first sector as in use.
158 0x01, 0x00, 0x01, 0x00,
161 fake_storage.expected[0..recording0.len()].copy_from_slice(&recording0);
162 fake_storage.actual[0..recording0.len()].copy_from_slice(&recording0);
164 let mut logger = Logger::new(&mut fake_storage);
167 let tap = gps::TimeAndPos {
169 unix_time: 1478026312,
174 let recording_id = logger.start_recording(&tap);
175 assert_eq!(2, recording_id);
177 let sectors_written = logger.stop_recording(&tap);
178 assert_eq!(1, sectors_written);
182 0x01, 0x00, 0x02, 0x00,
183 0x48, 0xe4, 0x18, 0x58,
188 0x9c, 0x8d, 0x99, 0x07,
189 0x9e, 0x8d, 0x99, 0x07,
192 0xff, 0xff, 0xff, 0xff, 0x0f,
199 let end = start + expected.len();
200 fake_storage.expected[start..end].copy_from_slice(&expected);
202 assert_eq!(fake_storage.expected, fake_storage.actual);
206 fn multi_sector_recording() {
207 let mut fake_storage = FakeStorage::new();
209 let mut logger = Logger::new(&mut fake_storage);
212 let tap = gps::TimeAndPos {
214 unix_time: 1578425250,
219 let recording_id = logger.start_recording(&tap);
220 assert_eq!(1, recording_id);
222 let mut prev_tap = tap;
225 let tap = gps::TimeAndPos {
227 unix_time: prev_tap.unix_time + 1,
228 latitude: prev_tap.latitude + 1,
229 longitude: prev_tap.longitude + 1,
232 logger.log(&prev_tap, &tap);
237 let sectors_written = logger.stop_recording(&tap);
238 assert_eq!(2, sectors_written);
241 0x01, 0x00, 0x01, 0x00,
245 0x03, 0x00, 0x01, 0x00,
248 assert_eq!(header0, fake_storage.actual[0..(0 + header0.len())]);
249 assert_eq!(header1, fake_storage.actual[4096..(4096 + header1.len())]);
252 extern "C" fn flush_write_buffer(user_data: *mut BufferUserData,
255 count: usize) -> isize {
256 let _file = user_data as *mut std::fs::File;
259 let file = &mut * _file;
261 file.write_all(std::slice::from_raw_parts(buf, count)).unwrap();
267 // Verifies that Logger::get_recording() detects unknown recording IDs.
269 fn get_recording_invalid() {
270 let pipe = Pipe::new();
272 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
274 let mut yenc_buffer_space = [0u8; 8192];
275 let mut yenc_buffer = Buffer::alloc();
277 let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
279 yenc_buffer.init(yenc_buffer_space.as_mut_ptr(),
280 yenc_buffer_space.len(),
284 let mut fake_storage = FakeStorage::new();
286 let mut logger = Logger::new(&mut fake_storage);
289 // Zero is never a valid recording id.
290 let result = logger.get_recording(0, &mut yenc_buffer);
291 assert_eq!(LoggerError::NoSuchRecording, result.unwrap_err());
293 let result = logger.get_recording(1, &mut yenc_buffer);
294 assert_eq!(LoggerError::NoSuchRecording, result.unwrap_err());
297 // Verifies that Logger::get_recording() can retrieve finished recordings.
299 fn get_recording_valid() {
300 let pipe = Pipe::new();
302 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
304 let mut yenc_buffer_space = [0u8; 8192];
305 let mut yenc_buffer = Buffer::alloc();
307 let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
309 yenc_buffer.init(yenc_buffer_space.as_mut_ptr(),
310 yenc_buffer_space.len(),
314 let mut fake_storage = FakeStorage::new();
316 let mut logger = Logger::new(&mut fake_storage);
319 let result = logger.get_recording(1, &mut yenc_buffer);
320 assert_eq!(LoggerError::NoSuchRecording, result.unwrap_err());
322 let tap0 = gps::TimeAndPos {
324 unix_time: 1478026311,
329 logger.start_recording(&tap0);
331 let tap1 = gps::TimeAndPos {
333 unix_time: 1478026311 + 1,
334 latitude: 0x73234e + 5,
335 longitude: 0x73234f + 5,
338 logger.log(&tap0, &tap1);
340 let tap2 = gps::TimeAndPos {
342 unix_time: 1478026311 + 2,
343 latitude: 0x73234e + 10,
344 longitude: 0x73234f + 10,
347 logger.log(&tap1, &tap2);
349 logger.stop_recording(&tap2);
351 assert!(logger.get_recording(1, &mut yenc_buffer).is_ok());
354 // Verifies that Logger::list_recordings() shows an empty listing
355 // if there are no recordings.
357 fn list_recordings0() {
358 let pipe = Pipe::new();
360 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
362 let mut ls_buffer_space = [0u8; 4096];
363 let mut ls_buffer = Buffer::alloc();
365 let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
367 ls_buffer.init(ls_buffer_space.as_mut_ptr(),
368 ls_buffer_space.len(),
372 let mut fake_storage = FakeStorage::new();
374 let mut logger = Logger::new(&mut fake_storage);
377 logger.list_recordings(&mut ls_buffer);
379 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.read_fd()) };
381 let mut listing_raw = [0u8; 256];
383 // There are no recordings, so there's no data in the pipe either.
384 assert!(file.read(&mut listing_raw).is_err());
387 // Verifies that Logger::list_recordings() shows a listing
388 // of a single recording in the very first sector.
390 fn list_recordings1() {
391 let pipe = Pipe::new();
393 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
395 let mut ls_buffer_space = [0u8; 4096];
396 let mut ls_buffer = Buffer::alloc();
398 let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
400 ls_buffer.init(ls_buffer_space.as_mut_ptr(),
401 ls_buffer_space.len(),
405 let mut fake_storage = FakeStorage::new();
407 // Mark first sector as in use.
410 0x01, 0x00, 0x01, 0x00,
411 0xa2, 0xdb, 0x14, 0x5e,
414 fake_storage.expected[0..recording0.len()].copy_from_slice(&recording0);
415 fake_storage.actual[0..recording0.len()].copy_from_slice(&recording0);
417 let mut logger = Logger::new(&mut fake_storage);
420 logger.list_recordings(&mut ls_buffer);
422 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.read_fd()) };
424 let mut listing_raw = [0u8; 256];
425 let num_bytes_read = file.read(&mut listing_raw).unwrap();
427 let expected_bytes = b"\
428 2020-01-07 19:27:30 4K 1\n";
430 assert_eq!(String::from_utf8(expected_bytes.to_vec()).unwrap(),
431 String::from_utf8(listing_raw[0..num_bytes_read].to_vec()).unwrap());
434 // Verifies that Logger::list_recordings() handles sectors holding
435 // additional recording data.
437 fn list_recording1_multi_sector() {
438 let pipe = Pipe::new();
440 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
442 let mut ls_buffer_space = [0u8; 4096];
443 let mut ls_buffer = Buffer::alloc();
445 let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
447 ls_buffer.init(ls_buffer_space.as_mut_ptr(),
448 ls_buffer_space.len(),
452 let mut fake_storage = FakeStorage::new();
454 // The first sector starts recording 1.
457 0x01, 0x00, 0x01, 0x00,
458 0x75, 0x18, 0x17, 0x5e,
461 // The second sector has additional data for recording 1.
463 0x03, 0x00, 0x01, 0x00,
466 fake_storage.actual[0..header0.len()].copy_from_slice(&header0);
467 fake_storage.actual[4096..4096 + header1.len()].copy_from_slice(&header1);
469 let mut logger = Logger::new(&mut fake_storage);
472 logger.list_recordings(&mut ls_buffer);
474 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.read_fd()) };
476 let mut listing_raw = [0u8; 4096];
477 let num_bytes_read = file.read(&mut listing_raw).unwrap();
479 let expected_bytes = b"\
480 2020-01-09 12:11:33 8K 1\n";
482 assert_eq!(String::from_utf8(expected_bytes.to_vec()).unwrap(),
483 String::from_utf8(listing_raw[0..num_bytes_read].to_vec()).unwrap());