ee0b30b92b749fbb61ea73dd3918b1613143baa5
[gps-watch.git] / test / logger_test.rs
1 /*
2  * Copyright (c) 2020 Tilman Sauerbeck (tilman at code-monkey de)
3  *
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:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
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.
22  */
23
24 use common::gps;
25 use common::storage::{Storage, Error};
26 use common::logger::*;
27
28 struct FakeStorage {
29     expected: Box<[u8]>,
30     actual: Box<[u8]>,
31 }
32
33 impl FakeStorage {
34     fn new() -> FakeStorage {
35         FakeStorage {
36             expected: vec![0xff; MEMORY_SIZE].into_boxed_slice(),
37             actual: vec![0xff; MEMORY_SIZE].into_boxed_slice(),
38         }
39     }
40 }
41
42 impl Storage for FakeStorage {
43     fn size(&self) -> usize {
44         MEMORY_SIZE
45     }
46
47     fn read(&self, address: usize, buffer: &mut [u8]) {
48         for i in 0..buffer.len() {
49             buffer[i] = self.actual[address + i];
50         }
51     }
52
53     fn write(&mut self, address: usize, buffer: &[u8; 4096]) -> Result<(), Error> {
54         if (address & 4095) != 0 {
55             return Err(Error::UnalignedAddress);
56         }
57
58         for i in 0..buffer.len() {
59             self.actual[address + i] = buffer[i];
60         }
61
62         Ok(())
63     }
64
65     fn clear(&mut self) {
66         self.actual = vec![0xff; MEMORY_SIZE].into_boxed_slice();
67     }
68 }
69
70 // Runs a couple of recordings on fully erased flash memory.
71 #[test]
72 fn first_recording() {
73     let mut fake_storage = FakeStorage::new();
74
75     let mut logger = Logger::new(&mut fake_storage);
76     logger.init();
77
78     let tap = gps::TimeAndPos {
79         system_time: 0,
80         unix_time: 1478026311,
81         latitude: 0x73234e,
82         longitude: 0x73234f,
83     };
84
85     let recording_id = logger.start_recording(&tap);
86     assert_eq!(1, recording_id);
87
88     let sectors_written = logger.stop_recording(&tap);
89     assert_eq!(1, sectors_written);
90
91     let expected = [
92         // Header:
93         0x01, 0x00, 0x01, 0x00,
94         0x47, 0xe4, 0x18, 0x58,
95
96         // First point:
97         0x03,
98         0x00,
99         0x9c, 0x8d, 0x99, 0x07,
100         0x9e, 0x8d, 0x99, 0x07,
101
102         // Sentinel:
103         0xff, 0xff, 0xff, 0xff, 0x0f,
104
105         // Footer:
106         0x00, 0x00
107     ];
108
109     let start = 0;
110     let end = start + expected.len();
111     fake_storage.expected[start..end].copy_from_slice(&expected);
112
113     assert_eq!(fake_storage.expected, fake_storage.actual);
114 }
115
116 #[test]
117 fn second_recording() {
118     let mut fake_storage = FakeStorage::new();
119
120     // Mark first sector as in use.
121     let recording0 = [
122         // Header:
123         0x01, 0x00, 0x01, 0x00,
124     ];
125
126     fake_storage.expected[0..recording0.len()].copy_from_slice(&recording0);
127     fake_storage.actual[0..recording0.len()].copy_from_slice(&recording0);
128
129     let mut logger = Logger::new(&mut fake_storage);
130     logger.init();
131
132     let tap = gps::TimeAndPos {
133         system_time: 0,
134         unix_time: 1478026312,
135         latitude: 0x73234e,
136         longitude: 0x73234f,
137     };
138
139     let recording_id = logger.start_recording(&tap);
140     assert_eq!(2, recording_id);
141
142     let sectors_written = logger.stop_recording(&tap);
143     assert_eq!(1, sectors_written);
144
145     let expected = [
146         // Header:
147         0x01, 0x00, 0x02, 0x00,
148         0x48, 0xe4, 0x18, 0x58,
149
150         // First point:
151         0x03,
152         0x00,
153         0x9c, 0x8d, 0x99, 0x07,
154         0x9e, 0x8d, 0x99, 0x07,
155
156         // Sentinel:
157         0xff, 0xff, 0xff, 0xff, 0x0f,
158
159         // Footer:
160         0x00, 0x00
161     ];
162
163     let start = 4096;
164     let end = start + expected.len();
165     fake_storage.expected[start..end].copy_from_slice(&expected);
166
167     assert_eq!(fake_storage.expected, fake_storage.actual);
168 }
169
170 #[test]
171 fn multi_sector_recording() {
172     let mut fake_storage = FakeStorage::new();
173
174     let mut logger = Logger::new(&mut fake_storage);
175     logger.init();
176
177     let tap = gps::TimeAndPos {
178         system_time: 0,
179         unix_time: 1578425250,
180         latitude: 0x73234e,
181         longitude: 0x73234f,
182     };
183
184     let recording_id = logger.start_recording(&tap);
185     assert_eq!(1, recording_id);
186
187     let mut prev_tap = tap;
188
189     for _ in 0..2048 {
190         let tap = gps::TimeAndPos {
191             system_time: 0,
192             unix_time: prev_tap.unix_time + 1,
193             latitude: prev_tap.latitude + 1,
194             longitude: prev_tap.longitude + 1,
195         };
196
197         logger.log(&prev_tap, &tap);
198
199         prev_tap = tap;
200     }
201
202     let sectors_written = logger.stop_recording(&tap);
203     assert_eq!(2, sectors_written);
204
205     let header0 = [
206         0x01, 0x00, 0x01, 0x00,
207     ];
208
209     let header1 = [
210         0x03, 0x00, 0x01, 0x00,
211     ];
212
213     assert_eq!(header0, fake_storage.actual[0..(0 + header0.len())]);
214     assert_eq!(header1, fake_storage.actual[4096..(4096 + header1.len())]);
215 }