blob: eecee08eee502a4431223ccbc8147cd5f79e3cf1 [file] [log] [blame]
David Brownc3898d62019-08-05 14:20:02 -06001//! Support and tests related to the dependency management for multi-image
2//! support.
3
4use crate::image::ImageVersion;
5
6pub trait Depender {
7 /// Generate a version for this particular image. The slot indicates
8 /// which slot this is being put in.
9 fn my_version(&self, offset: usize, slot: usize) -> ImageVersion;
10
11 /// Return dependencies for this image/slot combination.
12 fn my_deps(&self, offset: usize, slot: usize) -> Vec<ImageVersion>;
13
14 /// Return the image ID of the other version.
15 fn other_id(&self) -> u8;
16}
17
18/// A boring image is used when we aren't testing dependencies. There will
19/// be meaningful version numbers. The size field is the image number we
20/// are.
21pub struct BoringDep(pub usize);
22
23impl Depender for BoringDep {
24 fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
25 ImageVersion::new_synthetic(self.0 as u8, slot as u8, 0)
26 }
27
28 fn my_deps(&self, _offset: usize, _slot: usize) -> Vec<ImageVersion> {
29 vec![]
30 }
31
32 fn other_id(&self) -> u8 {
33 0
34 }
35}
36
37/// An individual test of the dependency mechanism describes one of the
38/// possibilities for the dependency information for each image, and what
39/// the expected outcome is.
40#[derive(Clone, Debug)]
41pub struct DepTest {
42 /// What kinds of dependency should be installed in the image.
43 pub depends: [DepType; 2],
44
45 /// What is the expected outcome of the upgrade.
46 pub upgrades: [UpgradeInfo; 2],
47}
48
49/// Describes the various types of dependency information that can be
50/// provided.
51#[derive(Clone, Debug)]
52pub enum DepType {
53 /// Do not include dependency information
54 Nothing,
55 /// Provide dependency information that matches the other image.
56 Correct,
David Brown873be312019-09-03 12:22:32 -060057 /// Provide a dependency that matches the old version of the other
58 /// image.
59 OldCorrect,
David Brownc3898d62019-08-05 14:20:02 -060060 /// Provide dependency information describing something newer than the
61 /// other image.
62 Newer,
David Brown873be312019-09-03 12:22:32 -060063 /// Don't provide an upgrade image at all for this image
64 NoUpgrade,
David Brownc3898d62019-08-05 14:20:02 -060065}
66
67/// Describes what our expectation is for an upgrade.
David Brown207c4572019-09-03 12:21:05 -060068#[derive(Clone, Debug, PartialEq, Eq)]
David Brownc3898d62019-08-05 14:20:02 -060069pub enum UpgradeInfo {
70 /// The current version should be held.
71 Held,
72 /// The image should be upgraded
73 Upgraded,
74}
75
76/// A "test" that gives no dependency information.
77pub static NO_DEPS: DepTest = DepTest {
78 depends: [DepType::Nothing, DepType::Nothing],
79 upgrades: [UpgradeInfo::Upgraded, UpgradeInfo::Upgraded],
80};
81
82/// A PairDep describes the dependencies between two pairs.
83pub struct PairDep {
84 /// The image number of this image.
85 number: usize,
86
87 test: DepTest,
88}
89
90impl PairDep {
91 pub fn new(total_image: usize, my_image: usize, deps: &DepTest) -> PairDep {
92 if total_image != 2 {
93 panic!("PairDep only works when there are two images");
94 }
95
96 PairDep {
97 number: my_image,
98 test: deps.clone(),
99 }
100 }
101}
102
103impl Depender for PairDep {
104 fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
105 ImageVersion::new_synthetic(self.number as u8, slot as u8, 0)
106 }
107
108 fn my_deps(&self, _offset: usize, slot: usize) -> Vec<ImageVersion> {
David Brown873be312019-09-03 12:22:32 -0600109 // For now, don't put any dependencies in slot zero. They could be
110 // added here if we someday implement checking these.
111 if slot == 0 {
112 vec![]
113 } else {
114 match self.test.depends[self.number] {
115 DepType::Nothing => vec![],
116 DepType::NoUpgrade => panic!("Shouldn't get to this point"),
117 DepType::Correct => vec![
118 ImageVersion::new_synthetic(self.other_id(), slot as u8, 0)
119 ],
120 DepType::OldCorrect => vec![
121 ImageVersion::new_synthetic(self.other_id(), 0, 0)
122 ],
123 DepType::Newer => vec![
124 ImageVersion::new_synthetic(self.other_id(), slot as u8, 1)
125 ],
126 }
David Brownc3898d62019-08-05 14:20:02 -0600127 }
128 }
129
130 fn other_id(&self) -> u8 {
131 (1 - self.number) as u8
132 }
133}
134
135impl ImageVersion {
136 /// Generate an image version based on some key information. The image
137 /// number influences the major version number (by an arbitrary factor),
138 /// and the slot affects the major number on the build_number. The minor
139 /// number can also be given to force numbers to be different.
140 fn new_synthetic(image_id: u8, slot: u8, minor: u8) -> ImageVersion {
141 ImageVersion {
142 major: image_id * 20 + slot,
143 minor: minor,
144 revision: 1,
145 build_num: slot as u32,
146 }
147 }
148}