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};
27 use common::fixed15_49;
29 use common::storage::{Storage, Error};
30 use common::logger::{MEMORY_SIZE, Logger, Error as LoggerError};
32 type Fixed = fixed15_49::Fixed15_49;
40 fn new() -> FakeStorage {
42 expected: vec![0xff; MEMORY_SIZE].into_boxed_slice(),
43 actual: vec![0xff; MEMORY_SIZE].into_boxed_slice(),
48 impl Storage for FakeStorage {
49 fn size(&self) -> usize {
53 fn read(&self, address: usize, buffer: &mut [u8]) {
54 for i in 0..buffer.len() {
55 buffer[i] = self.actual[address + i];
59 fn write(&mut self, address: usize, buffer: &[u8; 4096]) -> Result<(), Error> {
60 if (address & 4095) != 0 {
61 return Err(Error::UnalignedAddress);
64 for i in 0..buffer.len() {
65 self.actual[address + i] = buffer[i];
72 self.actual = vec![0xff; MEMORY_SIZE].into_boxed_slice();
82 let mut pipe_fd = [-1i32; 2];
86 fn pipe2(pipefd: *mut i32, flags: i32) -> i32;
89 const O_NONBLOCK : i32 = 0x800;
91 pipe2(pipe_fd.as_mut_ptr(), O_NONBLOCK);
99 fn read_fd(&self) -> i32 {
103 fn write_fd(&self) -> i32 {
108 // Runs a couple of recordings on fully erased flash memory.
110 fn first_recording() {
111 let mut fake_storage = FakeStorage::new();
113 let mut logger = Logger::new(&mut fake_storage);
116 let tap = gps::TimeAndPos {
118 unix_time: 1478026311,
121 latitude_rad: Fixed::from_f32(12.57613).to_radians(),
122 longitude_rad: Fixed::from_f32(12.576131666666667).to_radians(),
125 let recording_id = logger.start_recording(&tap);
126 assert_eq!(1, recording_id);
128 let sectors_written = logger.stop_recording(&tap);
129 assert_eq!(1, sectors_written);
133 0x01, 0x00, 0x01, 0x00,
134 0x47, 0xe4, 0x18, 0x58,
139 0x9c, 0x8d, 0x99, 0x07,
140 0x9e, 0x8d, 0x99, 0x07,
143 0xff, 0xff, 0xff, 0xff, 0x0f,
150 let end = start + expected.len();
151 fake_storage.expected[start..end].copy_from_slice(&expected);
153 assert_eq!(fake_storage.expected, fake_storage.actual);
157 fn second_recording() {
158 let mut fake_storage = FakeStorage::new();
160 // Mark first sector as in use.
163 0x01, 0x00, 0x01, 0x00,
166 fake_storage.expected[0..recording0.len()].copy_from_slice(&recording0);
167 fake_storage.actual[0..recording0.len()].copy_from_slice(&recording0);
169 let mut logger = Logger::new(&mut fake_storage);
172 let tap = gps::TimeAndPos {
174 unix_time: 1478026312,
177 latitude_rad: Fixed::from_f32(12.57613).to_radians(),
178 longitude_rad: Fixed::from_f32(12.576131666666667).to_radians(),
181 let recording_id = logger.start_recording(&tap);
182 assert_eq!(2, recording_id);
184 let sectors_written = logger.stop_recording(&tap);
185 assert_eq!(1, sectors_written);
189 0x01, 0x00, 0x02, 0x00,
190 0x48, 0xe4, 0x18, 0x58,
195 0x9c, 0x8d, 0x99, 0x07,
196 0x9e, 0x8d, 0x99, 0x07,
199 0xff, 0xff, 0xff, 0xff, 0x0f,
206 let end = start + expected.len();
207 fake_storage.expected[start..end].copy_from_slice(&expected);
209 assert_eq!(fake_storage.expected, fake_storage.actual);
213 fn multi_sector_recording() {
214 let mut fake_storage = FakeStorage::new();
216 let mut logger = Logger::new(&mut fake_storage);
219 let tap = gps::TimeAndPos {
221 unix_time: 1578425250,
224 latitude_rad: Fixed::from_f32(12.57613).to_radians(),
225 longitude_rad: Fixed::from_f32(12.576131666666667).to_radians(),
228 let recording_id = logger.start_recording(&tap);
229 assert_eq!(1, recording_id);
231 let mut prev_tap = tap;
234 let tap = gps::TimeAndPos {
236 unix_time: prev_tap.unix_time + 1,
237 latitude: prev_tap.latitude + 1,
238 longitude: prev_tap.longitude + 1,
239 latitude_rad: Fixed::from_f32(
240 (prev_tap.latitude + 1) as f32 / 600000.0).to_radians(),
241 longitude_rad: Fixed::from_f32(
242 (prev_tap.longitude + 1) as f32 / 600000.0).to_radians(),
245 logger.log(&prev_tap, &tap);
250 let sectors_written = logger.stop_recording(&tap);
251 assert_eq!(2, sectors_written);
254 0x01, 0x00, 0x01, 0x00,
258 0x03, 0x00, 0x01, 0x00,
261 assert_eq!(header0, fake_storage.actual[0..(0 + header0.len())]);
262 assert_eq!(header1, fake_storage.actual[4096..(4096 + header1.len())]);
265 extern "C" fn flush_write_buffer(user_data: *mut BufferUserData,
268 count: usize) -> isize {
269 let _file = user_data as *mut std::fs::File;
272 let file = &mut * _file;
274 file.write_all(std::slice::from_raw_parts(buf, count)).unwrap();
280 // Verifies that Logger::get_recording() detects unknown recording IDs.
282 fn get_recording_invalid() {
283 let pipe = Pipe::new();
285 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
287 let mut yenc_buffer_space = [0u8; 8192];
288 let mut yenc_buffer = Buffer::alloc();
290 let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
292 yenc_buffer.init(yenc_buffer_space.as_mut_ptr(),
293 yenc_buffer_space.len(),
297 let mut fake_storage = FakeStorage::new();
299 let mut logger = Logger::new(&mut fake_storage);
302 // Zero is never a valid recording id.
303 let result = logger.get_recording(0, &mut yenc_buffer);
304 assert_eq!(LoggerError::NoSuchRecording, result.unwrap_err());
306 let result = logger.get_recording(1, &mut yenc_buffer);
307 assert_eq!(LoggerError::NoSuchRecording, result.unwrap_err());
310 // Verifies that Logger::get_recording() can retrieve finished recordings.
312 fn get_recording_valid() {
313 let pipe = Pipe::new();
315 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
317 let mut yenc_buffer_space = [0u8; 8192];
318 let mut yenc_buffer = Buffer::alloc();
320 let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
322 yenc_buffer.init(yenc_buffer_space.as_mut_ptr(),
323 yenc_buffer_space.len(),
327 let mut fake_storage = FakeStorage::new();
329 let mut logger = Logger::new(&mut fake_storage);
332 let result = logger.get_recording(1, &mut yenc_buffer);
333 assert_eq!(LoggerError::NoSuchRecording, result.unwrap_err());
335 let tap0 = gps::TimeAndPos {
337 unix_time: 1478026311,
340 latitude_rad: Fixed::from_f32(12.57613).to_radians(),
341 longitude_rad: Fixed::from_f32(12.576131666666667).to_radians(),
344 logger.start_recording(&tap0);
346 let tap1 = gps::TimeAndPos {
348 unix_time: 1478026311 + 1,
349 latitude: 0x73234e + 5,
350 longitude: 0x73234f + 5,
351 latitude_rad: Fixed::from_f32(12.576138333333333).to_radians(),
352 longitude_rad: Fixed::from_f32(12.57614).to_radians(),
355 logger.log(&tap0, &tap1);
357 let tap2 = gps::TimeAndPos {
359 unix_time: 1478026311 + 2,
360 latitude: 0x73234e + 10,
361 longitude: 0x73234f + 10,
362 latitude_rad: Fixed::from_f32(12.576146666666666).to_radians(),
363 longitude_rad: Fixed::from_f32(12.576148333333334).to_radians(),
366 logger.log(&tap1, &tap2);
368 logger.stop_recording(&tap2);
370 assert!(logger.get_recording(1, &mut yenc_buffer).is_ok());
373 // Verifies that Logger::list_recordings() shows an empty listing
374 // if there are no recordings.
376 fn list_recordings0() {
377 let pipe = Pipe::new();
379 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
381 let mut ls_buffer_space = [0u8; 4096];
382 let mut ls_buffer = Buffer::alloc();
384 let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
386 ls_buffer.init(ls_buffer_space.as_mut_ptr(),
387 ls_buffer_space.len(),
391 let mut fake_storage = FakeStorage::new();
393 let mut logger = Logger::new(&mut fake_storage);
396 logger.list_recordings(&mut ls_buffer);
398 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.read_fd()) };
400 let mut listing_raw = [0u8; 256];
402 // There are no recordings, so there's no data in the pipe either.
403 assert!(file.read(&mut listing_raw).is_err());
406 // Verifies that Logger::list_recordings() shows a listing
407 // of a single recording in the very first sector.
409 fn list_recordings1() {
410 let pipe = Pipe::new();
412 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
414 let mut ls_buffer_space = [0u8; 4096];
415 let mut ls_buffer = Buffer::alloc();
417 let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
419 ls_buffer.init(ls_buffer_space.as_mut_ptr(),
420 ls_buffer_space.len(),
424 let mut fake_storage = FakeStorage::new();
426 // Mark first sector as in use.
429 0x01, 0x00, 0x01, 0x00,
430 0xa2, 0xdb, 0x14, 0x5e,
433 fake_storage.expected[0..recording0.len()].copy_from_slice(&recording0);
434 fake_storage.actual[0..recording0.len()].copy_from_slice(&recording0);
436 let mut logger = Logger::new(&mut fake_storage);
439 logger.list_recordings(&mut ls_buffer);
441 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.read_fd()) };
443 let mut listing_raw = [0u8; 256];
444 let num_bytes_read = file.read(&mut listing_raw).unwrap();
446 let expected_bytes = b"\
447 2020-01-07 19:27:30 4K 1\n";
449 assert_eq!(String::from_utf8(expected_bytes.to_vec()).unwrap(),
450 String::from_utf8(listing_raw[0..num_bytes_read].to_vec()).unwrap());
453 // Verifies that Logger::list_recordings() handles sectors holding
454 // additional recording data.
456 fn list_recording1_multi_sector() {
457 let pipe = Pipe::new();
459 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
461 let mut ls_buffer_space = [0u8; 4096];
462 let mut ls_buffer = Buffer::alloc();
464 let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
466 ls_buffer.init(ls_buffer_space.as_mut_ptr(),
467 ls_buffer_space.len(),
471 let mut fake_storage = FakeStorage::new();
473 // The first sector starts recording 1.
476 0x01, 0x00, 0x01, 0x00,
477 0x75, 0x18, 0x17, 0x5e,
480 // The second sector has additional data for recording 1.
482 0x03, 0x00, 0x01, 0x00,
485 fake_storage.actual[0..header0.len()].copy_from_slice(&header0);
486 fake_storage.actual[4096..4096 + header1.len()].copy_from_slice(&header1);
488 let mut logger = Logger::new(&mut fake_storage);
491 logger.list_recordings(&mut ls_buffer);
493 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.read_fd()) };
495 let mut listing_raw = [0u8; 4096];
496 let num_bytes_read = file.read(&mut listing_raw).unwrap();
498 let expected_bytes = b"\
499 2020-01-09 12:11:33 8K 1\n";
501 assert_eq!(String::from_utf8(expected_bytes.to_vec()).unwrap(),
502 String::from_utf8(listing_raw[0..num_bytes_read].to_vec()).unwrap());