test: Add tests for the logger module.
authorTilman Sauerbeck <tilman@code-monkey.de>
Wed, 8 Jan 2020 21:13:48 +0000 (22:13 +0100)
committerTilman Sauerbeck <tilman@code-monkey.de>
Thu, 9 Jan 2020 14:19:36 +0000 (15:19 +0100)
SConscript.test
test/logger_test.rs [new file with mode: 0644]
test/main.rs

index 57593ad3b74ea69c90efa697d601c5e2804a2829..32fa7230ca76f37aaa5719f40d6018b4940f69ef 100644 (file)
@@ -11,6 +11,7 @@ SConscript('SConscript.libcommon.rs', exports='env', duplicate=0)
 test_source_files = [
     'test/main.rs', # Must be listed first (see below).
     'test/gps_test.rs',
+    'test/logger_test.rs',
 ]
 
 test_env = env.Clone()
diff --git a/test/logger_test.rs b/test/logger_test.rs
new file mode 100644 (file)
index 0000000..ee0b30b
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2020 Tilman Sauerbeck (tilman at code-monkey de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+use common::gps;
+use common::storage::{Storage, Error};
+use common::logger::*;
+
+struct FakeStorage {
+    expected: Box<[u8]>,
+    actual: Box<[u8]>,
+}
+
+impl FakeStorage {
+    fn new() -> FakeStorage {
+        FakeStorage {
+            expected: vec![0xff; MEMORY_SIZE].into_boxed_slice(),
+            actual: vec![0xff; MEMORY_SIZE].into_boxed_slice(),
+        }
+    }
+}
+
+impl Storage for FakeStorage {
+    fn size(&self) -> usize {
+        MEMORY_SIZE
+    }
+
+    fn read(&self, address: usize, buffer: &mut [u8]) {
+        for i in 0..buffer.len() {
+            buffer[i] = self.actual[address + i];
+        }
+    }
+
+    fn write(&mut self, address: usize, buffer: &[u8; 4096]) -> Result<(), Error> {
+        if (address & 4095) != 0 {
+            return Err(Error::UnalignedAddress);
+        }
+
+        for i in 0..buffer.len() {
+            self.actual[address + i] = buffer[i];
+        }
+
+        Ok(())
+    }
+
+    fn clear(&mut self) {
+        self.actual = vec![0xff; MEMORY_SIZE].into_boxed_slice();
+    }
+}
+
+// Runs a couple of recordings on fully erased flash memory.
+#[test]
+fn first_recording() {
+    let mut fake_storage = FakeStorage::new();
+
+    let mut logger = Logger::new(&mut fake_storage);
+    logger.init();
+
+    let tap = gps::TimeAndPos {
+        system_time: 0,
+        unix_time: 1478026311,
+        latitude: 0x73234e,
+        longitude: 0x73234f,
+    };
+
+    let recording_id = logger.start_recording(&tap);
+    assert_eq!(1, recording_id);
+
+    let sectors_written = logger.stop_recording(&tap);
+    assert_eq!(1, sectors_written);
+
+    let expected = [
+        // Header:
+        0x01, 0x00, 0x01, 0x00,
+        0x47, 0xe4, 0x18, 0x58,
+
+        // First point:
+        0x03,
+        0x00,
+        0x9c, 0x8d, 0x99, 0x07,
+        0x9e, 0x8d, 0x99, 0x07,
+
+        // Sentinel:
+        0xff, 0xff, 0xff, 0xff, 0x0f,
+
+        // Footer:
+        0x00, 0x00
+    ];
+
+    let start = 0;
+    let end = start + expected.len();
+    fake_storage.expected[start..end].copy_from_slice(&expected);
+
+    assert_eq!(fake_storage.expected, fake_storage.actual);
+}
+
+#[test]
+fn second_recording() {
+    let mut fake_storage = FakeStorage::new();
+
+    // Mark first sector as in use.
+    let recording0 = [
+        // Header:
+        0x01, 0x00, 0x01, 0x00,
+    ];
+
+    fake_storage.expected[0..recording0.len()].copy_from_slice(&recording0);
+    fake_storage.actual[0..recording0.len()].copy_from_slice(&recording0);
+
+    let mut logger = Logger::new(&mut fake_storage);
+    logger.init();
+
+    let tap = gps::TimeAndPos {
+        system_time: 0,
+        unix_time: 1478026312,
+        latitude: 0x73234e,
+        longitude: 0x73234f,
+    };
+
+    let recording_id = logger.start_recording(&tap);
+    assert_eq!(2, recording_id);
+
+    let sectors_written = logger.stop_recording(&tap);
+    assert_eq!(1, sectors_written);
+
+    let expected = [
+        // Header:
+        0x01, 0x00, 0x02, 0x00,
+        0x48, 0xe4, 0x18, 0x58,
+
+        // First point:
+        0x03,
+        0x00,
+        0x9c, 0x8d, 0x99, 0x07,
+        0x9e, 0x8d, 0x99, 0x07,
+
+        // Sentinel:
+        0xff, 0xff, 0xff, 0xff, 0x0f,
+
+        // Footer:
+        0x00, 0x00
+    ];
+
+    let start = 4096;
+    let end = start + expected.len();
+    fake_storage.expected[start..end].copy_from_slice(&expected);
+
+    assert_eq!(fake_storage.expected, fake_storage.actual);
+}
+
+#[test]
+fn multi_sector_recording() {
+    let mut fake_storage = FakeStorage::new();
+
+    let mut logger = Logger::new(&mut fake_storage);
+    logger.init();
+
+    let tap = gps::TimeAndPos {
+        system_time: 0,
+        unix_time: 1578425250,
+        latitude: 0x73234e,
+        longitude: 0x73234f,
+    };
+
+    let recording_id = logger.start_recording(&tap);
+    assert_eq!(1, recording_id);
+
+    let mut prev_tap = tap;
+
+    for _ in 0..2048 {
+        let tap = gps::TimeAndPos {
+            system_time: 0,
+            unix_time: prev_tap.unix_time + 1,
+            latitude: prev_tap.latitude + 1,
+            longitude: prev_tap.longitude + 1,
+        };
+
+        logger.log(&prev_tap, &tap);
+
+        prev_tap = tap;
+    }
+
+    let sectors_written = logger.stop_recording(&tap);
+    assert_eq!(2, sectors_written);
+
+    let header0 = [
+        0x01, 0x00, 0x01, 0x00,
+    ];
+
+    let header1 = [
+        0x03, 0x00, 0x01, 0x00,
+    ];
+
+    assert_eq!(header0, fake_storage.actual[0..(0 + header0.len())]);
+    assert_eq!(header1, fake_storage.actual[4096..(4096 + header1.len())]);
+}
index 011e1859f9912e3311a909bf1d0f065c318120e7..265623eedb208491f0503f80e622a6f5a337b238 100644 (file)
@@ -24,6 +24,7 @@
 extern crate common;
 
 mod gps_test;
+mod logger_test;
 
 #[no_mangle]
 extern fn get_ticks() -> u32 {