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>(
39 &mut self,
40 ledger: &mut ResourceLedger<C>,
41 result: &TransactionResult<C>,
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_failed<C: Clone>(
102 &mut self,
103 ledger: &mut ResourceLedger<C>,
104 resource_key: ResourceKey,
105 scope: ScopeId,
106 command_revision: Revision,
107 reason: impl Into<String>,
108 ) -> FakeHostEvent {
109 self.observe_outcome(
110 ledger,
111 resource_key,
112 scope,
113 command_revision,
114 HostResourceOutcome::Failed(reason.into()),
115 )
116 }
117
118 pub fn close_succeeded<C: Clone>(
120 &mut self,
121 ledger: &mut ResourceLedger<C>,
122 resource_key: ResourceKey,
123 scope: ScopeId,
124 command_revision: Revision,
125 ) -> FakeHostEvent {
126 self.observe_outcome(
127 ledger,
128 resource_key,
129 scope,
130 command_revision,
131 HostResourceOutcome::Closed,
132 )
133 }
134
135 pub fn close_failed<C: Clone>(
137 &mut self,
138 ledger: &mut ResourceLedger<C>,
139 resource_key: ResourceKey,
140 scope: ScopeId,
141 command_revision: Revision,
142 reason: impl Into<String>,
143 ) -> FakeHostEvent {
144 self.observe_outcome(
145 ledger,
146 resource_key,
147 scope,
148 command_revision,
149 HostResourceOutcome::Failed(reason.into()),
150 )
151 }
152
153 pub fn resource_lost<C: Clone>(
155 &mut self,
156 ledger: &mut ResourceLedger<C>,
157 resource_key: ResourceKey,
158 scope: ScopeId,
159 command_revision: Revision,
160 reason: impl Into<String>,
161 ) -> FakeHostEvent {
162 self.observe_outcome(
163 ledger,
164 resource_key,
165 scope,
166 command_revision,
167 HostResourceOutcome::Failed(reason.into()),
168 )
169 }
170
171 pub fn duplicate_status<C: Clone>(
173 &mut self,
174 ledger: &mut ResourceLedger<C>,
175 event: &FakeHostEvent,
176 ) -> FakeHostEvent {
177 let status = event.status.clone();
178 let class = ledger.classify_status(status.clone());
179 FakeHostEvent { status, class }
180 }
181
182 fn status_for_command<C: Clone>(
183 &mut self,
184 ledger: &mut ResourceLedger<C>,
185 command: &ResourceCommand<C>,
186 revision: Revision,
187 ) -> FakeHostEvent {
188 match command {
189 ResourceCommand::Open { key, scope, .. }
190 | ResourceCommand::Replace { key, scope, .. }
191 | ResourceCommand::Refresh { key, scope, .. } => {
192 self.open_succeeded(ledger, key.clone(), *scope, revision)
193 }
194 ResourceCommand::Close { key, scope } => {
195 self.close_succeeded(ledger, key.clone(), *scope, revision)
196 }
197 }
198 }
199
200 fn next_revision(&mut self) -> Revision {
201 let revision = Revision::new(self.next_status_revision);
202 self.next_status_revision += 1;
203 revision
204 }
205}
206
207impl Default for FakeHost {
208 fn default() -> Self {
209 Self::new()
210 }
211}