@@ -19,6 +19,7 @@ mod tests {
1919 use reqwest:: { header, StatusCode } ;
2020 use sqlx:: PgPool ;
2121 use tap_core:: { manager:: Manager , receipt:: checks:: CheckList } ;
22+ use tokio:: time:: sleep;
2223 use tower:: { Service , ServiceBuilder , ServiceExt } ;
2324 use tower_http:: auth:: AsyncRequireAuthorizationLayer ;
2425
@@ -27,14 +28,11 @@ mod tests {
2728 use test_assets:: { create_signed_receipt, TAP_EIP712_DOMAIN } ;
2829
2930 const ALLOCATION_ID : Address = address ! ( "deadbeefcafebabedeadbeefcafebabedeadbeef" ) ;
31+ const BEARER_TOKEN : & str = "test" ;
3032
31- async fn handle ( _: Request < Body > ) -> anyhow:: Result < Response < Body > > {
32- Ok ( Response :: new ( Body :: default ( ) ) )
33- }
34-
35- #[ sqlx:: test( migrations = "../../migrations" ) ]
36- async fn test_middleware_composition ( pgpool : PgPool ) {
37- let token = "test" . to_string ( ) ;
33+ async fn service (
34+ pgpool : PgPool ,
35+ ) -> impl Service < Request < Body > , Response = Response < Body > , Error = impl std:: fmt:: Debug > {
3836 let context = IndexerTapContext :: new ( pgpool. clone ( ) , TAP_EIP712_DOMAIN . clone ( ) ) . await ;
3937 let tap_manager = Box :: leak ( Box :: new ( Manager :: new (
4038 TAP_EIP712_DOMAIN . clone ( ) ,
@@ -49,58 +47,89 @@ mod tests {
4947 )
5048 . unwrap ( ) ,
5149 ) ) ;
52- let free_query = Bearer :: new ( & token ) ;
50+ let free_query = Bearer :: new ( BEARER_TOKEN ) ;
5351 let tap_auth = auth:: tap_receipt_authorize ( tap_manager, metric) ;
5452 let authorize_requests = free_query. or ( tap_auth) ;
5553
5654 let authorization_middleware = AsyncRequireAuthorizationLayer :: new ( authorize_requests) ;
5755
5856 let mut service = ServiceBuilder :: new ( )
5957 . layer ( authorization_middleware)
60- . service_fn ( handle) ;
58+ . service_fn ( |_: Request < Body > | async {
59+ Ok :: < _ , anyhow:: Error > ( Response :: new ( Body :: default ( ) ) )
60+ } ) ;
6161
62- let handle = service. ready ( ) . await . unwrap ( ) ;
62+ service. ready ( ) . await . unwrap ( ) ;
63+ service
64+ }
6365
66+ #[ sqlx:: test( migrations = "../../migrations" ) ]
67+ async fn test_composition_header_valid ( pgpool : PgPool ) {
68+ let mut service = service ( pgpool. clone ( ) ) . await ;
6469 // should allow queries that contains the free token
6570 // if the token does not match, return payment required
6671 let mut req = Request :: new ( Default :: default ( ) ) ;
6772 req. headers_mut ( ) . insert (
6873 header:: AUTHORIZATION ,
69- format ! ( "Bearer {token}" ) . parse ( ) . unwrap ( ) ,
74+ format ! ( "Bearer {}" , BEARER_TOKEN ) . parse ( ) . unwrap ( ) ,
7075 ) ;
71- let res = handle . call ( req) . await . unwrap ( ) ;
76+ let res = service . call ( req) . await . unwrap ( ) ;
7277 assert_eq ! ( res. status( ) , StatusCode :: OK ) ;
78+ }
79+
80+ #[ sqlx:: test( migrations = "../../migrations" ) ]
81+ async fn test_composition_header_invalid ( pgpool : PgPool ) {
82+ let mut service = service ( pgpool. clone ( ) ) . await ;
7383
7484 // if the token exists but is wrong, try the receipt
7585 let mut req = Request :: new ( Default :: default ( ) ) ;
7686 req. headers_mut ( )
7787 . insert ( header:: AUTHORIZATION , "Bearer wrongtoken" . parse ( ) . unwrap ( ) ) ;
78- let res = handle . call ( req) . await . unwrap ( ) ;
88+ let res = service . call ( req) . await . unwrap ( ) ;
7989 // we return the error from tap
8090 assert_eq ! ( res. status( ) , StatusCode :: PAYMENT_REQUIRED ) ;
91+ }
92+
93+ #[ sqlx:: test( migrations = "../../migrations" ) ]
94+ async fn test_composition_with_receipt ( pgpool : PgPool ) {
95+ let mut service = service ( pgpool. clone ( ) ) . await ;
8196
8297 let receipt = create_signed_receipt ( ALLOCATION_ID , 1 , 1 , 1 ) . await ;
8398
8499 // check with receipt
85100 let mut req = Request :: new ( Default :: default ( ) ) ;
86101 req. extensions_mut ( ) . insert ( receipt) ;
87- let res = handle . call ( req) . await . unwrap ( ) ;
102+ let res = service . call ( req) . await . unwrap ( ) ;
88103 assert_eq ! ( res. status( ) , StatusCode :: OK ) ;
89104
90- // todo make this sleep better
91- tokio:: time:: sleep ( Duration :: from_millis ( 100 ) ) . await ;
92-
93105 // verify receipts
94- let result = sqlx:: query!( "SELECT * FROM scalar_tap_receipts" )
95- . fetch_all ( & pgpool)
96- . await
97- . unwrap ( ) ;
98- assert_eq ! ( result. len( ) , 1 ) ;
99-
100- // if it has neither, should return unauthorized
101- // check no headers
106+ if tokio:: time:: timeout ( Duration :: from_secs ( 1 ) , async {
107+ loop {
108+ let result = sqlx:: query!( "SELECT * FROM scalar_tap_receipts" )
109+ . fetch_all ( & pgpool)
110+ . await
111+ . unwrap ( ) ;
112+
113+ if result. is_empty ( ) {
114+ sleep ( Duration :: from_millis ( 50 ) ) . await ;
115+ } else {
116+ break ;
117+ }
118+ }
119+ } )
120+ . await
121+ . is_err ( )
122+ {
123+ panic ! ( "Timeout assertion" ) ;
124+ }
125+ }
126+
127+ #[ sqlx:: test( migrations = "../../migrations" ) ]
128+ async fn test_composition_without_header_or_receipt ( pgpool : PgPool ) {
129+ let mut service = service ( pgpool. clone ( ) ) . await ;
130+ // if it has neither, should return payment required
102131 let req = Request :: new ( Default :: default ( ) ) ;
103- let res = handle . call ( req) . await . unwrap ( ) ;
132+ let res = service . call ( req) . await . unwrap ( ) ;
104133 assert_eq ! ( res. status( ) , StatusCode :: PAYMENT_REQUIRED ) ;
105134 }
106135}
0 commit comments