7
7
//!
8
8
//! The `Snapshot` API manages serialization and deserialization of collections of objects
9
9
//! that implement the `Versionize` trait. Each object is stored in a separate section
10
- //! that can be save /loaded independently:
10
+ //! that can be saved /loaded independently:
11
11
//!
12
12
//! |----------------------------|
13
13
//! | 64 bit magic_id |
25
25
//! | optional CRC64 |
26
26
//! |----------------------------|
27
27
//!
28
- //! Each structure, union or enum is versioned separately and only need to increment their version
28
+ //! Each structure, union or enum is versioned separately and only needs to increment their version
29
29
//! if a field is added or removed. For each state snapshot we define 2 versions:
30
30
//! - **the format version** which refers to the SnapshotHdr, Section headers, CRC, or the
31
- //! representation of primitives types (currentl we use serde bincode as a backend). The current
31
+ //! representation of primitives types (currently we use serde bincode as a backend). The current
32
32
//! implementation does not have any logic dependent on it.
33
33
//! - **the data version** which refers to the state stored in all of the snapshot sections.
34
34
//!
@@ -340,6 +340,80 @@ mod tests {
340
340
}
341
341
}
342
342
343
+ #[ test]
344
+ fn test_get_format_version_x86 ( ) {
345
+ // Check if `get_format_version()` returns indeed the format
346
+ // version (the least significant 2 bytes) if the id is valid
347
+ // (the other bytes == BASE_MAGIC_ID).
348
+ #[ cfg( target_arch = "x86_64" ) ]
349
+ let good_magic_id = 0x0710_1984_8664_0001u64 ;
350
+ #[ cfg( target_arch = "aarch64" ) ]
351
+ let good_magic_id = 0x0710_1984_AAAA_0001u64 ;
352
+
353
+ assert_eq ! ( get_format_version( good_magic_id) . unwrap( ) , 1u16 ) ;
354
+
355
+ // Flip a bit to invalidate the arch id.
356
+ let invalid_magic_id = good_magic_id | ( 1u64 << 63 ) ;
357
+ assert_eq ! (
358
+ get_format_version( invalid_magic_id) . unwrap_err( ) ,
359
+ Error :: InvalidMagic ( invalid_magic_id)
360
+ ) ;
361
+ }
362
+
363
+ #[ test]
364
+ fn test_section_ops ( ) {
365
+ let vm = VersionMap :: new ( ) ;
366
+ let state = Test {
367
+ field0 : 0 ,
368
+ field1 : 1 ,
369
+ field2 : 2 ,
370
+ field3 : "test" . to_owned ( ) ,
371
+ field4 : vec ! [ 4 , 3 , 2 , 1 ] ,
372
+ field_x : 0 ,
373
+ } ;
374
+
375
+ let mut snapshot_mem = vec ! [ 0u8 ; 1024 ] ;
376
+
377
+ // Serialize as v1.
378
+ let mut snapshot = Snapshot :: new ( vm. clone ( ) , 1 ) ;
379
+ snapshot. write_section ( "test" , & state) . unwrap ( ) ;
380
+ snapshot. save ( & mut snapshot_mem. as_mut_slice ( ) ) . unwrap ( ) ;
381
+
382
+ let mut sections = & mut snapshot. sections ;
383
+ assert_eq ! ( sections. len( ) , 1 ) ;
384
+
385
+ let section = sections. get_mut ( "test" ) . unwrap ( ) ;
386
+ assert_eq ! ( section. name, "test" ) ;
387
+ // Data should contain field_x (8 bytes), field0 (8 bytes) and field1 (4 bytes) in this order.
388
+ // field_x == 1 because of the semantic serializer fn for field3, the semantic serializer fn
389
+ // for field4 will set field0 to field4.iter().sum() = 10 and field1 == 1 (the original value).
390
+ assert_eq ! (
391
+ section. data,
392
+ [ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 10 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 ]
393
+ ) ;
394
+
395
+ let state_1 = Test1 {
396
+ field_x : 0 ,
397
+ field0 : 0 ,
398
+ field1 : 1 ,
399
+ } ;
400
+
401
+ snapshot. write_section ( "test1" , & state_1) . unwrap ( ) ;
402
+ snapshot. save ( & mut snapshot_mem. as_mut_slice ( ) ) . unwrap ( ) ;
403
+ sections = & mut snapshot. sections ;
404
+ assert_eq ! ( sections. len( ) , 2 ) ;
405
+
406
+ // Trying to read a section with an invalid name should fail.
407
+ assert_eq ! (
408
+ snapshot. read_section:: <Test >( "test2" ) . unwrap_err( ) ,
409
+ Error :: SectionNotFound
410
+ ) ;
411
+
412
+ // Validate that the 2 inserted objects can be deserialized.
413
+ assert ! ( snapshot. read_section:: <Test >( "test" ) . is_ok( ) ) ;
414
+ assert ! ( snapshot. read_section:: <Test1 >( "test1" ) . is_ok( ) ) ;
415
+ }
416
+
343
417
#[ test]
344
418
fn test_struct_semantic_fn ( ) {
345
419
let mut vm = VersionMap :: new ( ) ;
@@ -370,8 +444,14 @@ mod tests {
370
444
371
445
// The semantic serializer fn for field4 will set field0 to field4.iter().sum() == 10.
372
446
assert_eq ! ( restored_state. field0, state. field4. iter( ) . sum:: <u64 >( ) ) ;
447
+ // The semantic deserializer for field4 will change field's value to vec![field0; 4].
373
448
assert_eq ! ( restored_state. field4, vec![ restored_state. field0; 4 ] ) ;
449
+ // The semantic serializer and deserializer for field3 will both increment field_x value.
374
450
assert_eq ! ( restored_state. field_x, 2 ) ;
451
+ // field1 should have the original value.
452
+ assert_eq ! ( restored_state. field1, 1 ) ;
453
+ // field2 should have the default value as this field was added at version 2.
454
+ assert_eq ! ( restored_state. field2, 20 ) ;
375
455
376
456
// Serialize as v3.
377
457
let mut snapshot = Snapshot :: new ( vm. clone ( ) , 3 ) ;
@@ -381,10 +461,13 @@ mod tests {
381
461
snapshot = Snapshot :: load ( & mut snapshot_mem. as_slice ( ) , vm. clone ( ) ) . unwrap ( ) ;
382
462
restored_state = snapshot. read_section :: < Test > ( "test" ) . unwrap ( ) ;
383
463
384
- // The semantic fn for field4 will set field0 to field4.iter().sum() == 10.
464
+ // We expect only the semantic serializer and deserializer for field4 to be called at version 3.
465
+ // The semantic serializer will set field0 to field4.iter().sum() == 10.
385
466
assert_eq ! ( restored_state. field0, state. field4. iter( ) . sum:: <u64 >( ) ) ;
386
- // The semantic deserializer fn will create 4 element vec with all values == field0
467
+ // The semantic deserializer will create a 4 elements vec with all values == field0.
387
468
assert_eq ! ( restored_state. field4, vec![ restored_state. field0; 4 ] ) ;
469
+ // The semantic fn for field3 must not be called at version 3.
470
+ assert_eq ! ( restored_state. field_x, 0 ) ;
388
471
389
472
// Serialize as v4.
390
473
let mut snapshot = Snapshot :: new ( vm. clone ( ) , 4 ) ;
@@ -394,7 +477,7 @@ mod tests {
394
477
snapshot = Snapshot :: load ( & mut snapshot_mem. as_slice ( ) , vm. clone ( ) ) . unwrap ( ) ;
395
478
restored_state = snapshot. read_section :: < Test > ( "test" ) . unwrap ( ) ;
396
479
397
- // The semantic fn must not be called.
480
+ // The 4 semantic fns must not be called at version 4 .
398
481
assert_eq ! ( restored_state. field0, 0 ) ;
399
482
assert_eq ! ( restored_state. field4, vec![ 4 , 3 , 2 , 1 ] ) ;
400
483
}
@@ -419,7 +502,7 @@ mod tests {
419
502
} ;
420
503
421
504
let mut snapshot = Snapshot :: new ( vm. clone ( ) , 4 ) ;
422
- // The section will succesfully be serialized.
505
+ // The section will successfully be serialized.
423
506
assert ! ( snapshot. write_section( "test" , & state) . is_ok( ) ) ;
424
507
425
508
snapshot = Snapshot :: new ( vm. clone ( ) , 1 ) ;
@@ -452,7 +535,7 @@ mod tests {
452
535
let mut snapshot_mem = vec ! [ 0u8 ; 1024 ] ;
453
536
454
537
let mut snapshot = Snapshot :: new ( vm. clone ( ) , 2 ) ;
455
- // The section will succesfully be serialized.
538
+ // The section will successfully be serialized.
456
539
assert ! ( snapshot. write_section( "test" , & state) . is_ok( ) ) ;
457
540
assert_eq ! ( snapshot. save( & mut snapshot_mem. as_mut_slice( ) ) , Ok ( ( ) ) ) ;
458
541
@@ -478,8 +561,9 @@ mod tests {
478
561
479
562
// Serialize as v1.
480
563
let mut snapshot = Snapshot :: new ( vm. clone ( ) , 1 ) ;
481
- // The section will succesfully be serialized.
564
+ // The section will successfully be serialized.
482
565
assert ! ( snapshot. write_section( "test" , & state_1) . is_ok( ) ) ;
566
+ // Saving the snapshot will fail due to the small size of `snapshot_mem` vec.
483
567
assert_eq ! (
484
568
snapshot. save( & mut snapshot_mem. as_mut_slice( ) ) . unwrap_err( ) ,
485
569
Error :: Serialize (
@@ -502,7 +586,7 @@ mod tests {
502
586
503
587
// Serialize as v1.
504
588
let mut snapshot = Snapshot :: new ( vm. clone ( ) , 1 ) ;
505
- // The section will succesfully be serialized.
589
+ // The section will successfully be serialized.
506
590
snapshot. write_section ( "test" , & state_1) . unwrap ( ) ;
507
591
snapshot
508
592
. save_with_crc64 ( & mut snapshot_mem. as_mut_slice ( ) )
@@ -523,7 +607,7 @@ mod tests {
523
607
524
608
// Serialize as v1.
525
609
let mut snapshot = Snapshot :: new ( vm. clone ( ) , 1 ) ;
526
- // The section will succesfully be serialized.
610
+ // The section will successfully be serialized.
527
611
snapshot. write_section ( "test" , & state_1) . unwrap ( ) ;
528
612
snapshot
529
613
. save_with_crc64 ( & mut snapshot_mem. as_mut_slice ( ) )
@@ -562,10 +646,12 @@ mod tests {
562
646
let mut snapshot_mem = vec ! [ 0u8 ; 1024 ] ;
563
647
564
648
let mut snapshot = Snapshot :: new ( vm. clone ( ) , 4 ) ;
565
- // The section will succesfully be serialized.
649
+ // The section will successfully be serialized.
566
650
assert ! ( snapshot. write_section( "test" , & state) . is_ok( ) ) ;
567
651
assert_eq ! ( snapshot. save( & mut snapshot_mem. as_mut_slice( ) ) , Ok ( ( ) ) ) ;
568
652
653
+ // Load operation should fail if we don't use the whole `snapshot_mem` resulted from
654
+ // serialization.
569
655
snapshot_mem. truncate ( 10 ) ;
570
656
let snapshot_load_error =
571
657
Snapshot :: load ( & mut snapshot_mem. as_slice ( ) , vm. clone ( ) ) . unwrap_err ( ) ;
@@ -714,7 +800,6 @@ mod tests {
714
800
715
801
snapshot = Snapshot :: load ( & mut snapshot_mem. as_slice ( ) , vm. clone ( ) ) . unwrap ( ) ;
716
802
let restored_state = snapshot. read_section :: < kvm_pit_config > ( "test" ) . unwrap ( ) ;
717
- println ! ( "State: {:?}" , restored_state) ;
718
803
// Check if we serialized x correctly, that is if semantic_x() was called.
719
804
assert_eq ! ( restored_state, state) ;
720
805
}
@@ -723,7 +808,7 @@ mod tests {
723
808
fn test_basic_add_remove_field ( ) {
724
809
#[ rustfmt:: skip]
725
810
let basic_add_remove_field_v1: & [ u8 ] = & [
726
- 0x01 , 0x00 ,
811
+ 0x01 , 0x00 ,
727
812
#[ cfg( target_arch = "aarch64" ) ]
728
813
0xAA ,
729
814
#[ cfg( target_arch = "aarch64" ) ]
@@ -742,7 +827,7 @@ mod tests {
742
827
let basic_add_remove_field_v2: & [ u8 ] = & [
743
828
0x01 , 0x00 ,
744
829
#[ cfg( target_arch = "aarch64" ) ]
745
- 0xAA ,
830
+ 0xAA ,
746
831
#[ cfg( target_arch = "aarch64" ) ]
747
832
0xAA ,
748
833
#[ cfg( target_arch = "x86_64" ) ]
@@ -758,9 +843,9 @@ mod tests {
758
843
759
844
#[ rustfmt:: skip]
760
845
let basic_add_remove_field_v3: & [ u8 ] = & [
761
- 0x01 , 0x00 ,
846
+ 0x01 , 0x00 ,
762
847
#[ cfg( target_arch = "aarch64" ) ]
763
- 0xAA ,
848
+ 0xAA ,
764
849
#[ cfg( target_arch = "aarch64" ) ]
765
850
0xAA ,
766
851
#[ cfg( target_arch = "x86_64" ) ]
@@ -823,27 +908,24 @@ mod tests {
823
908
824
909
let mut snapshot = Snapshot :: load ( & mut snapshot_blob, vm. clone ( ) ) . unwrap ( ) ;
825
910
let mut restored_state = snapshot. read_section :: < B > ( "test" ) . unwrap ( ) ;
826
- println ! ( "State: {:?}" , restored_state) ;
827
911
// Check if we serialized x correctly, that is if semantic_x() was called.
828
912
assert_eq ! ( restored_state. a. x, 1234 ) ;
829
913
assert_eq ! ( restored_state. a. z, stringify!( whatever) ) ;
830
914
831
915
snapshot_blob = basic_add_remove_field_v2;
832
916
snapshot = Snapshot :: load ( & mut snapshot_blob, vm. clone ( ) ) . unwrap ( ) ;
833
917
restored_state = snapshot. read_section :: < B > ( "test" ) . unwrap ( ) ;
834
- println ! ( "State: {:?}" , restored_state) ;
835
918
// Check if x was not serialized, it should be 0.
836
919
assert_eq ! ( restored_state. a. x, 0 ) ;
837
- // z field was added in version to , make sure it contains the original value
920
+ // z field was added in version 2 , make sure it contains the original value.
838
921
assert_eq ! ( restored_state. a. z, stringify!( basic) ) ;
839
922
840
923
snapshot_blob = basic_add_remove_field_v3;
841
924
snapshot = Snapshot :: load ( & mut snapshot_blob, vm. clone ( ) ) . unwrap ( ) ;
842
925
restored_state = snapshot. read_section :: < B > ( "test" ) . unwrap ( ) ;
843
- println ! ( "State: {:?}" , restored_state) ;
844
926
// Check if x was not serialized, it should be 0.
845
927
assert_eq ! ( restored_state. a. x, 0 ) ;
846
- // z field was added in version to , make sure it contains the original value
928
+ // z field was added in version 2 , make sure it contains the original value.
847
929
assert_eq ! ( restored_state. a. z, stringify!( basic) ) ;
848
930
assert_eq ! ( restored_state. a. q, 1234 ) ;
849
931
}
0 commit comments