@@ -336,3 +336,182 @@ impl Collection {
336336 Ok ( ( ) )
337337 }
338338}
339+
340+ #[ cfg( test) ]
341+ mod tests {
342+ use std:: sync:: Arc ;
343+
344+ use oo7:: dbus;
345+
346+ use super :: * ;
347+
348+ /// Helper to create a peer-to-peer connection pair using Unix socket
349+ async fn create_p2p_connection ( ) -> ( zbus:: Connection , zbus:: Connection ) {
350+ let guid = zbus:: Guid :: generate ( ) ;
351+ let ( p0, p1) = tokio:: net:: UnixStream :: pair ( ) . unwrap ( ) ;
352+
353+ let ( client_conn, server_conn) = tokio:: try_join!(
354+ zbus:: connection:: Builder :: unix_stream( p0) . p2p( ) . build( ) ,
355+ zbus:: connection:: Builder :: unix_stream( p1)
356+ . server( guid)
357+ . unwrap( )
358+ . p2p( )
359+ . build( ) ,
360+ )
361+ . unwrap ( ) ;
362+
363+ ( server_conn, client_conn)
364+ }
365+
366+ #[ tokio:: test]
367+ async fn create_item_plain ( ) {
368+ let ( server_conn, client_conn) = create_p2p_connection ( ) . await ;
369+
370+ let _server = Service :: run_with_connection (
371+ server_conn,
372+ Some ( oo7:: Secret :: from ( "test-password-long-enough" ) ) ,
373+ )
374+ . await
375+ . unwrap ( ) ;
376+
377+ tokio:: time:: sleep ( tokio:: time:: Duration :: from_millis ( 50 ) ) . await ;
378+
379+ let service_api = dbus:: api:: Service :: new ( & client_conn) . await . unwrap ( ) ;
380+
381+ // Open plain session
382+ let ( _aes_key, session) = service_api. open_session ( None ) . await . unwrap ( ) ;
383+
384+ // Get default collection
385+ let collections = service_api. collections ( ) . await . unwrap ( ) ;
386+
387+ // Create an item using the proper API
388+ let secret = oo7:: Secret :: text ( "my-secret-password" ) ;
389+ let attributes = & [ ( "application" , "test-app" ) , ( "type" , "password" ) ] ;
390+ let dbus_secret = dbus:: api:: DBusSecret :: new ( Arc :: new ( session) , secret. clone ( ) ) ;
391+
392+ let item = collections[ 0 ]
393+ . create_item ( "Test Item" , attributes, & dbus_secret, false , None )
394+ . await
395+ . unwrap ( ) ;
396+
397+ // Verify item exists in collection
398+ let items = collections[ 0 ] . items ( ) . await . unwrap ( ) ;
399+ assert_eq ! ( items. len( ) , 1 , "Collection should have one item" ) ;
400+ assert_eq ! ( items[ 0 ] . inner( ) . path( ) , item. inner( ) . path( ) ) ;
401+
402+ // Verify item label
403+ let label = item. label ( ) . await . unwrap ( ) ;
404+ assert_eq ! ( label, "Test Item" ) ;
405+ }
406+
407+ #[ tokio:: test]
408+ async fn create_item_encrypted ( ) {
409+ let ( server_conn, client_conn) = create_p2p_connection ( ) . await ;
410+
411+ let _server = Service :: run_with_connection (
412+ server_conn,
413+ Some ( oo7:: Secret :: from ( "test-password-long-enough" ) ) ,
414+ )
415+ . await
416+ . unwrap ( ) ;
417+
418+ tokio:: time:: sleep ( tokio:: time:: Duration :: from_millis ( 50 ) ) . await ;
419+
420+ let service_api = dbus:: api:: Service :: new ( & client_conn) . await . unwrap ( ) ;
421+
422+ // Open encrypted session
423+ let client_private_key = oo7:: Key :: generate_private_key ( ) . unwrap ( ) ;
424+ let client_public_key = oo7:: Key :: generate_public_key ( & client_private_key) . unwrap ( ) ;
425+
426+ let ( server_public_key_opt, session) = service_api
427+ . open_session ( Some ( client_public_key) )
428+ . await
429+ . unwrap ( ) ;
430+
431+ let server_public_key = server_public_key_opt. unwrap ( ) ;
432+ let aes_key = oo7:: Key :: generate_aes_key ( & client_private_key, & server_public_key) . unwrap ( ) ;
433+
434+ // Get default collection
435+ let collections = service_api. collections ( ) . await . unwrap ( ) ;
436+
437+ // Create an encrypted item using the proper API
438+ let secret = oo7:: Secret :: text ( "my-encrypted-secret" ) ;
439+ let attributes = & [ ( "application" , "test-app" ) , ( "type" , "encrypted-password" ) ] ;
440+ let dbus_secret =
441+ dbus:: api:: DBusSecret :: new_encrypted ( Arc :: new ( session) , secret, & aes_key) . unwrap ( ) ;
442+
443+ let item = collections[ 0 ]
444+ . create_item ( "Test Encrypted Item" , attributes, & dbus_secret, false , None )
445+ . await
446+ . unwrap ( ) ;
447+
448+ // Verify item exists
449+ let items = collections[ 0 ] . items ( ) . await . unwrap ( ) ;
450+ assert_eq ! ( items. len( ) , 1 , "Collection should have one item" ) ;
451+ assert_eq ! ( items[ 0 ] . inner( ) . path( ) , item. inner( ) . path( ) ) ;
452+ }
453+
454+ #[ tokio:: test]
455+ async fn search_items_after_creation ( ) {
456+ let ( server_conn, client_conn) = create_p2p_connection ( ) . await ;
457+
458+ let _server = Service :: run_with_connection (
459+ server_conn,
460+ Some ( oo7:: Secret :: from ( "test-password-long-enough" ) ) ,
461+ )
462+ . await
463+ . unwrap ( ) ;
464+
465+ tokio:: time:: sleep ( tokio:: time:: Duration :: from_millis ( 50 ) ) . await ;
466+
467+ let service_api = dbus:: api:: Service :: new ( & client_conn) . await . unwrap ( ) ;
468+ let ( _aes_key, session) = service_api. open_session ( None ) . await . unwrap ( ) ;
469+ let session = Arc :: new ( session) ;
470+
471+ let collections = service_api. collections ( ) . await . unwrap ( ) ;
472+
473+ // Create two items with different attributes
474+ let secret1 = oo7:: Secret :: text ( "password1" ) ;
475+ let attributes1 = & [ ( "application" , "firefox" ) , ( "username" , "user1" ) ] ;
476+ let dbus_secret1 = dbus:: api:: DBusSecret :: new ( Arc :: clone ( & session) , secret1) ;
477+
478+ collections[ 0 ]
479+ . create_item ( "Firefox Password" , attributes1, & dbus_secret1, false , None )
480+ . await
481+ . unwrap ( ) ;
482+
483+ let secret2 = oo7:: Secret :: text ( "password2" ) ;
484+ let attributes2 = & [ ( "application" , "chrome" ) , ( "username" , "user2" ) ] ;
485+ let dbus_secret2 = dbus:: api:: DBusSecret :: new ( Arc :: clone ( & session) , secret2) ;
486+
487+ collections[ 0 ]
488+ . create_item ( "Chrome Password" , attributes2, & dbus_secret2, false , None )
489+ . await
490+ . unwrap ( ) ;
491+
492+ // Search for firefox item
493+ let firefox_attrs = & [ ( "application" , "firefox" ) ] ;
494+ let firefox_items = collections[ 0 ] . search_items ( firefox_attrs) . await . unwrap ( ) ;
495+
496+ assert_eq ! ( firefox_items. len( ) , 1 , "Should find one firefox item" ) ;
497+
498+ // Search for chrome item
499+ let chrome_attrs = & [ ( "application" , "chrome" ) ] ;
500+ let chrome_items = collections[ 0 ] . search_items ( chrome_attrs) . await . unwrap ( ) ;
501+
502+ assert_eq ! ( chrome_items. len( ) , 1 , "Should find one chrome item" ) ;
503+
504+ // Search for non-existent item
505+ let nonexistent_attrs = & [ ( "application" , "nonexistent" ) ] ;
506+ let nonexistent_items = collections[ 0 ]
507+ . search_items ( nonexistent_attrs)
508+ . await
509+ . unwrap ( ) ;
510+
511+ assert_eq ! (
512+ nonexistent_items. len( ) ,
513+ 0 ,
514+ "Should find no nonexistent items"
515+ ) ;
516+ }
517+ }
0 commit comments