@@ -20,9 +20,10 @@ use alloc::vec::Vec;
20
20
use pb:: response:: Response ;
21
21
22
22
use crate :: backup;
23
- use crate :: workflow:: { confirm, status , unlock } ;
23
+ use crate :: workflow:: { confirm, unlock , Workflows } ;
24
24
25
- pub async fn check (
25
+ pub async fn check < W : Workflows > (
26
+ workflows : & mut W ,
26
27
& pb:: CheckBackupRequest { silent } : & pb:: CheckBackupRequest ,
27
28
) -> Result < Response , Error > {
28
29
if !bitbox02:: sd:: sdcard_inserted ( ) {
@@ -34,29 +35,31 @@ pub async fn check(
34
35
let ( backup_data, metadata) = backup:: load ( & id) ?;
35
36
if seed. as_slice ( ) != backup_data. get_seed ( ) {
36
37
if !silent {
37
- status :: status ( "Backup missing\n or invalid" , false ) . await ;
38
+ workflows . status ( "Backup missing\n or invalid" , false ) . await ;
38
39
}
39
40
return Err ( Error :: Generic ) ;
40
41
}
41
42
if !silent {
42
- confirm:: confirm ( & confirm:: Params {
43
- title : "Name?" ,
44
- body : & metadata. name ,
45
- scrollable : true ,
46
- accept_is_nextarrow : true ,
47
- ..Default :: default ( )
48
- } )
49
- . await ?;
43
+ workflows
44
+ . confirm ( & confirm:: Params {
45
+ title : "Name?" ,
46
+ body : & metadata. name ,
47
+ scrollable : true ,
48
+ accept_is_nextarrow : true ,
49
+ ..Default :: default ( )
50
+ } )
51
+ . await ?;
50
52
51
- confirm:: confirm ( & confirm:: Params {
52
- title : "ID?" ,
53
- body : & id,
54
- scrollable : true ,
55
- ..Default :: default ( )
56
- } )
57
- . await ?;
53
+ workflows
54
+ . confirm ( & confirm:: Params {
55
+ title : "ID?" ,
56
+ body : & id,
57
+ scrollable : true ,
58
+ ..Default :: default ( )
59
+ } )
60
+ . await ?;
58
61
59
- status :: status ( "Backup valid" , true ) . await ;
62
+ workflows . status ( "Backup valid" , true ) . await ;
60
63
}
61
64
Ok ( Response :: CheckBackup ( pb:: CheckBackupResponse { id } ) )
62
65
}
@@ -69,19 +72,21 @@ pub async fn check(
69
72
/// If the device is initialized, an existing backup is overwritten, but the seed birthdate is
70
73
/// retained from the previous backup. If no backup existed, the seed birthdate is set to 0, meaning
71
74
/// it is unknown.
72
- pub async fn create (
75
+ pub async fn create < W : Workflows > (
76
+ workflows : & mut W ,
73
77
& pb:: CreateBackupRequest {
74
78
timestamp,
75
79
timezone_offset,
76
80
} : & pb:: CreateBackupRequest ,
77
81
) -> Result < Response , Error > {
78
- confirm:: confirm ( & confirm:: Params {
79
- title : "Is today?" ,
80
- body : & bitbox02:: format_datetime ( timestamp, timezone_offset, true )
81
- . map_err ( |_| Error :: InvalidInput ) ?,
82
- ..Default :: default ( )
83
- } )
84
- . await ?;
82
+ workflows
83
+ . confirm ( & confirm:: Params {
84
+ title : "Is today?" ,
85
+ body : & bitbox02:: format_datetime ( timestamp, timezone_offset, true )
86
+ . map_err ( |_| Error :: InvalidInput ) ?,
87
+ ..Default :: default ( )
88
+ } )
89
+ . await ?;
85
90
86
91
// Wait for sd card
87
92
super :: sdcard:: process ( & pb:: InsertRemoveSdCardRequest {
@@ -92,7 +97,7 @@ pub async fn create(
92
97
let is_initialized = bitbox02:: memory:: is_initialized ( ) ;
93
98
94
99
if is_initialized {
95
- unlock:: unlock_keystore ( "Unlock device" , unlock:: CanCancel :: Yes ) . await ?;
100
+ unlock:: unlock_keystore ( workflows , "Unlock device" , unlock:: CanCancel :: Yes ) . await ?;
96
101
}
97
102
98
103
let seed = bitbox02:: keystore:: copy_seed ( ) ?;
@@ -122,12 +127,12 @@ pub async fn create(
122
127
// process again.
123
128
let _ = bitbox02:: memory:: set_initialized ( ) ;
124
129
125
- status :: status ( "Backup created" , true ) . await ;
130
+ workflows . status ( "Backup created" , true ) . await ;
126
131
Ok ( Response :: Success ( pb:: Success { } ) )
127
132
}
128
133
Err ( err) => {
129
134
let msg = format ! ( "Backup not created\n Please contact\n support ({:?})" , err) ;
130
- status :: status ( & msg, false ) . await ;
135
+ workflows . status ( & msg, false ) . await ;
131
136
Err ( Error :: Generic )
132
137
}
133
138
}
@@ -154,6 +159,7 @@ mod tests {
154
159
use super :: * ;
155
160
156
161
use crate :: bb02_async:: block_on;
162
+ use crate :: workflow:: testing:: { Screen , TestingWorkflows } ;
157
163
use alloc:: boxed:: Box ;
158
164
use bitbox02:: testing:: {
159
165
mock, mock_memory, mock_sd, mock_unlocked, mock_unlocked_using_mnemonic, Data ,
@@ -167,26 +173,44 @@ mod tests {
167
173
// All good.
168
174
mock ( Data {
169
175
sdcard_inserted : Some ( true ) ,
170
- ui_confirm_create : Some ( Box :: new ( |params| {
171
- assert_eq ! ( params. body, "Mon 2020-09-28" ) ;
172
- true
173
- } ) ) ,
174
176
..Default :: default ( )
175
177
} ) ;
176
178
mock_sd ( ) ;
177
179
mock_memory ( ) ;
178
180
mock_unlocked ( ) ;
181
+
182
+ let mut mock_workflows = TestingWorkflows :: new ( ) ;
179
183
assert_eq ! (
180
- block_on( create( & pb:: CreateBackupRequest {
181
- timestamp: EXPECTED_TIMESTMAP ,
182
- timezone_offset: 18000 ,
183
- } ) ) ,
184
+ block_on( create(
185
+ & mut mock_workflows,
186
+ & pb:: CreateBackupRequest {
187
+ timestamp: EXPECTED_TIMESTMAP ,
188
+ timezone_offset: 18000 ,
189
+ }
190
+ ) ) ,
184
191
Ok ( Response :: Success ( pb:: Success { } ) )
185
192
) ;
186
193
assert_eq ! ( EXPECTED_TIMESTMAP , bitbox02:: memory:: get_seed_birthdate( ) ) ;
194
+ assert_eq ! (
195
+ mock_workflows. screens,
196
+ vec![
197
+ Screen :: Confirm {
198
+ title: "Is today?" . into( ) ,
199
+ body: "Mon 2020-09-28" . into( ) ,
200
+ longtouch: false
201
+ } ,
202
+ Screen :: Status {
203
+ title: "Backup created" . into( ) ,
204
+ success: true
205
+ }
206
+ ]
207
+ ) ;
187
208
188
209
assert_eq ! (
189
- block_on( check( & pb:: CheckBackupRequest { silent: true } ) ) ,
210
+ block_on( check(
211
+ & mut TestingWorkflows :: new( ) ,
212
+ & pb:: CheckBackupRequest { silent: true }
213
+ ) ) ,
190
214
Ok ( Response :: CheckBackup ( pb:: CheckBackupResponse {
191
215
id: "41233dfbad010723dbbb93514b7b81016b73f8aa35c5148e1b478f60d5750dce" . into( )
192
216
} ) )
@@ -197,29 +221,10 @@ mod tests {
197
221
/// should catch regressions when changing backup loading/verification in the firmware code.
198
222
#[ test]
199
223
fn test_fixture ( ) {
200
- static mut UI_COUNTER : u32 = 0 ;
201
- static EXPECTED_ID : & str =
224
+ const EXPECTED_ID : & str =
202
225
"577782fdfffbe314b23acaeefc39ad5e8641fba7e7dbe418a35956a879a67dd2" ;
203
226
mock ( Data {
204
227
sdcard_inserted : Some ( true ) ,
205
- ui_confirm_create : Some ( Box :: new ( |params| {
206
- match unsafe {
207
- UI_COUNTER += 1 ;
208
- UI_COUNTER
209
- } {
210
- 1 => {
211
- assert_eq ! ( params. title, "Name?" ) ;
212
- assert_eq ! ( params. body, "My BitBox" ) ;
213
- true
214
- }
215
- 2 => {
216
- assert_eq ! ( params. title, "ID?" ) ;
217
- assert_eq ! ( params. body, EXPECTED_ID ) ;
218
- true
219
- }
220
- _ => panic ! ( "unexpected UI dialog" ) ,
221
- }
222
- } ) ) ,
223
228
..Default :: default ( )
224
229
} ) ;
225
230
mock_sd ( ) ;
@@ -241,13 +246,35 @@ mod tests {
241
246
. unwrap ( ) ;
242
247
}
243
248
// Check that the loaded seed matches the backup.
249
+ let mut mock_workflows = TestingWorkflows :: new ( ) ;
244
250
assert_eq ! (
245
- block_on( check( & pb:: CheckBackupRequest { silent: false } ) ) ,
251
+ block_on( check(
252
+ & mut mock_workflows,
253
+ & pb:: CheckBackupRequest { silent: false }
254
+ ) ) ,
246
255
Ok ( Response :: CheckBackup ( pb:: CheckBackupResponse {
247
256
id: EXPECTED_ID . into( )
248
257
} ) )
249
258
) ;
250
- assert_eq ! ( unsafe { UI_COUNTER } , 2 ) ;
259
+ assert_eq ! (
260
+ mock_workflows. screens,
261
+ vec![
262
+ Screen :: Confirm {
263
+ title: "Name?" . into( ) ,
264
+ body: "My BitBox" . into( ) ,
265
+ longtouch: false
266
+ } ,
267
+ Screen :: Confirm {
268
+ title: "ID?" . into( ) ,
269
+ body: EXPECTED_ID . into( ) ,
270
+ longtouch: false
271
+ } ,
272
+ Screen :: Status {
273
+ title: "Backup valid" . into( ) ,
274
+ success: true
275
+ } ,
276
+ ]
277
+ ) ;
251
278
}
252
279
253
280
#[ test]
@@ -270,17 +297,19 @@ mod tests {
270
297
// Create one backup.
271
298
mock ( Data {
272
299
sdcard_inserted : Some ( true ) ,
273
- ui_confirm_create : Some ( Box :: new ( |_params| true ) ) ,
274
300
..Default :: default ( )
275
301
} ) ;
276
302
mock_memory ( ) ;
277
303
mock_unlocked_using_mnemonic ( "purity concert above invest pigeon category peace tuition hazard vivid latin since legal speak nation session onion library travel spell region blast estate stay" , "" ) ;
278
304
279
305
bitbox02:: memory:: set_device_name ( DEVICE_NAME_1 ) . unwrap ( ) ;
280
- assert ! ( block_on( create( & pb:: CreateBackupRequest {
281
- timestamp: EXPECTED_TIMESTAMP ,
282
- timezone_offset: 18000 ,
283
- } ) )
306
+ assert ! ( block_on( create(
307
+ & mut TestingWorkflows :: new( ) ,
308
+ & pb:: CreateBackupRequest {
309
+ timestamp: EXPECTED_TIMESTAMP ,
310
+ timezone_offset: 18000 ,
311
+ }
312
+ ) )
284
313
. is_ok( ) ) ;
285
314
286
315
assert_eq ! (
@@ -297,16 +326,18 @@ mod tests {
297
326
// Create another backup.
298
327
mock ( Data {
299
328
sdcard_inserted : Some ( true ) ,
300
- ui_confirm_create : Some ( Box :: new ( |_params| true ) ) ,
301
329
..Default :: default ( )
302
330
} ) ;
303
331
mock_memory ( ) ;
304
332
mock_unlocked_using_mnemonic ( "goddess item rack improve shaft occur actress rib emerge salad rich blame model glare lounge stable electric height scrub scrub oyster now dinner oven" , "" ) ;
305
333
bitbox02:: memory:: set_device_name ( DEVICE_NAME_2 ) . unwrap ( ) ;
306
- assert ! ( block_on( create( & pb:: CreateBackupRequest {
307
- timestamp: EXPECTED_TIMESTAMP ,
308
- timezone_offset: 18000 ,
309
- } ) )
334
+ assert ! ( block_on( create(
335
+ & mut TestingWorkflows :: new( ) ,
336
+ & pb:: CreateBackupRequest {
337
+ timestamp: EXPECTED_TIMESTAMP ,
338
+ timezone_offset: 18000 ,
339
+ }
340
+ ) )
310
341
. is_ok( ) ) ;
311
342
312
343
assert_eq ! (
0 commit comments