@@ -1223,7 +1223,33 @@ impl Message {
12231223 }
12241224}
12251225
1226+ #[ repr( C ) ]
1227+ #[ derive( Debug , Default , Versionize ) ]
1228+ struct Message2 {
1229+ pub len : u32 ,
1230+ #[ version( end = 4 ) ]
1231+ pub padding : u32 ,
1232+ pub value : u32 ,
1233+ #[ version( start = 2 , default_fn = "default_extra_value" ) ]
1234+ pub extra_value : u16 ,
1235+ #[ version( start = 3 , end = 4 , default_fn = "default_status" ) ]
1236+ pub status : Wrapping < bool > ,
1237+ pub entries : __IncompleteArrayField < u32 > ,
1238+ }
1239+
1240+ impl Message2 {
1241+ fn default_extra_value ( _source_version : u16 ) -> u16 {
1242+ 4
1243+ }
1244+
1245+ fn default_status ( _source_version : u16 ) -> Wrapping < bool > {
1246+ Wrapping ( false )
1247+ }
1248+ }
1249+
12261250generate_fam_struct_impl ! ( Message , u32 , entries, u32 , len, 100 ) ;
1251+ // Duplicated structure used but with max_len 1 - for negative testing.
1252+ generate_fam_struct_impl ! ( Message2 , u32 , entries, u32 , len, 1 ) ;
12271253
12281254#[ repr( C ) ]
12291255#[ derive( Default ) ]
@@ -1292,6 +1318,7 @@ impl<T> Versionize for __IncompleteArrayField<T> {
12921318}
12931319
12941320type MessageFamStructWrapper = FamStructWrapper < Message > ;
1321+ type Message2FamStructWrapper = FamStructWrapper < Message2 > ;
12951322
12961323#[ test]
12971324fn test_versionize_famstructwrapper ( ) {
@@ -1303,7 +1330,7 @@ fn test_versionize_famstructwrapper() {
13031330 . new_version ( )
13041331 . set_type_version ( Message :: type_id ( ) , 4 ) ;
13051332
1306- let mut state = MessageFamStructWrapper :: new ( 0 ) ;
1333+ let mut state = MessageFamStructWrapper :: new ( 0 ) . unwrap ( ) ;
13071334 state. as_mut_fam_struct ( ) . padding = 8 ;
13081335 state. as_mut_fam_struct ( ) . extra_value = 16 ;
13091336 state. as_mut_fam_struct ( ) . status = Wrapping ( true ) ;
@@ -1422,7 +1449,7 @@ pub struct FamStructTest {
14221449
14231450impl FamStructTest {
14241451 fn default_message ( _target_version : u16 ) -> Vec < MessageFamStructWrapper > {
1425- let mut f = MessageFamStructWrapper :: new ( 0 ) ;
1452+ let mut f = MessageFamStructWrapper :: new ( 0 ) . unwrap ( ) ;
14261453 f. as_mut_fam_struct ( ) . padding = 1 ;
14271454 f. as_mut_fam_struct ( ) . extra_value = 2 ;
14281455
@@ -1448,7 +1475,7 @@ impl FamStructTest {
14481475 // Fail if semantic deserialization is called for a version >= 2.
14491476 assert ! ( target_version < 2 ) ;
14501477
1451- let mut f = MessageFamStructWrapper :: new ( 0 ) ;
1478+ let mut f = MessageFamStructWrapper :: new ( 0 ) . unwrap ( ) ;
14521479 f. as_mut_fam_struct ( ) . padding = 3 ;
14531480 f. as_mut_fam_struct ( ) . extra_value = 4 ;
14541481
@@ -1472,12 +1499,12 @@ fn test_versionize_struct_with_famstructs() {
14721499
14731500 let mut snapshot_mem = vec ! [ 0u8 ; 1024 ] ;
14741501
1475- let mut f = MessageFamStructWrapper :: new ( 0 ) ;
1502+ let mut f = MessageFamStructWrapper :: new ( 0 ) . unwrap ( ) ;
14761503 f. as_mut_fam_struct ( ) . padding = 5 ;
14771504 f. as_mut_fam_struct ( ) . extra_value = 6 ;
14781505 f. push ( 10 ) . unwrap ( ) ;
14791506
1480- let mut f2 = MessageFamStructWrapper :: new ( 0 ) ;
1507+ let mut f2 = MessageFamStructWrapper :: new ( 0 ) . unwrap ( ) ;
14811508 f2. as_mut_fam_struct ( ) . padding = 7 ;
14821509 f2. as_mut_fam_struct ( ) . extra_value = 8 ;
14831510 f2. push ( 20 ) . unwrap ( ) ;
@@ -1556,12 +1583,30 @@ impl SomeStruct {
15561583 // Fail if semantic serialization is called for the latest version.
15571584 assert ! ( target_version < 2 ) ;
15581585 self . message . as_mut_fam_struct ( ) . padding += 2 ;
1586+
15591587 Ok ( ( ) )
15601588 }
15611589}
15621590
1563- // TODO: remove this test once FamStructWrapper `Clone` implementation gets fixed.
1564- // Tracking issue: https://github.com/rust-vmm/vmm-sys-util/issues/85.
1591+ #[ derive( Clone , Versionize ) ]
1592+ pub struct SomeStruct2 {
1593+ message : Message2FamStructWrapper ,
1594+ #[ version( start = 2 , ser_fn = "ser_u16" ) ]
1595+ some_u16 : u16 ,
1596+ }
1597+
1598+ impl SomeStruct2 {
1599+ fn ser_u16 ( & mut self , target_version : u16 ) -> VersionizeResult < ( ) > {
1600+ // Fail if semantic serialization is called for the latest version.
1601+ assert ! ( target_version < 2 ) ;
1602+ self . message . as_mut_fam_struct ( ) . padding += 2 ;
1603+
1604+ Ok ( ( ) )
1605+ }
1606+ }
1607+
1608+ // `Clone` issue fixed: https://github.com/rust-vmm/vmm-sys-util/issues/85.
1609+ // We are keeping this as regression test.
15651610#[ test]
15661611fn test_famstructwrapper_clone ( ) {
15671612 // Test that having a `FamStructWrapper<T>` in a structure that implements
@@ -1570,7 +1615,7 @@ fn test_famstructwrapper_clone() {
15701615 let mut vm = VersionMap :: new ( ) ;
15711616 vm. new_version ( ) . set_type_version ( SomeStruct :: type_id ( ) , 2 ) ;
15721617
1573- let mut f = MessageFamStructWrapper :: new ( 0 ) ;
1618+ let mut f = MessageFamStructWrapper :: new ( 0 ) . unwrap ( ) ;
15741619 f. as_mut_fam_struct ( ) . padding = 8 ;
15751620
15761621 f. push ( 1 ) . unwrap ( ) ;
@@ -1589,6 +1634,12 @@ fn test_famstructwrapper_clone() {
15891634 . unwrap ( ) ;
15901635 let mut restored_state =
15911636 <SomeStruct as Versionize >:: deserialize ( & mut snapshot_mem. as_slice ( ) , & vm, 1 ) . unwrap ( ) ;
1637+
1638+ // Negative scenario - FamStruct versionize impl fails due to SizeLimitExceeded.
1639+ assert ! (
1640+ <SomeStruct2 as Versionize >:: deserialize( & mut snapshot_mem. as_slice( ) , & vm, 1 ) . is_err( )
1641+ ) ;
1642+
15921643 let original_values = state. message . as_slice ( ) ;
15931644 let restored_values = restored_state. message . as_slice ( ) ;
15941645
@@ -1597,20 +1648,23 @@ fn test_famstructwrapper_clone() {
15971648 restored_state. message. as_fam_struct_ref( ) . padding
15981649 ) ;
15991650 assert_eq ! ( original_values, restored_values) ;
1600- // `padding` field will take the default value (0 ), and then it will be incremented with 2
1651+ // `padding` field will have its value serialized (8 ), and then it will be incremented with 2
16011652 // by `ser_u16`.
1602- assert_eq ! ( 2 , restored_state. message. as_fam_struct_ref( ) . padding) ;
1653+ assert_eq ! ( 10 , restored_state. message. as_fam_struct_ref( ) . padding) ;
16031654
16041655 // Serialize as v2.
16051656 state
16061657 . serialize ( & mut snapshot_mem. as_mut_slice ( ) , & vm, 2 )
16071658 . unwrap ( ) ;
16081659 restored_state =
16091660 <SomeStruct as Versionize >:: deserialize ( & mut snapshot_mem. as_slice ( ) , & vm, 2 ) . unwrap ( ) ;
1610- assert_ne ! (
1661+
1662+ // Padding is correctly preserved and ser_u16 is not called - it would fail due to ser_u16
1663+ // assert anyways, but we double that check here.
1664+ assert_eq ! (
16111665 state. message. as_fam_struct_ref( ) . padding,
16121666 restored_state. message. as_fam_struct_ref( ) . padding
16131667 ) ;
1614- // `padding` field will take the default value (0 ). `ser_u16` won't be called at v2.
1615- assert_eq ! ( 0 , restored_state. message. as_fam_struct_ref( ) . padding) ;
1668+ // `padding` field will have its value preserved (8 ). `ser_u16` won't be called at v2.
1669+ assert_eq ! ( 8 , restored_state. message. as_fam_struct_ref( ) . padding) ;
16161670}
0 commit comments