sim: Run main test as a Rust unit test

As a start of doing the testing using Rust/Cargo's test framework, write
a test runner that just runs the existing tests.  They run as they do
now, except that there is an assertion that there were no failures.

Signed-off-by: David Brown <david.brown@linaro.org>
diff --git a/sim/Cargo.toml b/sim/Cargo.toml
index 6bca65d..829a898 100644
--- a/sim/Cargo.toml
+++ b/sim/Cargo.toml
@@ -26,5 +26,12 @@
 untrusted = "0.5"
 pem = "0.4"
 
+# The simulator runs very slowly without optimization.  A value of 1
+# compiles in about half the time, but runs about 5-6 times slower.  2
+# and 3 are hardly different in either compile time or performance.
+# Use 2 in case that makes the code slightly more debuggable.
 [profile.test]
-opt-level = 1
+opt-level = 2
+
+[profile.dev]
+opt-level = 2
diff --git a/sim/src/lib.rs b/sim/src/lib.rs
index 3f3967d..fe2d52e 100644
--- a/sim/src/lib.rs
+++ b/sim/src/lib.rs
@@ -58,7 +58,7 @@
 #[derive(Copy, Clone, Debug, Deserialize)]
 pub enum DeviceName { Stm32f4, K64f, K64fBig, Nrf52840 }
 
-static ALL_DEVICES: &'static [DeviceName] = &[
+pub static ALL_DEVICES: &'static [DeviceName] = &[
     DeviceName::Stm32f4,
     DeviceName::K64f,
     DeviceName::K64fBig,
@@ -152,20 +152,20 @@
     }
 }
 
-struct RunStatus {
+pub struct RunStatus {
     failures: usize,
     passes: usize,
 }
 
 impl RunStatus {
-    fn new() -> RunStatus {
+    pub fn new() -> RunStatus {
         RunStatus {
             failures: 0,
             passes: 0,
         }
     }
 
-    fn run_single(&mut self, device: DeviceName, align: u8) {
+    pub fn run_single(&mut self, device: DeviceName, align: u8) {
         warn!("Running on device {} with alignment {}", device, align);
 
         let (mut flash, areadesc) = make_device(device, align);
@@ -249,6 +249,10 @@
             self.passes += 1;
         }
     }
+
+    pub fn failures(&self) -> usize {
+        self.failures
+    }
 }
 
 /// Build the Flash and area descriptor for a given device.
diff --git a/sim/tests/core.rs b/sim/tests/core.rs
new file mode 100644
index 0000000..dea9cfe
--- /dev/null
+++ b/sim/tests/core.rs
@@ -0,0 +1,20 @@
+//! Core tests
+//!
+//! Run the existing testsuite as a Rust unit test.
+
+extern crate bootsim;
+
+use bootsim::{ALL_DEVICES, RunStatus};
+
+#[test]
+fn core_tests() {
+    let mut status = RunStatus::new();
+
+    for &dev in ALL_DEVICES {
+        for &align in &[1, 2, 4, 8] {
+            status.run_single(dev, align);
+        }
+    }
+
+    assert!(status.failures() == 0);
+}