2323from signedjson .key import encode_verify_key_base64 , get_verify_key
2424
2525from twisted .internet import defer
26+ from twisted .internet .defer import Deferred , ensureDeferred
2627
2728from synapse .api .errors import SynapseError
2829from synapse .crypto import keyring
3334)
3435from synapse .logging .context import (
3536 LoggingContext ,
36- PreserveLoggingContext ,
3737 current_context ,
3838 make_deferred_yieldable ,
3939)
@@ -68,54 +68,40 @@ def sign_response(self, res):
6868
6969
7070class KeyringTestCase (unittest .HomeserverTestCase ):
71- def make_homeserver (self , reactor , clock ):
72- self .mock_perspective_server = MockPerspectiveServer ()
73- self .http_client = Mock ()
74-
75- config = self .default_config ()
76- config ["trusted_key_servers" ] = [
77- {
78- "server_name" : self .mock_perspective_server .server_name ,
79- "verify_keys" : self .mock_perspective_server .get_verify_keys (),
80- }
81- ]
82-
83- return self .setup_test_homeserver (
84- handlers = None , http_client = self .http_client , config = config
85- )
86-
87- def check_context (self , _ , expected ):
71+ def check_context (self , val , expected ):
8872 self .assertEquals (getattr (current_context (), "request" , None ), expected )
73+ return val
8974
9075 def test_verify_json_objects_for_server_awaits_previous_requests (self ):
91- key1 = signedjson .key .generate_signing_key (1 )
76+ mock_fetcher = keyring .KeyFetcher ()
77+ mock_fetcher .get_keys = Mock ()
78+ kr = keyring .Keyring (self .hs , key_fetchers = (mock_fetcher ,))
9279
93- kr = keyring .Keyring (self .hs )
80+ # a signed object that we are going to try to validate
81+ key1 = signedjson .key .generate_signing_key (1 )
9482 json1 = {}
9583 signedjson .sign .sign_json (json1 , "server10" , key1 )
9684
97- persp_resp = {
98- "server_keys" : [
99- self .mock_perspective_server .get_signed_key (
100- "server10" , signedjson .key .get_verify_key (key1 )
101- )
102- ]
103- }
104- persp_deferred = defer .Deferred ()
85+ # start off a first set of lookups. We make the mock fetcher block until this
86+ # deferred completes.
87+ first_lookup_deferred = Deferred ()
88+
89+ async def first_lookup_fetch (keys_to_fetch ):
90+ self .assertEquals (current_context ().request , "context_11" )
91+ self .assertEqual (keys_to_fetch , {"server10" : {get_key_id (key1 ): 0 }})
10592
106- async def get_perspectives (** kwargs ):
107- self .assertEquals (current_context ().request , "11" )
108- with PreserveLoggingContext ():
109- await persp_deferred
110- return persp_resp
93+ await make_deferred_yieldable (first_lookup_deferred )
94+ return {
95+ "server10" : {
96+ get_key_id (key1 ): FetchKeyResult (get_verify_key (key1 ), 100 )
97+ }
98+ }
11199
112- self . http_client . post_json . side_effect = get_perspectives
100+ mock_fetcher . get_keys . side_effect = first_lookup_fetch
113101
114- # start off a first set of lookups
115- @defer .inlineCallbacks
116- def first_lookup ():
117- with LoggingContext ("11" ) as context_11 :
118- context_11 .request = "11"
102+ async def first_lookup ():
103+ with LoggingContext ("context_11" ) as context_11 :
104+ context_11 .request = "context_11"
119105
120106 res_deferreds = kr .verify_json_objects_for_server (
121107 [("server10" , json1 , 0 , "test10" ), ("server11" , {}, 0 , "test11" )]
@@ -124,53 +110,59 @@ def first_lookup():
124110 # the unsigned json should be rejected pretty quickly
125111 self .assertTrue (res_deferreds [1 ].called )
126112 try :
127- yield res_deferreds [1 ]
113+ await res_deferreds [1 ]
128114 self .assertFalse ("unsigned json didn't cause a failure" )
129115 except SynapseError :
130116 pass
131117
132118 self .assertFalse (res_deferreds [0 ].called )
133119 res_deferreds [0 ].addBoth (self .check_context , None )
134120
135- yield make_deferred_yieldable (res_deferreds [0 ])
121+ await make_deferred_yieldable (res_deferreds [0 ])
136122
137- # let verify_json_objects_for_server finish its work before we kill the
138- # logcontext
139- yield self .clock .sleep (0 )
123+ d0 = ensureDeferred (first_lookup ())
140124
141- d0 = first_lookup ()
142-
143- # wait a tick for it to send the request to the perspectives server
144- # (it first tries the datastore)
145- self .pump ()
146- self .http_client .post_json .assert_called_once ()
125+ mock_fetcher .get_keys .assert_called_once ()
147126
148127 # a second request for a server with outstanding requests
149128 # should block rather than start a second call
150- @defer .inlineCallbacks
151- def second_lookup ():
152- with LoggingContext ("12" ) as context_12 :
153- context_12 .request = "12"
154- self .http_client .post_json .reset_mock ()
155- self .http_client .post_json .return_value = defer .Deferred ()
129+
130+ async def second_lookup_fetch (keys_to_fetch ):
131+ self .assertEquals (current_context ().request , "context_12" )
132+ return {
133+ "server10" : {
134+ get_key_id (key1 ): FetchKeyResult (get_verify_key (key1 ), 100 )
135+ }
136+ }
137+
138+ mock_fetcher .get_keys .reset_mock ()
139+ mock_fetcher .get_keys .side_effect = second_lookup_fetch
140+ second_lookup_state = [0 ]
141+
142+ async def second_lookup ():
143+ with LoggingContext ("context_12" ) as context_12 :
144+ context_12 .request = "context_12"
156145
157146 res_deferreds_2 = kr .verify_json_objects_for_server (
158147 [("server10" , json1 , 0 , "test" )]
159148 )
160149 res_deferreds_2 [0 ].addBoth (self .check_context , None )
161- yield make_deferred_yieldable (res_deferreds_2 [0 ])
150+ second_lookup_state [0 ] = 1
151+ await make_deferred_yieldable (res_deferreds_2 [0 ])
152+ second_lookup_state [0 ] = 2
162153
163- # let verify_json_objects_for_server finish its work before we kill the
164- # logcontext
165- yield self .clock .sleep (0 )
166-
167- d2 = second_lookup ()
154+ d2 = ensureDeferred (second_lookup ())
168155
169156 self .pump ()
170- self .http_client .post_json .assert_not_called ()
157+ # the second request should be pending, but the fetcher should not yet have been
158+ # called
159+ self .assertEqual (second_lookup_state [0 ], 1 )
160+ mock_fetcher .get_keys .assert_not_called ()
171161
172162 # complete the first request
173- persp_deferred .callback (persp_resp )
163+ first_lookup_deferred .callback (None )
164+
165+ # and now both verifications should succeed.
174166 self .get_success (d0 )
175167 self .get_success (d2 )
176168
0 commit comments