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 common::buffer::{Buffer, BufferUserData};
26 use common::storage::{Storage, Error};
27 use common::logger::{MEMORY_SIZE, Logger, Error as LoggerError};
35 fn new() -> FakeStorage {
37 expected: vec![0xff; MEMORY_SIZE].into_boxed_slice(),
38 actual: vec![0xff; MEMORY_SIZE].into_boxed_slice(),
43 impl Storage for FakeStorage {
44 fn size(&self) -> usize {
48 fn read(&self, address: usize, buffer: &mut [u8]) {
49 for i in 0..buffer.len() {
50 buffer[i] = self.actual[address + i];
54 fn write(&mut self, address: usize, buffer: &[u8; 4096]) -> Result<(), Error> {
55 if (address & 4095) != 0 {
56 return Err(Error::UnalignedAddress);
59 for i in 0..buffer.len() {
60 self.actual[address + i] = buffer[i];
67 self.actual = vec![0xff; MEMORY_SIZE].into_boxed_slice();
77 let mut pipe_fd = [-1i32; 2];
81 fn pipe(pipefd: *mut i32) -> i32;
84 pipe(pipe_fd.as_mut_ptr());
92 fn read_fd(&self) -> i32 {
96 fn write_fd(&self) -> i32 {
101 // Runs a couple of recordings on fully erased flash memory.
103 fn first_recording() {
104 let mut fake_storage = FakeStorage::new();
106 let mut logger = Logger::new(&mut fake_storage);
109 let tap = gps::TimeAndPos {
111 unix_time: 1478026311,
116 let recording_id = logger.start_recording(&tap);
117 assert_eq!(1, recording_id);
119 let sectors_written = logger.stop_recording(&tap);
120 assert_eq!(1, sectors_written);
124 0x01, 0x00, 0x01, 0x00,
125 0x47, 0xe4, 0x18, 0x58,
130 0x9c, 0x8d, 0x99, 0x07,
131 0x9e, 0x8d, 0x99, 0x07,
134 0xff, 0xff, 0xff, 0xff, 0x0f,
141 let end = start + expected.len();
142 fake_storage.expected[start..end].copy_from_slice(&expected);
144 assert_eq!(fake_storage.expected, fake_storage.actual);
148 fn second_recording() {
149 let mut fake_storage = FakeStorage::new();
151 // Mark first sector as in use.
154 0x01, 0x00, 0x01, 0x00,
157 fake_storage.expected[0..recording0.len()].copy_from_slice(&recording0);
158 fake_storage.actual[0..recording0.len()].copy_from_slice(&recording0);
160 let mut logger = Logger::new(&mut fake_storage);
163 let tap = gps::TimeAndPos {
165 unix_time: 1478026312,
170 let recording_id = logger.start_recording(&tap);
171 assert_eq!(2, recording_id);
173 let sectors_written = logger.stop_recording(&tap);
174 assert_eq!(1, sectors_written);
178 0x01, 0x00, 0x02, 0x00,
179 0x48, 0xe4, 0x18, 0x58,
184 0x9c, 0x8d, 0x99, 0x07,
185 0x9e, 0x8d, 0x99, 0x07,
188 0xff, 0xff, 0xff, 0xff, 0x0f,
195 let end = start + expected.len();
196 fake_storage.expected[start..end].copy_from_slice(&expected);
198 assert_eq!(fake_storage.expected, fake_storage.actual);
202 fn multi_sector_recording() {
203 let mut fake_storage = FakeStorage::new();
205 let mut logger = Logger::new(&mut fake_storage);
208 let tap = gps::TimeAndPos {
210 unix_time: 1578425250,
215 let recording_id = logger.start_recording(&tap);
216 assert_eq!(1, recording_id);
218 let mut prev_tap = tap;
221 let tap = gps::TimeAndPos {
223 unix_time: prev_tap.unix_time + 1,
224 latitude: prev_tap.latitude + 1,
225 longitude: prev_tap.longitude + 1,
228 logger.log(&prev_tap, &tap);
233 let sectors_written = logger.stop_recording(&tap);
234 assert_eq!(2, sectors_written);
237 0x01, 0x00, 0x01, 0x00,
241 0x03, 0x00, 0x01, 0x00,
244 assert_eq!(header0, fake_storage.actual[0..(0 + header0.len())]);
245 assert_eq!(header1, fake_storage.actual[4096..(4096 + header1.len())]);
248 extern "C" fn flush_write_buffer(user_data: *mut BufferUserData,
251 count: usize) -> isize {
252 let _file = user_data as *mut std::fs::File;
255 let file = &mut * _file;
257 file.write_all(std::slice::from_raw_parts(buf, count)).unwrap();
263 // Verifies that Logger::get_recording() detects unknown recording IDs.
265 fn get_recording_invalid() {
266 let pipe = Pipe::new();
268 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
270 let mut yenc_buffer_space = [0u8; 8192];
271 let mut yenc_buffer = Buffer::alloc();
273 let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
275 yenc_buffer.init(yenc_buffer_space.as_mut_ptr(),
276 yenc_buffer_space.len(),
280 let mut fake_storage = FakeStorage::new();
282 let mut logger = Logger::new(&mut fake_storage);
285 // Zero is never a valid recording id.
286 let result = logger.get_recording(0, &mut yenc_buffer);
287 assert_eq!(LoggerError::NoSuchRecording, result.unwrap_err());
289 let result = logger.get_recording(1, &mut yenc_buffer);
290 assert_eq!(LoggerError::NoSuchRecording, result.unwrap_err());
293 // Verifies that Logger::get_recording() can retrieve finished recordings.
295 fn get_recording_valid() {
296 let pipe = Pipe::new();
298 let mut file = unsafe { std::fs::File::from_raw_fd(pipe.write_fd()) };
300 let mut yenc_buffer_space = [0u8; 8192];
301 let mut yenc_buffer = Buffer::alloc();
303 let user_data = (&mut file as *mut std::fs::File) as *mut BufferUserData;
305 yenc_buffer.init(yenc_buffer_space.as_mut_ptr(),
306 yenc_buffer_space.len(),
310 let mut fake_storage = FakeStorage::new();
312 let mut logger = Logger::new(&mut fake_storage);
315 let result = logger.get_recording(1, &mut yenc_buffer);
316 assert_eq!(LoggerError::NoSuchRecording, result.unwrap_err());
318 let tap0 = gps::TimeAndPos {
320 unix_time: 1478026311,
325 logger.start_recording(&tap0);
327 let tap1 = gps::TimeAndPos {
329 unix_time: 1478026311 + 1,
330 latitude: 0x73234e + 5,
331 longitude: 0x73234f + 5,
334 logger.log(&tap0, &tap1);
336 let tap2 = gps::TimeAndPos {
338 unix_time: 1478026311 + 2,
339 latitude: 0x73234e + 10,
340 longitude: 0x73234f + 10,
343 logger.log(&tap1, &tap2);
345 logger.stop_recording(&tap2);
347 assert!(logger.get_recording(1, &mut yenc_buffer).is_ok());