@@ -293,8 +293,8 @@ func TestUnsafeRefresh(t *testing.T) {
293293 for _ , role := range metadata .TOP_LEVEL_ROLE_NAMES {
294294 var version int
295295 if role == metadata .ROOT {
296- // The root file is written when the updater is
297- // created, so the version is reset .
296+ // The root file on disk is version 1 ( written when updater was created).
297+ // Unsafe mode doesn't persist to disk, it only loads from disk .
298298 version = 1
299299 }
300300 assertContentEquals (t , role , & version )
@@ -303,12 +303,58 @@ func TestUnsafeRefresh(t *testing.T) {
303303 assert .Equal (t , metadata .ROOT , updater .trusted .Root .Signed .Type )
304304 assert .Equal (t , metadata .SPECIFICATION_VERSION , updater .trusted .Root .Signed .SpecVersion )
305305 assert .True (t , updater .trusted .Root .Signed .ConsistentSnapshot )
306- assert .Equal (t , int64 (1 ), updater .trusted .Root .Signed .Version )
306+ // However, the in-memory trusted root should be version 2 after loading from disk
307+ assert .Equal (t , int64 (2 ), updater .trusted .Root .Signed .Version )
307308 assert .NotNil (t , updater .trusted .Snapshot )
308309 assert .NotNil (t , updater .trusted .Timestamp )
309310 assert .Equal (t , 1 , len (updater .trusted .Targets ))
310311}
311312
313+ func TestUnsafeRefreshWithRotatedRoots (t * testing.T ) {
314+ // First run a "real" refresh to establish initial metadata
315+ err := loadOrResetTrustedRootMetadata ()
316+ assert .NoError (t , err )
317+
318+ updaterConfig , err := loadUpdaterConfig ()
319+ assert .NoError (t , err )
320+ _ , err = runRefresh (updaterConfig , time .Now ())
321+ assert .NoError (t , err )
322+ assertFilesExist (t , metadata .TOP_LEVEL_ROLE_NAMES [:])
323+
324+ // Bump root version without changing keys (simpler test case)
325+ // This tests if unsafe mode can handle multiple root versions on disk
326+ simulator .Sim .MDRoot .Signed .Version = 2
327+ simulator .Sim .PublishRoot ()
328+
329+ simulator .Sim .MDRoot .Signed .Version = 3
330+ simulator .Sim .PublishRoot ()
331+
332+ // Run another refresh in online mode to download the new root versions
333+ // This ensures root.2.json and root.3.json are in the local cache
334+ updaterConfig , err = loadUpdaterConfig ()
335+ assert .NoError (t , err )
336+ onlineUpdater , err := runRefresh (updaterConfig , time .Now ())
337+ assert .NoError (t , err )
338+ assert .Equal (t , int64 (3 ), onlineUpdater .trusted .Root .Signed .Version )
339+
340+ // Now create a new unsafe updater with the original trusted root (version 1)
341+ // and verify it loads the rotated roots from disk
342+ updaterConfig , err = loadUnsafeUpdaterConfig ()
343+ assert .NoError (t , err )
344+ unsafeUpdater , err := runRefresh (updaterConfig , time .Now ())
345+ assert .NoError (t , err )
346+
347+ // The key assertion: unsafe mode should load rotated roots from disk
348+ // and end up with the latest root version
349+ assert .Equal (t , int64 (3 ), unsafeUpdater .trusted .Root .Signed .Version ,
350+ "Unsafe local mode should load rotated roots from disk" )
351+
352+ // Verify the other metadata is properly loaded
353+ assert .NotNil (t , unsafeUpdater .trusted .Timestamp )
354+ assert .NotNil (t , unsafeUpdater .trusted .Snapshot )
355+ assert .Equal (t , 1 , len (unsafeUpdater .trusted .Targets ))
356+ }
357+
312358func TestTrustedRootMissing (t * testing.T ) {
313359 err := loadOrResetTrustedRootMetadata ()
314360 assert .NoError (t , err )
0 commit comments