From 970981d3b0bb14d10956377b79051fa42b7deec4 Mon Sep 17 00:00:00 2001 From: stakx Date: Thu, 22 Jun 2017 22:43:33 +0200 Subject: [PATCH] Make `Interceptor` more thread-safe Several methods in `Interceptor` currently read and modify a private dictionary without any synchronization or locking, which means that if someone tries to perform several setups concurrently on the same mock, they might run into a some multithreading-related exception every now and then. --- Source/Interceptor.cs | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/Source/Interceptor.cs b/Source/Interceptor.cs index 01a930650..edde1db83 100644 --- a/Source/Interceptor.cs +++ b/Source/Interceptor.cs @@ -75,10 +75,13 @@ internal void VerifyAll() private void VerifyOrThrow(Func match) { - var failures = calls.Values.Where(match).ToArray(); - if (failures.Length > 0) + lock (calls) { - throw new MockVerificationException(failures); + var failures = calls.Values.Where(match); + if (failures.Any()) + { + throw new MockVerificationException(failures.ToArray()); + } } } @@ -96,18 +99,21 @@ public void AddCall(IProxyCall call, SetupKind kind) if (!call.IsConditional) { - // if it's not a conditional call, we do - // all the override setups. - // TODO maybe add the conditionals to other - // record like calls to be user friendly and display - // somethig like: non of this calls were performed. - if (calls.ContainsKey(key)) + lock (calls) { - // Remove previous from ordered calls - InterceptionContext.RemoveOrderedCall(calls[key]); - } + // if it's not a conditional call, we do + // all the override setups. + // TODO maybe add the conditionals to other + // record like calls to be user friendly and display + // somethig like: non of this calls were performed. + if (calls.ContainsKey(key)) + { + // Remove previous from ordered calls + InterceptionContext.RemoveOrderedCall(calls[key]); + } - calls[key] = call; + calls[key] = call; + } } InterceptionContext.AddOrderedCall(call); @@ -115,7 +121,10 @@ public void AddCall(IProxyCall call, SetupKind kind) internal void ClearCalls() { - calls.Clear(); + lock (calls) + { + calls.Clear(); + } } private IEnumerable InterceptionStrategies()