@@ -270,4 +270,97 @@ mod tests {
270270 assert_eq ! ( info. status, 0x0304 ) ;
271271 assert_eq ! ( info. configuration_capability, 0x0506 ) ;
272272 }
273+
274+ #[ test]
275+ fn test_ciptype_roundtrip ( ) {
276+ for ( raw, typ) in [
277+ ( 0xC1 , CipType :: Bool ) ,
278+ ( 0xC2 , CipType :: SInt ) ,
279+ ( 0xC3 , CipType :: Int ) ,
280+ ( 0xC4 , CipType :: DInt ) ,
281+ ( 0xC5 , CipType :: LInt ) ,
282+ ( 0xCA , CipType :: Real ) ,
283+ ( 0xD0 , CipType :: String ) ,
284+ ( 0xD3 , CipType :: BoolPacked ) ,
285+ ] {
286+ assert_eq ! ( CipType :: from_u8( raw) , Some ( typ) ) ;
287+ assert_eq ! ( CipType :: from_u16( raw as u16 ) , Some ( typ) ) ;
288+ }
289+ }
290+
291+ #[ test]
292+ fn test_identity_info_decode_too_short ( ) {
293+ let raw = vec ! [ 0u8 ; 5 ] ;
294+ assert ! ( IdentityInfo :: decode( & raw) . is_err( ) ) ;
295+ }
296+
297+ #[ test]
298+ fn test_identity_info_decode_name_too_short ( ) {
299+ let mut raw = vec ! [ 0u8 ; 2 + 2 + 2 + 2 + 2 + 4 ] ;
300+ raw. extend_from_slice ( & 10u16 . to_le_bytes ( ) ) ; // claims name length 10
301+ raw. extend_from_slice ( & [ 1 , 2 , 3 ] ) ; // only 3 bytes
302+ assert ! ( IdentityInfo :: decode( & raw) . is_err( ) ) ;
303+ }
304+
305+ #[ test]
306+ fn test_connection_manager_info_decode_too_short ( ) {
307+ let raw = vec ! [ 0x01 , 0x02 , 0x03 ] ;
308+ assert ! ( ConnectionManagerInfo :: decode( & raw) . is_err( ) ) ;
309+ }
310+
311+ #[ test]
312+ fn test_cipvalue_type_name ( ) {
313+ assert_eq ! ( CipValue :: Bool ( true ) . type_name( ) , "BOOL" ) ;
314+ assert_eq ! ( CipValue :: SInt ( 1 ) . type_name( ) , "SINT" ) ;
315+ assert_eq ! ( CipValue :: Int ( 1 ) . type_name( ) , "INT" ) ;
316+ assert_eq ! ( CipValue :: DInt ( 1 ) . type_name( ) , "DINT" ) ;
317+ assert_eq ! ( CipValue :: LInt ( 1 ) . type_name( ) , "LINT" ) ;
318+ assert_eq ! ( CipValue :: Real ( 1.0 ) . type_name( ) , "REAL" ) ;
319+ assert_eq ! ( CipValue :: String ( "x" . into( ) ) . type_name( ) , "STRING" ) ;
320+ assert_eq ! ( CipValue :: BoolPacked ( vec![ 1 ] ) . type_name( ) , "BOOL_PACKED" ) ;
321+ assert_eq ! ( CipValue :: Unit . type_name( ) , "UNIT" ) ;
322+ }
323+
324+ #[ test]
325+ fn test_multiresult_variants ( ) {
326+ let ok = MultiResult :: Ok ( 123 ) ;
327+ let err: MultiResult < ( ) > = MultiResult :: Err ( 0x05 ) ;
328+
329+ assert ! ( matches!( ok, MultiResult :: Ok ( _) ) ) ;
330+ assert ! ( matches!( err, MultiResult :: Err ( 0x05 ) ) ) ;
331+ }
332+
333+ #[ test]
334+ fn test_symbolinfo_basic ( ) {
335+ let s = SymbolInfo {
336+ name : "Tag" . into ( ) ,
337+ typ : CipType :: DInt ,
338+ array_dims : Some ( ( 10 , 0 , 0 ) ) ,
339+ } ;
340+
341+ assert_eq ! ( s. name, "Tag" ) ;
342+ assert_eq ! ( s. typ, CipType :: DInt ) ;
343+ assert_eq ! ( s. array_dims, Some ( ( 10 , 0 , 0 ) ) ) ;
344+ }
345+ #[ test]
346+ fn test_identity_info_decode_exact_boundary ( ) {
347+ let mut raw = Vec :: new ( ) ;
348+ raw. extend_from_slice ( & 1u16 . to_le_bytes ( ) ) ; // vendor
349+ raw. extend_from_slice ( & 2u16 . to_le_bytes ( ) ) ; // type
350+ raw. extend_from_slice ( & 3u16 . to_le_bytes ( ) ) ; // code
351+ raw. extend_from_slice ( & [ 1 , 2 ] ) ; // revision
352+ raw. extend_from_slice ( & 4u16 . to_le_bytes ( ) ) ; // status
353+ raw. extend_from_slice ( & 5u32 . to_le_bytes ( ) ) ; // serial
354+
355+ let name = b"A" ;
356+ raw. extend_from_slice ( & ( name. len ( ) as u16 ) . to_le_bytes ( ) ) ;
357+ raw. extend_from_slice ( name) ;
358+
359+ raw. extend ( std:: iter:: repeat_n ( 0 , 82 - name. len ( ) ) ) ;
360+ raw. push ( 7 ) ; // state
361+
362+ let info = IdentityInfo :: decode ( & raw ) . unwrap ( ) ;
363+ assert_eq ! ( info. product_name, "A" ) ;
364+ assert_eq ! ( info. state, 7 ) ;
365+ }
273366}
0 commit comments