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 pipe(pipefd: *mut i32) -> i32;
86 pipe(pipe_fd.as_mut_ptr());
94 fn read_fd(&self) -> i32 {
98 fn write_fd(&self) -> i32 {
103 // Runs a couple of recordings on fully erased flash memory.
105 fn first_recording() {
106 let mut fake_storage = FakeStorage::new();
108 let mut logger = Logger::new(&mut fake_storage);
111 let tap = gps::TimeAndPos {
113 unix_time: 1478026311,
118 let recording_id = logger.start_recording(&tap);
119 assert_eq!(1, recording_id);
121 let sectors_written = logger.stop_recording(&tap);
122 assert_eq!(1, sectors_written);
126 0x01, 0x00, 0x01, 0x00,
127 0x47, 0xe4, 0x18, 0x58,
132 0x9c, 0x8d, 0x99, 0x07,
133 0x9e, 0x8d, 0x99, 0x07,
136 0xff, 0xff, 0xff, 0xff, 0x0f,
143 let end = start + expected.len();
144 fake_storage.expected[start..end].copy_from_slice(&expected);
146 assert_eq!(fake_storage.expected, fake_storage.actual);
150 fn second_recording() {
151 let mut fake_storage = FakeStorage::new();
153 // Mark first sector as in use.
156 0x01, 0x00, 0x01, 0x00,
159 fake_storage.expected[0..recording0.len()].copy_from_slice(&recording0);
160 fake_storage.actual[0..recording0.len()].copy_from_slice(&recording0);
162 let mut logger = Logger::new(&mut fake_storage);
165 let tap = gps::TimeAndPos {
167 unix_time: 1478026312,
172 let recording_id = logger.start_recording(&tap);
173 assert_eq!(2, recording_id);
175 let sectors_written = logger.stop_recording(&tap);
176 assert_eq!(1, sectors_written);
180 0x01, 0x00, 0x02, 0x00,
181 0x48, 0xe4, 0x18, 0x58,
186 0x9c, 0x8d, 0x99, 0x07,
187 0x9e, 0x8d, 0x99, 0x07,
190 0xff, 0xff, 0xff, 0xff, 0x0f,
197 let end = start + expected.len();
198 fake_storage.expected[start..end].copy_from_slice(&expected);
200 assert_eq!(fake_storage.expected, fake_storage.actual);
204 fn multi_sector_recording() {
205 let mut fake_storage = FakeStorage::new();
207 let mut logger = Logger::new(&mut fake_storage);
210 let tap = gps::TimeAndPos {
212 unix_time: 1578425250,
217 let recording_id = logger.start_recording(&tap);
218 assert_eq!(1, recording_id);
220 let mut prev_tap = tap;
223 let tap = gps::TimeAndPos {
225 unix_time: prev_tap.unix_time + 1,
226 latitude: prev_tap.latitude + 1,
227 longitude: prev_tap.longitude + 1,
230 logger.log(&prev_tap, &tap);
235 let sectors_written = logger.stop_recording(&tap);
236 assert_eq!(2, sectors_written);
239 0x01, 0x00, 0x01, 0x00,
243 0x03, 0x00, 0x01, 0x00,
246 assert_eq!(header0, fake_storage.actual[0..(0 + header0.len())]);
247 assert_eq!(header1, fake_storage.actual[4096..(4096 + header1.len())]);
250 extern "C" fn flush_write_buffer(user_data: *mut BufferUserData,
253 count: usize) -> isize {
254 let _file = user_data as *mut std::fs::File;
257 let file = &mut * _file;
259 file.write_all(std::slice::from_raw_parts(buf, count)).unwrap();
265 // Verifies that Logger::get_recording() detects unknown recording IDs.
267 fn get_recording_invalid() {
268 let pipe = Pipe::new();
270 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
272 let mut yenc_buffer_space = [0u8; 8192];
273 let mut yenc_buffer = Buffer::alloc();
275 let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
277 yenc_buffer.init(yenc_buffer_space.as_mut_ptr(),
278 yenc_buffer_space.len(),
282 let mut fake_storage = FakeStorage::new();
284 let mut logger = Logger::new(&mut fake_storage);
287 // Zero is never a valid recording id.
288 let result = logger.get_recording(0, &mut yenc_buffer);
289 assert_eq!(LoggerError::NoSuchRecording, result.unwrap_err());
291 let result = logger.get_recording(1, &mut yenc_buffer);
292 assert_eq!(LoggerError::NoSuchRecording, result.unwrap_err());
295 // Verifies that Logger::get_recording() can retrieve finished recordings.
297 fn get_recording_valid() {
298 let pipe = Pipe::new();
300 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
302 let mut yenc_buffer_space = [0u8; 8192];
303 let mut yenc_buffer = Buffer::alloc();
305 let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
307 yenc_buffer.init(yenc_buffer_space.as_mut_ptr(),
308 yenc_buffer_space.len(),
312 let mut fake_storage = FakeStorage::new();
314 let mut logger = Logger::new(&mut fake_storage);
317 let result = logger.get_recording(1, &mut yenc_buffer);
318 assert_eq!(LoggerError::NoSuchRecording, result.unwrap_err());
320 let tap0 = gps::TimeAndPos {
322 unix_time: 1478026311,
327 logger.start_recording(&tap0);
329 let tap1 = gps::TimeAndPos {
331 unix_time: 1478026311 + 1,
332 latitude: 0x73234e + 5,
333 longitude: 0x73234f + 5,
336 logger.log(&tap0, &tap1);
338 let tap2 = gps::TimeAndPos {
340 unix_time: 1478026311 + 2,
341 latitude: 0x73234e + 10,
342 longitude: 0x73234f + 10,
345 logger.log(&tap1, &tap2);
347 logger.stop_recording(&tap2);
349 assert!(logger.get_recording(1, &mut yenc_buffer).is_ok());
352 // Verifies that Logger::list_recordings() shows a listing
353 // of a single recording in the very first sector.
355 fn list_recordings1() {
356 let pipe = Pipe::new();
358 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
360 let mut ls_buffer_space = [0u8; 4096];
361 let mut ls_buffer = Buffer::alloc();
363 let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
365 ls_buffer.init(ls_buffer_space.as_mut_ptr(),
366 ls_buffer_space.len(),
370 let mut fake_storage = FakeStorage::new();
372 // Mark first sector as in use.
375 0x01, 0x00, 0x01, 0x00,
376 0xa2, 0xdb, 0x14, 0x5e,
379 fake_storage.expected[0..recording0.len()].copy_from_slice(&recording0);
380 fake_storage.actual[0..recording0.len()].copy_from_slice(&recording0);
382 let mut logger = Logger::new(&mut fake_storage);
385 logger.list_recordings(&mut ls_buffer);
387 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.read_fd()) };
389 let mut listing_raw = [0u8; 256];
390 let num_bytes_read = file.read(&mut listing_raw).unwrap();
392 let expected_bytes = b"\
393 2020-01-07 19:27:30 1\n";
395 assert_eq!(String::from_utf8(expected_bytes.to_vec()).unwrap(),
396 String::from_utf8(listing_raw[0..num_bytes_read].to_vec()).unwrap());