1
1
using System ;
2
2
using System . Collections . Generic ;
3
3
using System . Linq ;
4
- using System . Text ;
5
- using System . Threading . Tasks ;
6
4
using BenchmarkDotNet . Attributes ;
5
+ using BenchmarkDotNet . Code ;
6
+ using BenchmarkDotNet . Configs ;
7
+ using BenchmarkDotNet . Jobs ;
8
+ using BenchmarkDotNet . Reports ;
9
+ using BenchmarkDotNet . Running ;
10
+ using BenchmarkDotNet . Toolchains ;
11
+ using BenchmarkDotNet . Toolchains . InProcess . Emit ;
7
12
using Xunit ;
13
+ using Xunit . Abstractions ;
8
14
9
15
namespace BenchmarkDotNet . IntegrationTests
10
16
{
11
17
public class ParamSourceTests : BenchmarkTestExecutor
12
18
{
19
+ public ParamSourceTests ( ITestOutputHelper output ) : base ( output ) { }
20
+
21
+ public static IEnumerable < object [ ] > GetToolchains ( )
22
+ => new [ ]
23
+ {
24
+ new object [ ] { Job . Default . GetToolchain ( ) } ,
25
+ new object [ ] { InProcessEmitToolchain . Instance } ,
26
+ } ;
27
+
13
28
[ Fact ]
14
29
public void ParamSourceCanHandleStringWithSurrogates ( )
15
30
{
@@ -35,5 +50,159 @@ public IEnumerable<string> StringValues
35
50
[ Benchmark ]
36
51
public void Method ( ) { }
37
52
}
53
+
54
+ private Summary CanExecuteWithExtraInfo ( Type type , IToolchain toolchain )
55
+ {
56
+ IConfig config = CreateSimpleConfig ( job : Job . Dry . WithToolchain ( toolchain ) ) ;
57
+ if ( ! toolchain . IsInProcess )
58
+ {
59
+ // Show the relevant codegen excerpt in test results (the *.notcs is not part of the logs)
60
+ Output . WriteLine ( "// Benchmarks and CodeGenerator.GetParamsContent()" ) ;
61
+ BenchmarkRunInfo runInfo = BenchmarkConverter . TypeToBenchmarks ( type , config ) ;
62
+ foreach ( BenchmarkCase benchmarkCase in runInfo . BenchmarksCases )
63
+ {
64
+ Output . WriteLine ( "// " + benchmarkCase . DisplayInfo ) ;
65
+ Output . WriteLine ( CodeGenerator . GetParamsContent ( benchmarkCase ) ) ;
66
+ }
67
+ }
68
+ return CanExecute ( type , config ) ;
69
+ }
70
+
71
+ public interface ITargetInterface
72
+ {
73
+ int Data { get ; }
74
+ }
75
+
76
+ private class NonPublicSource : ITargetInterface
77
+ {
78
+ public int Data { get ; }
79
+ public NonPublicSource ( int data ) => Data = data ;
80
+ public override string ToString ( ) => "src " + Data . ToString ( ) ;
81
+ }
82
+
83
+ public class PrivateClassWithPublicInterface
84
+ {
85
+ public static IEnumerable < ITargetInterface > GetSource ( )
86
+ {
87
+ yield return null ;
88
+ yield return new NonPublicSource ( 1 ) ;
89
+ yield return new NonPublicSource ( 2 ) ;
90
+ }
91
+
92
+ [ ParamsSource ( nameof ( GetSource ) ) ]
93
+ public ITargetInterface ParamsTarget { get ; set ; }
94
+
95
+ [ Benchmark ]
96
+ public int Benchmark ( ) => ParamsTarget ? . Data ?? 0 ;
97
+ }
98
+
99
+ [ Theory , MemberData ( nameof ( GetToolchains ) ) ]
100
+ public void PrivateClassWithPublicInterface_Succeeds ( IToolchain toolchain ) => CanExecuteWithExtraInfo ( typeof ( PrivateClassWithPublicInterface ) , toolchain ) ;
101
+
102
+ public class PrivateClassWithPublicInterface_Array
103
+ {
104
+ public IEnumerable < ITargetInterface [ ] > GetSource ( )
105
+ {
106
+ yield return null ;
107
+ yield return Array . Empty < NonPublicSource > ( ) ;
108
+ yield return new NonPublicSource [ ] { null } ;
109
+ yield return new [ ] { new NonPublicSource ( 1 ) , new NonPublicSource ( 2 ) } ;
110
+ }
111
+
112
+ [ ParamsSource ( nameof ( GetSource ) ) ]
113
+ public ITargetInterface [ ] ParamsTarget { get ; set ; }
114
+
115
+ [ Benchmark ]
116
+ public int Benchmark ( ) => ParamsTarget ? . Sum ( p => p ? . Data ?? 0 ) ?? 0 ;
117
+ }
118
+
119
+ [ Theory , MemberData ( nameof ( GetToolchains ) ) ]
120
+ public void PrivateClassWithPublicInterface_Array_Succeeds ( IToolchain toolchain ) => CanExecuteWithExtraInfo ( typeof ( PrivateClassWithPublicInterface_Array ) , toolchain ) ;
121
+
122
+ public class PrivateClassWithPublicInterface_Enumerable
123
+ {
124
+ public IEnumerable < IEnumerable < ITargetInterface > > GetSource ( )
125
+ {
126
+ static IEnumerable < ITargetInterface > YieldNull ( ) { yield return null ; }
127
+ yield return null ;
128
+ yield return Enumerable . Empty < NonPublicSource > ( ) ;
129
+ yield return YieldNull ( ) ;
130
+ yield return PrivateClassWithPublicInterface . GetSource ( ) ;
131
+ }
132
+
133
+ [ ParamsSource ( nameof ( GetSource ) ) ]
134
+ public IEnumerable < ITargetInterface > ParamsTarget { get ; set ; }
135
+
136
+ [ Benchmark ]
137
+ public int Benchmark ( ) => ParamsTarget ? . Sum ( p => p ? . Data ?? 0 ) ?? 0 ;
138
+ }
139
+
140
+ [ Theory , MemberData ( nameof ( GetToolchains ) ) ]
141
+ public void PrivateClassWithPublicInterface_Enumerable_Succeeds ( IToolchain toolchain ) => CanExecuteWithExtraInfo ( typeof ( PrivateClassWithPublicInterface_Enumerable ) , toolchain ) ;
142
+
143
+ public class PrivateClassWithPublicInterface_AsObject
144
+ {
145
+ public static IEnumerable < object > GetSource ( )
146
+ {
147
+ yield return null ;
148
+ yield return new NonPublicSource ( 1 ) ;
149
+ yield return new NonPublicSource ( 2 ) ;
150
+ }
151
+
152
+ [ ParamsSource ( nameof ( GetSource ) ) ]
153
+ public ITargetInterface ParamsTarget { get ; set ; }
154
+
155
+ [ Benchmark ]
156
+ public int Benchmark ( ) => ParamsTarget ? . Data ?? 0 ;
157
+ }
158
+
159
+ [ Theory , MemberData ( nameof ( GetToolchains ) ) ]
160
+ public void PrivateClassWithPublicInterface_AsObject_Succeeds ( IToolchain toolchain ) => CanExecuteWithExtraInfo ( typeof ( PrivateClassWithPublicInterface_AsObject ) , toolchain ) ;
161
+
162
+ public class PublicSource
163
+ {
164
+ public int Data { get ; }
165
+ public PublicSource ( int data ) => Data = data ;
166
+ // op_Implicit would be meaningless because codegen wouldn't have to do anything.
167
+ public static explicit operator TargetType ( PublicSource @this ) => @this != null ? new TargetType ( @this . Data ) : null ;
168
+ public override string ToString ( ) => "src " + Data . ToString ( ) ;
169
+ }
170
+
171
+ public class TargetType
172
+ {
173
+ public int Data { get ; }
174
+ public TargetType ( int data ) => Data = data ;
175
+ public override string ToString ( ) => "target " + Data . ToString ( ) ;
176
+ }
177
+
178
+ public class SourceWithExplicitCastToTarget
179
+ {
180
+ public static IEnumerable < PublicSource > GetSource ( )
181
+ {
182
+ yield return null ;
183
+ yield return new PublicSource ( 1 ) ;
184
+ yield return new PublicSource ( 2 ) ;
185
+ }
186
+
187
+ [ ParamsSource ( nameof ( GetSource ) ) ]
188
+ public TargetType ParamsTarget { get ; set ; }
189
+
190
+ [ Benchmark ]
191
+ public int Benchmark ( ) => ParamsTarget ? . Data ?? 0 ;
192
+ }
193
+
194
+ [ Fact ]
195
+ public void SourceWithExplicitCastToTarget_DefaultToolchain_Succeeds ( ) => CanExecuteWithExtraInfo ( typeof ( SourceWithExplicitCastToTarget ) , Job . Default . GetToolchain ( ) ) ;
196
+
197
+ [ Fact ]
198
+ public void SourceWithExplicitCastToTarget_InProcessToolchain_Throws ( )
199
+ {
200
+ // op_Explicit is currently not supported by InProcessEmitToolchain
201
+ // See TryChangeType() in Toolchains/InProcess.Emit.Implementation/Runnable/RunnableReflectionHelpers.cs
202
+ // If that changes, this test and the one above should be merged into:
203
+ // [Theory, MemberData(nameof(GetToolchains))]
204
+ // public void SourceWithExplicitCastToTarget_Succeeds(IToolchain toolchain) => CanExecuteWithExtraInfo(typeof(SourceWithExplicitCastToTarget), toolchain);
205
+ Assert . ThrowsAny < Exception > ( ( ) => CanExecuteWithExtraInfo ( typeof ( SourceWithExplicitCastToTarget ) , InProcessEmitToolchain . Instance ) ) ;
206
+ }
38
207
}
39
208
}
0 commit comments