1use trellis_core::{
2 HostResourceOutcome, ResourceCommand, ResourceKey, Revision, ScopeId, TransactionResult,
3};
4
5use crate::{HostStatusClass, HostStatusEvent, ResourceLedger};
6
7#[derive(Clone, Debug, Eq, PartialEq)]
9pub struct FakeHostEvent {
10 pub status: HostStatusEvent,
12 pub class: HostStatusClass,
14}
15
16impl FakeHostEvent {
17 pub fn into_status(self) -> HostStatusEvent {
19 self.status
20 }
21}
22
23#[derive(Clone, Debug, Eq, PartialEq)]
25pub struct FakeHost {
26 next_status_revision: u64,
27}
28
29impl FakeHost {
30 pub const fn new() -> Self {
32 Self {
33 next_status_revision: 1,
34 }
35 }
36
37 pub fn apply_result<C: Clone, O>(
39 &mut self,
40 ledger: &mut ResourceLedger<C>,
41 result: &TransactionResult<C, O>,
42 ) -> Vec<FakeHostEvent> {
43 ledger.apply_result(result);
44 result
45 .resource_plan
46 .commands()
47 .iter()
48 .map(|command| self.status_for_command(ledger, command, result.revision))
49 .collect()
50 }
51
52 pub fn observe<C: Clone>(
54 &mut self,
55 ledger: &mut ResourceLedger<C>,
56 resource_key: ResourceKey,
57 scope: ScopeId,
58 command_revision: Revision,
59 ) -> FakeHostEvent {
60 self.observe_outcome(
61 ledger,
62 resource_key,
63 scope,
64 command_revision,
65 HostResourceOutcome::Open,
66 )
67 }
68
69 pub fn observe_outcome<C: Clone>(
71 &mut self,
72 ledger: &mut ResourceLedger<C>,
73 resource_key: ResourceKey,
74 scope: ScopeId,
75 command_revision: Revision,
76 status: HostResourceOutcome,
77 ) -> FakeHostEvent {
78 let status = HostStatusEvent {
79 resource_key,
80 scope,
81 command_revision,
82 status_revision: self.next_revision(),
83 status,
84 };
85 let class = ledger.classify_status(status.clone());
86 FakeHostEvent { status, class }
87 }
88
89 pub fn open_succeeded<C: Clone>(
91 &mut self,
92 ledger: &mut ResourceLedger<C>,
93 resource_key: ResourceKey,
94 scope: ScopeId,
95 command_revision: Revision,
96 ) -> FakeHostEvent {
97 self.observe(ledger, resource_key, scope, command_revision)
98 }
99
100 pub fn open_succeeds_later<C: Clone>(
102 &mut self,
103 ledger: &mut ResourceLedger<C>,
104 resource_key: ResourceKey,
105 scope: ScopeId,
106 command_revision: Revision,
107 ) -> FakeHostEvent {
108 self.open_succeeded(ledger, resource_key, scope, command_revision)
109 }
110
111 pub fn open_failed<C: Clone>(
113 &mut self,
114 ledger: &mut ResourceLedger<C>,
115 resource_key: ResourceKey,
116 scope: ScopeId,
117 command_revision: Revision,
118 reason: impl Into<String>,
119 ) -> FakeHostEvent {
120 self.observe_outcome(
121 ledger,
122 resource_key,
123 scope,
124 command_revision,
125 HostResourceOutcome::Failed(reason.into()),
126 )
127 }
128
129 pub fn close_succeeded<C: Clone>(
131 &mut self,
132 ledger: &mut ResourceLedger<C>,
133 resource_key: ResourceKey,
134 scope: ScopeId,
135 command_revision: Revision,
136 ) -> FakeHostEvent {
137 self.observe_outcome(
138 ledger,
139 resource_key,
140 scope,
141 command_revision,
142 HostResourceOutcome::Closed,
143 )
144 }
145
146 pub fn close_failed<C: Clone>(
148 &mut self,
149 ledger: &mut ResourceLedger<C>,
150 resource_key: ResourceKey,
151 scope: ScopeId,
152 command_revision: Revision,
153 reason: impl Into<String>,
154 ) -> FakeHostEvent {
155 self.observe_outcome(
156 ledger,
157 resource_key,
158 scope,
159 command_revision,
160 HostResourceOutcome::Failed(reason.into()),
161 )
162 }
163
164 pub fn resource_lost<C: Clone>(
166 &mut self,
167 ledger: &mut ResourceLedger<C>,
168 resource_key: ResourceKey,
169 scope: ScopeId,
170 command_revision: Revision,
171 reason: impl Into<String>,
172 ) -> FakeHostEvent {
173 self.observe_outcome(
174 ledger,
175 resource_key,
176 scope,
177 command_revision,
178 HostResourceOutcome::Failed(reason.into()),
179 )
180 }
181
182 pub fn duplicate_status<C: Clone>(
184 &mut self,
185 ledger: &mut ResourceLedger<C>,
186 event: &FakeHostEvent,
187 ) -> FakeHostEvent {
188 let status = event.status.clone();
189 let class = ledger.classify_status(status.clone());
190 FakeHostEvent { status, class }
191 }
192
193 fn status_for_command<C: Clone>(
194 &mut self,
195 ledger: &mut ResourceLedger<C>,
196 command: &ResourceCommand<C>,
197 revision: Revision,
198 ) -> FakeHostEvent {
199 match command {
200 ResourceCommand::Open { key, scope, .. }
201 | ResourceCommand::Replace { key, scope, .. }
202 | ResourceCommand::Refresh { key, scope, .. } => {
203 self.open_succeeded(ledger, key.clone(), *scope, revision)
204 }
205 ResourceCommand::Close { key, scope } => {
206 self.close_succeeded(ledger, key.clone(), *scope, revision)
207 }
208 }
209 }
210
211 fn next_revision(&mut self) -> Revision {
212 let revision = Revision::new(self.next_status_revision);
213 self.next_status_revision += 1;
214 revision
215 }
216}
217
218impl Default for FakeHost {
219 fn default() -> Self {
220 Self::new()
221 }
222}