Skip to content

Commit 00721d9

Browse files
committed
benchmark e2e tests
1 parent acb9e7b commit 00721d9

File tree

3 files changed

+136
-17
lines changed

3 files changed

+136
-17
lines changed

Proxii.Test/Integration/Interceptors/BenchmarkInterceptortest.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ namespace Proxii.Test.Integration.Interceptors
1212
public class BenchmarkInterceptorTest
1313
{
1414
// ensure it's within 1 microsecond of the correct timing
15-
private const double TimingEpsilon = .001;
15+
private const double TimingEpsilon = .005;
1616

1717
private readonly ProxyGenerator _generator = new ProxyGenerator();
1818

1919
[TestMethod]
20-
public void BenchmarkInterceptor_CallsWithAccurateTiming()
20+
public void BenchmarkInterceptor_RecordsAccurateTiming()
2121
{
2222
// so we can independently take the two timings
2323
double normalTiming = 0, proxyTiming = 0;
@@ -88,7 +88,7 @@ private bool EpsilonEqual(double epsilon, double a, double b)
8888
return Math.Abs(a - b) <= epsilon;
8989
}
9090

91-
private double TakeDoTiming(IBenchmarkTestObject obj, int times = 1)
91+
private double TakeDoTiming(IBenchmarkTestObject obj)
9292
{
9393
double timing;
9494

@@ -107,25 +107,25 @@ private double TakeDoTiming(IBenchmarkTestObject obj, int times = 1)
107107

108108
return timing;
109109
}
110+
}
110111

111-
public class BenchmarkTestObject : IBenchmarkTestObject
112+
public class BenchmarkTestObject : IBenchmarkTestObject
113+
{
114+
public void Do()
112115
{
113-
public void Do()
114-
{
115-
Thread.Sleep(300);
116-
}
117-
118-
public void Do(int i, string s)
119-
{
120-
Thread.Sleep(300);
121-
}
116+
Thread.Sleep(300);
122117
}
123118

124-
public interface IBenchmarkTestObject
119+
public void Do(int i, string s)
125120
{
126-
void Do();
127-
128-
void Do(int i, string s);
121+
Thread.Sleep(300);
129122
}
130123
}
124+
125+
public interface IBenchmarkTestObject
126+
{
127+
void Do();
128+
129+
void Do(int i, string s);
130+
}
131131
}

Proxii.Test/Proxii.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
<ItemGroup>
5858
<Compile Include="e2e\ProxiiAfterInvokeTest.cs" />
5959
<Compile Include="e2e\ProxiiBeforeInvokeTest.cs" />
60+
<Compile Include="e2e\ProxiiBenchmarkTest.cs" />
6061
<Compile Include="e2e\ProxiiByArgumentTypeTest.cs" />
6162
<Compile Include="e2e\ProxiiByMethodNamePatternTest.cs" />
6263
<Compile Include="e2e\ProxiiByMethodNameTest.cs" />
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.Linq;
5+
using System.Reflection;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using Castle.DynamicProxy;
9+
using Microsoft.VisualStudio.TestTools.UnitTesting;
10+
using Proxii.Library.Interceptors;
11+
using Proxii.Test.Integration.Interceptors;
12+
13+
namespace Proxii.Test.e2e
14+
{
15+
[TestClass]
16+
public class ProxiiBenchmarkTest
17+
{
18+
// TODO encapsulate benchmark test behavior in its own class
19+
20+
// ensure it's within 1 microsecond of the correct timing
21+
private const double TimingEpsilon = .005;
22+
23+
[TestMethod]
24+
public void Proxii_Benchmark_RecordsAccurateTiming()
25+
{
26+
// so we can independently take the two timings
27+
double normalTiming = 0, proxyTiming = 0;
28+
29+
Action<double> proxyTimingAction = (d) => proxyTiming = d;
30+
31+
// create the object normally
32+
var normalObject = new BenchmarkTestObject();
33+
34+
// create a proxy
35+
var proxy = Proxii.Proxy<IBenchmarkTestObject, BenchmarkTestObject>()
36+
.Benchmark(proxyTimingAction)
37+
.Create();
38+
39+
// take timing via interceptor
40+
proxy.Do();
41+
42+
// take timing manually
43+
normalTiming = TakeDoTiming(normalObject);
44+
45+
// ensure the interceptor at least called the action
46+
Assert.AreNotEqual(0, proxyTiming, "proxy timing is set");
47+
48+
// ensure the interceptor gave an accurate timing
49+
Assert.IsTrue(EpsilonEqual(TimingEpsilon, normalTiming, proxyTiming));
50+
}
51+
52+
[TestMethod]
53+
public void BenchmarkInterceptor_CallsWithCorrectMethodInfo()
54+
{
55+
string result = null;
56+
57+
Action<double, MethodInfo> proxyTimingAction = (d, m) => result = m.Name;
58+
59+
// create a proxy
60+
var proxy = Proxii.Proxy<IBenchmarkTestObject, BenchmarkTestObject>()
61+
.Benchmark(proxyTimingAction)
62+
.Create();
63+
64+
proxy.Do();
65+
66+
Assert.AreEqual("Do", result);
67+
}
68+
69+
[TestMethod]
70+
public void BenchmarkInterceptor_CallsWithCorrectMethodInfoAndArguments()
71+
{
72+
string result = null;
73+
74+
Action<double, MethodInfo, object[]> proxyTimingAction = (d, m, args) => result = $"called method {m.Name} with arguments ({string.Join(", ", args)})";
75+
76+
// create a proxy
77+
var proxy = Proxii.Proxy<IBenchmarkTestObject, BenchmarkTestObject>()
78+
.Benchmark(proxyTimingAction)
79+
.Create();
80+
81+
proxy.Do(1, "foo");
82+
83+
Assert.AreEqual("called method Do with arguments (1, foo)", result);
84+
}
85+
86+
private double TakeDoTiming(IBenchmarkTestObject obj)
87+
{
88+
double timing;
89+
90+
var stopwatch = Stopwatch.StartNew();
91+
92+
// time the proxy
93+
try
94+
{
95+
obj.Do();
96+
}
97+
finally
98+
{
99+
stopwatch.Stop();
100+
timing = stopwatch.ElapsedMilliseconds;
101+
}
102+
103+
return timing;
104+
}
105+
106+
/// <summary>
107+
/// compares two doubles for equality, allowing for a maximum difference of epsilon
108+
/// </summary>
109+
/// <param name="epsilon">maximum difference allowed for the numbers to be considered equal (inclusive)</param>
110+
/// <param name="a"></param>
111+
/// <param name="b"></param>
112+
/// <returns>true if the numbers fall within epsilon range of one another</returns>
113+
private bool EpsilonEqual(double epsilon, double a, double b)
114+
{
115+
return Math.Abs(a - b) <= epsilon;
116+
}
117+
}
118+
}

0 commit comments

Comments
 (0)