@@ -142,7 +142,8 @@ fn assert_event_topic_matches(env: &Env, event: &(Address, Vec<Val>, Val), expec
142142
143143 assert_eq ! (
144144 actual_topic, expected_topic,
145- "event topic should match expected contract identifier"
145+ "event topic mismatch: expected {:?}, got {:?}" ,
146+ expected_topic, actual_topic
146147 ) ;
147148}
148149
@@ -301,7 +302,7 @@ fn test_register_creator_event_fires_once() {
301302}
302303
303304#[ test]
304- #[ should_panic( expected = "event topic should match expected contract identifier " ) ]
305+ #[ should_panic( expected = "event topic mismatch " ) ]
305306fn test_assert_event_topic_matches_rejects_unexpected_identifier ( ) {
306307 let env = Env :: default ( ) ;
307308 env. mock_all_auths ( ) ;
@@ -438,3 +439,129 @@ fn test_sell_key_event_payload_field_order_is_documented() {
438439 [ "seller" , "creator_id" , "quantity" , "proceeds" , "ledger" ]
439440 ) ;
440441}
442+
443+ #[ test]
444+ #[ should_panic( expected = "event topic mismatch" ) ]
445+ fn test_assert_event_topic_matches_panics_on_buy_vs_sell_mismatch ( ) {
446+ let env = Env :: default ( ) ;
447+ env. mock_all_auths ( ) ;
448+ let fixture = EventFixture :: new ( & env) ;
449+ let buyer = Address :: generate ( & env) ;
450+
451+ fixture. register_creator ( & env, "alice" ) ;
452+ fixture. buy_key ( & buyer, KEY_PRICE ) ;
453+
454+ let buy_event = env
455+ . events ( )
456+ . all ( )
457+ . iter ( )
458+ . rev ( )
459+ . find ( |( _, topics, _) | {
460+ topics
461+ . get ( events:: TOPIC_EVENT_NAME_INDEX )
462+ . map ( |v| {
463+ let name: Symbol = v. into_val ( & env) ;
464+ name == events:: BUY_EVENT_NAME
465+ } )
466+ . unwrap_or ( false )
467+ } )
468+ . expect ( "buy event should be present" ) ;
469+
470+ assert_event_topic_matches ( & env, & buy_event, events:: SELL_EVENT_NAME ) ;
471+ }
472+
473+ #[ test]
474+ fn test_assert_event_topic_matches_passes_on_matching_topic ( ) {
475+ let env = Env :: default ( ) ;
476+ env. mock_all_auths ( ) ;
477+ let fixture = EventFixture :: new ( & env) ;
478+ let buyer = Address :: generate ( & env) ;
479+
480+ fixture. register_creator ( & env, "alice" ) ;
481+ fixture. buy_key ( & buyer, KEY_PRICE ) ;
482+
483+ let buy_event = env
484+ . events ( )
485+ . all ( )
486+ . iter ( )
487+ . rev ( )
488+ . find ( |( _, topics, _) | {
489+ topics
490+ . get ( events:: TOPIC_EVENT_NAME_INDEX )
491+ . map ( |v| {
492+ let name: Symbol = v. into_val ( & env) ;
493+ name == events:: BUY_EVENT_NAME
494+ } )
495+ . unwrap_or ( false )
496+ } )
497+ . expect ( "buy event should be present" ) ;
498+
499+ assert_event_topic_matches ( & env, & buy_event, events:: BUY_EVENT_NAME ) ;
500+ }
501+
502+ #[ test]
503+ #[ should_panic( expected = "event topic should be present" ) ]
504+ fn test_assert_event_topic_matches_panics_when_no_topics ( ) {
505+ let env = Env :: default ( ) ;
506+ let addr = Address :: generate ( & env) ;
507+ let empty_topics: Vec < Val > = Vec :: new ( & env) ;
508+ let event = ( addr, empty_topics, 0_i32 . into_val ( & env) ) ;
509+
510+ assert_event_topic_matches ( & env, & event, events:: BUY_EVENT_NAME ) ;
511+ }
512+
513+ #[ test]
514+ fn test_assert_event_topic_mismatch_message_identifies_topics ( ) {
515+ let env = Env :: default ( ) ;
516+ env. mock_all_auths ( ) ;
517+ let fixture = EventFixture :: new ( & env) ;
518+ let buyer = Address :: generate ( & env) ;
519+
520+ fixture. register_creator ( & env, "alice" ) ;
521+ fixture. buy_key ( & buyer, KEY_PRICE ) ;
522+
523+ let buy_event = env
524+ . events ( )
525+ . all ( )
526+ . iter ( )
527+ . rev ( )
528+ . find ( |( _, topics, _) | {
529+ topics
530+ . get ( events:: TOPIC_EVENT_NAME_INDEX )
531+ . map ( |v| {
532+ let name: Symbol = v. into_val ( & env) ;
533+ name == events:: BUY_EVENT_NAME
534+ } )
535+ . unwrap_or ( false )
536+ } )
537+ . expect ( "buy event should be present" ) ;
538+
539+ let err = std:: panic:: catch_unwind ( std:: panic:: AssertUnwindSafe ( || {
540+ assert_event_topic_matches ( & env, & buy_event, events:: SELL_EVENT_NAME ) ;
541+ } ) )
542+ . unwrap_err ( ) ;
543+
544+ let message = err
545+ . downcast_ref :: < std:: string:: String > ( )
546+ . cloned ( )
547+ . or_else ( || {
548+ err. downcast_ref :: < & str > ( )
549+ . map ( |s| std:: string:: String :: from ( * s) )
550+ } )
551+ . unwrap_or_default ( ) ;
552+ assert ! (
553+ message. contains( "event topic mismatch" ) ,
554+ "message should indicate topic mismatch, got: {}" ,
555+ message
556+ ) ;
557+ assert ! (
558+ message. contains( & format!( "{:?}" , events:: BUY_EVENT_NAME ) ) ,
559+ "message should identify actual topic, got: {}" ,
560+ message
561+ ) ;
562+ assert ! (
563+ message. contains( & format!( "{:?}" , events:: SELL_EVENT_NAME ) ) ,
564+ "message should identify expected topic, got: {}" ,
565+ message
566+ ) ;
567+ }
0 commit comments