Skip to content

Commit c8b3f6e

Browse files
committed
Merge remote-tracking branch 'remotes/origin/R2.2019Lite' into rusev/async-context
2 parents 52671b8 + 7f1604c commit c8b3f6e

File tree

5 files changed

+104
-51
lines changed

5 files changed

+104
-51
lines changed

Telerik.JustMock/Core/Behaviors/RecursiveMockingBehavior.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
JustMock Lite
3-
Copyright © 2010-2015 Progress Software Corporation
3+
Copyright © 2010-2015,2019 Progress Software Corporation
44
55
Licensed under the Apache License, Version 2.0 (the "License");
66
you may not use this file except in compliance with the License.
@@ -121,7 +121,7 @@ private bool MustReturnMock(Invocation invocation, bool checkPropertyOnTestFixtu
121121
#endif
122122
}
123123

124-
return invocation.InArrange || this.type == RecursiveMockingBehaviorType.ReturnMock;
124+
return invocation.InArrange && !invocation.InArrangeArgMatching || this.type == RecursiveMockingBehaviorType.ReturnMock;
125125
}
126126

127127
private object CreateMock(Type returnType, MocksRepository repository, Invocation invocation)

Telerik.JustMock/Core/CallPatternCreator.cs

Lines changed: 60 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -271,42 +271,46 @@ internal static CallPattern FromExpression(MocksRepository repository, Expressio
271271
callPattern.SetMethod(method, checkCompatibility: true);
272272

273273
//Finally, construct the arguments part of the call pattern.
274-
bool hasParams = false;
275-
bool hasSingleValueInParams = false;
276-
if (args != null && args.Length > 0)
274+
using (repository.StartArrangeArgMatching())
277275
{
278-
var lastParameter = method.GetParameters().Last();
279-
if (Attribute.IsDefined(lastParameter, typeof(ParamArrayAttribute)) && args.Last() is NewArrayExpression)
280-
{
281-
hasParams = true;
282-
var paramsArg = (NewArrayExpression)args.Last();
283-
args = args.Take(args.Length - 1).Concat(paramsArg.Expressions).ToArray();
284-
if (paramsArg.Expressions.Count == 1)
285-
hasSingleValueInParams = true;
286-
}
276+
bool hasParams = false;
277+
bool hasSingleValueInParams = false;
287278

288-
foreach (var argument in args)
279+
if (args != null && args.Length > 0)
289280
{
290-
callPattern.ArgumentMatchers.Add(MocksRepository.CreateMatcherForArgument(argument));
291-
}
281+
var lastParameter = method.GetParameters().Last();
282+
if (Attribute.IsDefined(lastParameter, typeof(ParamArrayAttribute)) && args.Last() is NewArrayExpression)
283+
{
284+
hasParams = true;
285+
var paramsArg = (NewArrayExpression)args.Last();
286+
args = args.Take(args.Length - 1).Concat(paramsArg.Expressions).ToArray();
287+
if (paramsArg.Expressions.Count == 1)
288+
hasSingleValueInParams = true;
289+
}
292290

293-
if (hasParams)
294-
{
295-
int paramsCount = method.GetParameters().Count();
296-
if (hasSingleValueInParams)
291+
foreach (var argument in args)
297292
{
298-
IMatcher matcher = callPattern.ArgumentMatchers[paramsCount - 1];
299-
ITypedMatcher typeMatcher = matcher as ITypedMatcher;
300-
if (typeMatcher != null && typeMatcher.Type != method.GetParameters().Last().ParameterType)
301-
{
302-
callPattern.ArgumentMatchers[paramsCount - 1] = new ParamsMatcher(new IMatcher[] { matcher });
303-
}
293+
callPattern.ArgumentMatchers.Add(MocksRepository.CreateMatcherForArgument(argument));
304294
}
305-
else
295+
296+
if (hasParams)
306297
{
307-
IEnumerable<IMatcher> paramMatchers = callPattern.ArgumentMatchers.Skip(paramsCount - 1).Take(callPattern.ArgumentMatchers.Count - paramsCount + 1);
308-
callPattern.ArgumentMatchers = callPattern.ArgumentMatchers.Take(paramsCount - 1).ToList();
309-
callPattern.ArgumentMatchers.Add(new ParamsMatcher(paramMatchers.ToArray()));
298+
int paramsCount = method.GetParameters().Count();
299+
if (hasSingleValueInParams)
300+
{
301+
IMatcher matcher = callPattern.ArgumentMatchers[paramsCount - 1];
302+
ITypedMatcher typeMatcher = matcher as ITypedMatcher;
303+
if (typeMatcher != null && typeMatcher.Type != method.GetParameters().Last().ParameterType)
304+
{
305+
callPattern.ArgumentMatchers[paramsCount - 1] = new ParamsMatcher(new IMatcher[] { matcher });
306+
}
307+
}
308+
else
309+
{
310+
IEnumerable<IMatcher> paramMatchers = callPattern.ArgumentMatchers.Skip(paramsCount - 1).Take(callPattern.ArgumentMatchers.Count - paramsCount + 1);
311+
callPattern.ArgumentMatchers = callPattern.ArgumentMatchers.Take(paramsCount - 1).ToList();
312+
callPattern.ArgumentMatchers.Add(new ParamsMatcher(paramMatchers.ToArray()));
313+
}
310314
}
311315
}
312316
}
@@ -319,7 +323,7 @@ internal static CallPattern FromExpression(MocksRepository repository, Expressio
319323
return callPattern;
320324
}
321325

322-
internal static CallPattern FromMethodBase(object instance, MethodBase method, object[] arguments)
326+
internal static CallPattern FromMethodBase(MocksRepository repository, object instance, MethodBase method, object[] arguments)
323327
{
324328
var callPattern = new CallPattern
325329
{
@@ -331,26 +335,34 @@ internal static CallPattern FromMethodBase(object instance, MethodBase method, o
331335

332336
callPattern.SetMethod(method, checkCompatibility: true);
333337

334-
var parameters = method.GetParameters();
335-
if (arguments == null || arguments.Length == 0)
338+
using (repository != null ? repository.StartArrangeArgMatching() : null)
336339
{
337-
callPattern.ArgumentMatchers.AddRange(method.GetParameters().Select(p => (IMatcher)new TypeMatcher(p.ParameterType)));
338-
}
339-
else
340-
{
341-
if (arguments.Length != method.GetParameters().Length)
340+
var parameters = method.GetParameters();
341+
if (arguments == null || arguments.Length == 0)
342342
{
343-
throw new MockException("Argument count mismatch.");
343+
callPattern.ArgumentMatchers.AddRange(method.GetParameters().Select(p => (IMatcher)new TypeMatcher(p.ParameterType)));
344344
}
345+
else
346+
{
347+
if (arguments.Length != method.GetParameters().Length)
348+
{
349+
throw new MockException("Argument count mismatch.");
350+
}
345351

346-
callPattern.ArgumentMatchers.AddRange(arguments.Select(arg => MocksRepository.CreateMatcherForArgument(arg)));
352+
callPattern.ArgumentMatchers.AddRange(arguments.Select(arg => MocksRepository.CreateMatcherForArgument(arg)));
353+
}
347354
}
348355

349356
callPattern.AdjustForExtensionMethod();
350357

351358
return callPattern;
352359
}
353360

361+
internal static CallPattern FromMethodBase(object instance, MethodBase method, object[] arguments)
362+
{
363+
return FromMethodBase(null, instance, method, arguments);
364+
}
365+
354366
internal static CallPattern FromAction(MocksRepository repository, Action memberAction, bool dispatchToMethodMocks = false)
355367
{
356368
var callPattern = new CallPattern();
@@ -365,7 +377,9 @@ internal static CallPattern FromAction(MocksRepository repository, Action member
365377
}
366378

367379
if (lastInvocation == null)
380+
{
368381
throw new MockException("The specified action did not call a mocked method.");
382+
}
369383

370384
callPattern.SetMethod(lastInvocation.Method, checkCompatibility: true);
371385
callPattern.InstanceMatcher = new ReferenceMatcher(lastInvocation.Instance);
@@ -374,11 +388,14 @@ internal static CallPattern FromAction(MocksRepository repository, Action member
374388
// one coming from a matcher, it is impossible to tell exactly which arguments are literal and which are matchers.
375389
// So, we assume that the user always first specifies some literal values, and then some matchers.
376390
// We assume that the user will never pass a literal after a matcher.
377-
for (int i = 0; i < lastInvocation.Args.Length; ++i)
391+
using (repository.StartArrangeArgMatching())
378392
{
379-
var indexInMatchers = i - (lastInvocation.Args.Length - repository.MatchersInContext.Count);
380-
var matcher = indexInMatchers >= 0 ? repository.MatchersInContext[indexInMatchers] : new ValueMatcher(lastInvocation.Args[i]);
381-
callPattern.ArgumentMatchers.Add(matcher);
393+
for (int i = 0; i < lastInvocation.Args.Length; ++i)
394+
{
395+
var indexInMatchers = i - (lastInvocation.Args.Length - repository.MatchersInContext.Count);
396+
var matcher = indexInMatchers >= 0 ? repository.MatchersInContext[indexInMatchers] : new ValueMatcher(lastInvocation.Args[i]);
397+
callPattern.ArgumentMatchers.Add(matcher);
398+
}
382399
}
383400
repository.MatchersInContext.Clear();
384401

Telerik.JustMock/Core/Invocation.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
JustMock Lite
3-
Copyright © 2010-2015,2018 Progress Software Corporation
3+
Copyright © 2010-2015,2018-2019 Progress Software Corporation
44
55
Licensed under the Apache License, Version 2.0 (the "License");
66
you may not use this file except in compliance with the License.
@@ -59,9 +59,11 @@ internal bool IsReturnValueSet
5959
#endregion
6060

6161
internal bool InArrange { get; set; }
62+
internal bool InArrangeArgMatching { get; set; }
6263
internal bool InAssertSet { get; set; }
6364
internal bool Recording { get; set; }
6465
internal bool RetainBehaviorDuringRecording { get; set; }
66+
6567
internal MocksRepository Repository { get; set; }
6668

6769
internal IMockMixin MockMixin { get; private set; }

Telerik.JustMock/Core/MocksRepository.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ public sealed class MocksRepository
9595
#endif
9696
};
9797

98-
9998
internal IRecorder Recorder
10099
{
101100
get { return this.sharedContext.Recorder; }
@@ -381,6 +380,7 @@ internal void DispatchInvocation(Invocation invocation)
381380
}
382381

383382
invocation.InArrange = this.sharedContext.InArrange;
383+
invocation.InArrangeArgMatching = this.sharedContext.InArrangeArgMatching;
384384
invocation.InAssertSet = this.sharedContext.InAssertSet;
385385
invocation.Recording = this.Recorder != null;
386386
invocation.RetainBehaviorDuringRecording = this.sharedContext.DispatchToMethodMocks;
@@ -470,6 +470,11 @@ internal IDisposable StartRecording(IRecorder recorder, bool dispatchToMethodMoc
470470
return this.sharedContext.StartRecording(recorder, dispatchToMethodMocks);
471471
}
472472

473+
internal IDisposable StartArrangeArgMatching()
474+
{
475+
return this.sharedContext.StartArrangeArgMatching();
476+
}
477+
473478
internal void AddMatcherInContext(IMatcher matcher)
474479
{
475480
if (!this.sharedContext.InArrange || this.sharedContext.Recorder != null)
@@ -736,7 +741,7 @@ internal TMethodMock Arrange<TMethodMock>(object instance, MethodBase method, ob
736741
{
737742
var result = methodMockFactory();
738743
result.Repository = this;
739-
result.CallPattern = CallPatternCreator.FromMethodBase(instance, method, arguments);
744+
result.CallPattern = CallPatternCreator.FromMethodBase(this, instance, method, arguments);
740745

741746
AddArrange(result);
742747
return result;

Telerik.JustMock/Core/RepositorySharedContext.cs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
JustMock Lite
3-
Copyright © 2010-2015,2018 Progress Software Corporation
3+
Copyright © 2010-2015,2018-2019 Progress Software Corporation
44
55
Licensed under the Apache License, Version 2.0 (the "License");
66
you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@ internal class RepositorySharedContext
3232

3333
private readonly ThreadLocalProperty<IRecorder> recorder = new ThreadLocalProperty<IRecorder>();
3434
private readonly ThreadLocalProperty<object> inArrange = new ThreadLocalProperty<object>();
35+
private readonly ThreadLocalProperty<object> inArrangeArgMatching = new ThreadLocalProperty<object>();
3536
private readonly ThreadLocalProperty<object> dispatchToMethodMocks = new ThreadLocalProperty<object>();
3637
private readonly ThreadLocalProperty<object> inAssertSet = new ThreadLocalProperty<object>();
3738

@@ -47,6 +48,12 @@ public bool InArrange
4748
private set { this.inArrange.Set(value ? (object)value : null); }
4849
}
4950

51+
public bool InArrangeArgMatching
52+
{
53+
get { return this.inArrangeArgMatching.Get() != null; }
54+
private set { this.inArrangeArgMatching.Set(value ? (object)value : null); }
55+
}
56+
5057
public bool InAssertSet
5158
{
5259
get { return this.inAssertSet.Get() != null; }
@@ -73,6 +80,12 @@ public IDisposable StartArrange()
7380
return new InArrangeContext(this);
7481
}
7582

83+
public IDisposable StartArrangeArgMatching()
84+
{
85+
Monitor.Enter(this);
86+
return new InArrangeArgMatchingContext(this);
87+
}
88+
7689
public IDisposable StartAssertSet()
7790
{
7891
Monitor.Enter(this);
@@ -125,7 +138,7 @@ private class InArrangeContext : ContextSession
125138
public InArrangeContext(RepositorySharedContext context)
126139
: base(context)
127140
{
128-
Debug.Assert(!this.Context.InArrange);
141+
Debug.Assert(!this.Context.InArrange);
129142
context.InArrange = true;
130143
}
131144

@@ -136,12 +149,28 @@ public override void Dispose()
136149
}
137150
}
138151

152+
private class InArrangeArgMatchingContext : ContextSession
153+
{
154+
public InArrangeArgMatchingContext(RepositorySharedContext context)
155+
: base(context)
156+
{
157+
Debug.Assert(!this.Context.InArrangeArgMatching);
158+
context.InArrangeArgMatching = true;
159+
}
160+
161+
public override void Dispose()
162+
{
163+
this.Context.InArrangeArgMatching = false;
164+
Monitor.Exit(this.Context);
165+
}
166+
}
167+
139168
private class InAssertSetContext : ContextSession
140169
{
141170
public InAssertSetContext(RepositorySharedContext context)
142171
: base(context)
143172
{
144-
Debug.Assert(!this.Context.InAssertSet);
173+
Debug.Assert(!this.Context.InAssertSet);
145174
context.InAssertSet = true;
146175
}
147176

0 commit comments

Comments
 (0)