sim: Add dependency tests to simulator

Create a trait `Depender` which is passed down to the image create and
verification to check and test for various types of dependency
resolution.  Add a test that uses this to test the simple case of unmet
dependencies preventing an upgrade.

The actual test is disabled (with an `if false ...`) because the code
under test loops forever in this configuration.

Signed-off-by: David Brown <david.brown@linaro.org>
diff --git a/sim/src/depends.rs b/sim/src/depends.rs
new file mode 100644
index 0000000..9036d8d
--- /dev/null
+++ b/sim/src/depends.rs
@@ -0,0 +1,133 @@
+//! Support and tests related to the dependency management for multi-image
+//! support.
+
+use crate::image::ImageVersion;
+
+pub trait Depender {
+    /// Generate a version for this particular image.  The slot indicates
+    /// which slot this is being put in.
+    fn my_version(&self, offset: usize, slot: usize) -> ImageVersion;
+
+    /// Return dependencies for this image/slot combination.
+    fn my_deps(&self, offset: usize, slot: usize) -> Vec<ImageVersion>;
+
+    /// Return the image ID of the other version.
+    fn other_id(&self) -> u8;
+}
+
+/// A boring image is used when we aren't testing dependencies.  There will
+/// be meaningful version numbers.  The size field is the image number we
+/// are.
+pub struct BoringDep(pub usize);
+
+impl Depender for BoringDep {
+    fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
+        ImageVersion::new_synthetic(self.0 as u8, slot as u8, 0)
+    }
+
+    fn my_deps(&self, _offset: usize, _slot: usize) -> Vec<ImageVersion> {
+        vec![]
+    }
+
+    fn other_id(&self) -> u8 {
+        0
+    }
+}
+
+/// An individual test of the dependency mechanism describes one of the
+/// possibilities for the dependency information for each image, and what
+/// the expected outcome is.
+#[derive(Clone, Debug)]
+pub struct DepTest {
+    /// What kinds of dependency should be installed in the image.
+    pub depends: [DepType; 2],
+
+    /// What is the expected outcome of the upgrade.
+    pub upgrades: [UpgradeInfo; 2],
+}
+
+/// Describes the various types of dependency information that can be
+/// provided.
+#[derive(Clone, Debug)]
+pub enum DepType {
+    /// Do not include dependency information
+    Nothing,
+    /// Provide dependency information that matches the other image.
+    Correct,
+    /// Provide dependency information describing something newer than the
+    /// other image.
+    Newer,
+}
+
+/// Describes what our expectation is for an upgrade.
+#[derive(Clone, Debug)]
+pub enum UpgradeInfo {
+    /// The current version should be held.
+    Held,
+    /// The image should be upgraded
+    Upgraded,
+}
+
+/// A "test" that gives no dependency information.
+pub static NO_DEPS: DepTest = DepTest {
+    depends: [DepType::Nothing, DepType::Nothing],
+    upgrades: [UpgradeInfo::Upgraded, UpgradeInfo::Upgraded],
+};
+
+/// A PairDep describes the dependencies between two pairs.
+pub struct PairDep {
+    /// The image number of this image.
+    number: usize,
+
+    test: DepTest,
+}
+
+impl PairDep {
+    pub fn new(total_image: usize, my_image: usize, deps: &DepTest) -> PairDep {
+        if total_image != 2 {
+            panic!("PairDep only works when there are two images");
+        }
+
+        PairDep {
+            number: my_image,
+            test: deps.clone(),
+        }
+    }
+}
+
+impl Depender for PairDep {
+    fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
+        ImageVersion::new_synthetic(self.number as u8, slot as u8, 0)
+    }
+
+    fn my_deps(&self, _offset: usize, slot: usize) -> Vec<ImageVersion> {
+        match self.test.depends[slot] {
+            DepType::Nothing => vec![],
+            DepType::Correct => vec![
+                ImageVersion::new_synthetic(self.other_id(), slot as u8, 0)
+            ],
+            DepType::Newer => vec![
+                ImageVersion::new_synthetic(self.other_id(), slot as u8, 1)
+            ],
+        }
+    }
+
+    fn other_id(&self) -> u8 {
+        (1 - self.number) as u8
+    }
+}
+
+impl ImageVersion {
+    /// Generate an image version based on some key information.  The image
+    /// number influences the major version number (by an arbitrary factor),
+    /// and the slot affects the major number on the build_number.  The minor
+    /// number can also be given to force numbers to be different.
+    fn new_synthetic(image_id: u8, slot: u8, minor: u8) -> ImageVersion {
+        ImageVersion {
+            major: image_id * 20 + slot,
+            minor: minor,
+            revision: 1,
+            build_num: slot as u32,
+        }
+    }
+}