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,
+ }
+ }
+}