@@ -197,11 +197,6 @@ module V3
197197 action . precursor ( service_instance , app :, message :)
198198 end . not_to raise_error
199199
200- # Mock the validation for the second request to simulate the race condition and trigger a
201- # unique constraint violation on service_instance_guid + app_guid
202- allow_any_instance_of ( ServiceBinding ) . to receive ( :validate ) . and_return ( true )
203- allow ( ServiceBinding ) . to receive ( :first ) . with ( service_instance :, app :) . and_return ( nil )
204-
205200 # Second request, should fail with correct error
206201 expect do
207202 action . precursor ( service_instance , app : app , message : message2 )
@@ -233,6 +228,29 @@ module V3
233228 )
234229 end
235230
231+ context 'concurrent credential binding creation' do
232+ let ( :name ) { nil }
233+
234+ # TODO: Once the unique constraints to allow multiple bindings are removed, this needs to be set to 1
235+ # before { TestConfig.override(max_service_credential_bindings_per_app_service_instance: 1) }
236+
237+ def attempt_precursor
238+ action . precursor ( service_instance , app :, message :)
239+ :ok
240+ rescue StandardError => e
241+ e
242+ end
243+
244+ it 'allows only one binding when two creates run in parallel' do
245+ results = [ Thread . new { attempt_precursor } , Thread . new { attempt_precursor } ] . map ( &:value )
246+
247+ expect ( ServiceBinding . where ( app :, service_instance :) . count ) . to eq ( 1 )
248+ expect ( results . count ( :ok ) ) . to eq ( 1 )
249+ expect ( results . count { |r | r . is_a? ( VCAP ::CloudController ::V3 ::ServiceBindingCreate ::UnprocessableCreate ) } ) . to eq ( 1 )
250+ expect ( results . grep ( Exception ) . map ( &:message ) ) . to include ( 'The app is already bound to the service instance' )
251+ end
252+ end
253+
236254 context 'when multiple bindings are allowed' do
237255 before do
238256 # TODO: Remove skip when the service bindings unique constraints are removed
0 commit comments