@@ -1633,3 +1633,89 @@ fn lsps5_service_handler_persistence_across_restarts() {
16331633 }
16341634 }
16351635}
1636+
1637+ #[ test]
1638+ fn prune_webhook_removes_registered_webhook ( ) {
1639+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
1640+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
1641+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
1642+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
1643+ let ( lsps_nodes, _) = lsps5_test_setup ( nodes, Arc :: new ( DefaultTimeProvider ) ) ;
1644+ let LSPSNodes { service_node, client_node, .. } = lsps_nodes;
1645+ create_chan_between_nodes ( & service_node. inner , & client_node. inner ) ;
1646+
1647+ let service_node_id = service_node. inner . node . get_our_node_id ( ) ;
1648+ let client_node_id = client_node. inner . node . get_our_node_id ( ) ;
1649+ let service_handler = service_node. liquidity_manager . lsps5_service_handler ( ) . unwrap ( ) ;
1650+
1651+ // assert_lsps5_accept registers a webhook with app_name "App".
1652+ let app_name = LSPS5AppName :: from_string ( "App" . to_string ( ) ) . unwrap ( ) ;
1653+
1654+ // Register a webhook through the normal request flow.
1655+ assert_lsps5_accept ( & service_node, & client_node) ;
1656+
1657+ // The notification must be emitted before pruning to confirm the webhook is registered.
1658+ let result = service_handler. notify_payment_incoming ( client_node_id) ;
1659+ assert ! ( result. is_ok( ) ) ;
1660+ assert ! ( service_node. liquidity_manager. next_event( ) . is_some( ) , "Webhook notification expected" ) ;
1661+
1662+ // Prune the webhook.
1663+ let prune_result = service_handler. prune_webhook ( client_node_id, & app_name) ;
1664+ assert ! ( prune_result. is_ok( ) , "prune_webhook should succeed for a registered webhook" ) ;
1665+
1666+ // After pruning, notify should succeed but produce no event (no webhooks left).
1667+ let result_after = service_handler. notify_payment_incoming ( client_node_id) ;
1668+ assert ! ( result_after. is_ok( ) ) ;
1669+ assert ! (
1670+ service_node. liquidity_manager. next_event( ) . is_none( ) ,
1671+ "No notification event expected after pruning"
1672+ ) ;
1673+
1674+ // A second prune of the same app_name must fail.
1675+ let second_prune = service_handler. prune_webhook ( client_node_id, & app_name) ;
1676+ assert ! ( second_prune. is_err( ) , "prune_webhook should fail when the webhook is already removed" ) ;
1677+
1678+ let _ = service_node_id; // suppress unused warning
1679+ }
1680+
1681+ #[ test]
1682+ fn prune_webhook_fails_for_unknown_counterparty ( ) {
1683+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
1684+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
1685+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
1686+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
1687+ let ( lsps_nodes, _) = lsps5_test_setup ( nodes, Arc :: new ( DefaultTimeProvider ) ) ;
1688+ let LSPSNodes { service_node, client_node, .. } = lsps_nodes;
1689+ create_chan_between_nodes ( & service_node. inner , & client_node. inner ) ;
1690+
1691+ let client_node_id = client_node. inner . node . get_our_node_id ( ) ;
1692+ let service_handler = service_node. liquidity_manager . lsps5_service_handler ( ) . unwrap ( ) ;
1693+
1694+ let app_name = LSPS5AppName :: from_string ( "SomeApp" . to_string ( ) ) . unwrap ( ) ;
1695+
1696+ // Pruning for a peer with no state must return an error.
1697+ let result = service_handler. prune_webhook ( client_node_id, & app_name) ;
1698+ assert ! ( result. is_err( ) , "prune_webhook should fail when counterparty has no state" ) ;
1699+ }
1700+
1701+ #[ test]
1702+ fn prune_webhook_fails_for_unknown_app_name ( ) {
1703+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
1704+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
1705+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
1706+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
1707+ let ( lsps_nodes, _) = lsps5_test_setup ( nodes, Arc :: new ( DefaultTimeProvider ) ) ;
1708+ let LSPSNodes { service_node, client_node, .. } = lsps_nodes;
1709+ create_chan_between_nodes ( & service_node. inner , & client_node. inner ) ;
1710+
1711+ let client_node_id = client_node. inner . node . get_our_node_id ( ) ;
1712+ let service_handler = service_node. liquidity_manager . lsps5_service_handler ( ) . unwrap ( ) ;
1713+
1714+ // Register one webhook.
1715+ assert_lsps5_accept ( & service_node, & client_node) ;
1716+
1717+ // Pruning with a different app_name must fail.
1718+ let unknown_app_name = LSPS5AppName :: from_string ( "UnknownApp" . to_string ( ) ) . unwrap ( ) ;
1719+ let result = service_handler. prune_webhook ( client_node_id, & unknown_app_name) ;
1720+ assert ! ( result. is_err( ) , "prune_webhook should fail for an unregistered app_name" ) ;
1721+ }
0 commit comments