/// <summary> /// Creates the singleton dynamic test. /// </summary> /// <param name="runner">The runner.</param> /// <param name="il">The il.</param> private static void CreateSingleton(MethodRunner runner, ILGenerator il) { // Set up the call to the method. il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.EmitCall(OpCodes.Call, runner.Method, null); }
private void ParseTimingBaseline( MethodSignature methodSignature, Attribute attribute, MethodRunner methodRunner) { if (!(attribute is TimingBaselineAttribute)) { return; } switch (methodSignature) { case MethodSignature.Zero: baselineMethods[0] = methodRunner; break; case MethodSignature.CountInt32: baselineMethods[1] = methodRunner; break; case MethodSignature.CountIterationInt32: baselineMethods[2] = methodRunner; break; } }
/// <summary> /// Parses the method info object and adds the appropriate tests. /// </summary> /// <param name="method">The method.</param> private void ParseMethod(MethodInfo method) { // Make sure we have a valid signature. MethodSignature methodSignature = GetMethodSignature(method); if (methodSignature == MethodSignature.Unknown) { return; } // Get the attributes for the method. var methodRunner = new MethodRunner(this, method, fixture, methodSignature); foreach (Attribute attribute in method.GetCustomAttributes(false)) { // Check for [TimingFixtureSetup]. ParseTimingFixtureSetup(method, methodSignature, attribute); // Check for [TimingFixtureTeardown]. ParseTimingFixtureTeardown(method, methodSignature, attribute); // Check for [TimingSetup]. ParseTimingSetup(method, methodSignature, attribute, methodRunner); // Check for [TimingTeardown]. ParseTimingTeardown(method, methodSignature, attribute, methodRunner); // Check for [TimingBaseline]. ParseTimingBaseline(methodSignature, attribute, methodRunner); // Check for [Timing] ParseTiming(attribute, methodRunner); } }
private void ParseTiming(Attribute attribute, MethodRunner methodRunner) { if (!(attribute is TimingAttribute)) { return; } // Add this as an actual timing unit. methodRunner.TimingAttribute = (TimingAttribute)attribute; methods.Add(methodRunner); // Report that this method has been added. runner.StatusListener.AddTimingMethod(methodRunner); }
/// <summary> /// Assigns the default baselines if one hasn't already been assigned. /// </summary> private void AssignDefaultBaselines() { if (baselineMethods[0] == null) { MethodInfo zeroMethod = GetType().GetMethod("Baseline", new Type[] { }); baselineMethods[0] = new MethodRunner(this, zeroMethod, this, MethodSignature.Zero); } if (baselineMethods[1] == null) { MethodInfo countMethod = GetType().GetMethod("Baseline", new[] { typeof(int) }); baselineMethods[1] = new MethodRunner(this, countMethod, this, MethodSignature.CountInt32); } if (baselineMethods[2] == null) { MethodInfo countIterationMethod = GetType().GetMethod("Baseline", new[] { typeof(int), typeof(int) }); baselineMethods[2] = new MethodRunner(this, countIterationMethod, this, MethodSignature.CountIterationInt32); } }
private void ParseTimingTeardown( MethodInfo method, MethodSignature methodSignature, Attribute attribute, MethodRunner methodRunner) { if (!(attribute is TimingTeardownAttribute)) { return; } switch (methodSignature) { case MethodSignature.Zero: case MethodSignature.CountInt32: teardownMethods.Add(methodRunner); break; default: runner.StatusListener.Error( "{0}: [TimingTeardown] takes zero or one integer.", method.Name); break; } }
private void ParseTiming(Attribute attribute, MethodRunner methodRunner) { if (!(attribute is TimingAttribute)) { return; } // Add this as an actual timing unit. methodRunner.TimingAttribute = (TimingAttribute) attribute; methods.Add(methodRunner); // Report that this method has been added. runner.StatusListener.AddTimingMethod(methodRunner); }
/// <summary> /// Creates a dynamic method for testing units. All units take the same parameters. /// </summary> /// <param name="runner">The runner.</param> /// <returns></returns> public static DynamicUnitTiming CreateTestMethod(MethodRunner runner) { // Create the basic signature. var signature = new[] { typeof(object), typeof(int) }; var method = new DynamicMethod("DynamicUnitTest" + (counter++), typeof(void), signature, typeof(MethodRunnerCompiler)); // Create an IL generator for the method body. ILGenerator il = method.GetILGenerator(256); // We determine what type of IL code we generate based on the singleton type. if (runner.TimingAttribute.Singleton) { // Create a single call version. CreateSingleton(runner, il); } else { // Create the local variables. il.DeclareLocal(typeof(int)); il.DeclareLocal(typeof(bool)); // Declare the labels. Label loopLabel = il.DefineLabel(); Label topLabel = il.DefineLabel(); // Assign zero to the count variable. il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Br_S, loopLabel); // Build up the actual execution. il.MarkLabel(topLabel); // Figure out how to call this method. il.Emit(OpCodes.Ldarg_0); switch (runner.MethodSignature) { case MethodSignature.CountInt32: il.Emit(OpCodes.Ldloc_0); break; case MethodSignature.CountIterationInt32: il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldarg_1); break; } il.EmitCall(OpCodes.Call, runner.Method, null); // Increment the counter. il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_0); // Create the loop test. This loads the count variable and compares // it to the second argument (iterations). il.MarkLabel(loopLabel); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Clt); il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Ldloc_1); il.Emit(OpCodes.Brtrue_S, topLabel); } // Finish up with a return IL. il.Emit(OpCodes.Ret); // Create the paramters. method.DefineParameter(0, ParameterAttributes.In, "target"); method.DefineParameter(1, ParameterAttributes.In, "iteration"); // Create the delegate and return it. return (DynamicUnitTiming) method.CreateDelegate(typeof(DynamicUnitTiming)); }
/// <summary> /// Creates a dynamic method for testing units. All units take the same parameters. /// </summary> /// <param name="runner">The runner.</param> /// <returns></returns> public static DynamicUnitTiming CreateTestMethod(MethodRunner runner) { // Create the basic signature. var signature = new[] { typeof(object), typeof(int) }; var method = new DynamicMethod("DynamicUnitTest" + (counter++), typeof(void), signature, typeof(MethodRunnerCompiler)); // Create an IL generator for the method body. ILGenerator il = method.GetILGenerator(256); // We determine what type of IL code we generate based on the singleton type. if (runner.TimingAttribute.Singleton) { // Create a single call version. CreateSingleton(runner, il); } else { // Create the local variables. il.DeclareLocal(typeof(int)); il.DeclareLocal(typeof(bool)); // Declare the labels. Label loopLabel = il.DefineLabel(); Label topLabel = il.DefineLabel(); // Assign zero to the count variable. il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Br_S, loopLabel); // Build up the actual execution. il.MarkLabel(topLabel); // Figure out how to call this method. il.Emit(OpCodes.Ldarg_0); switch (runner.MethodSignature) { case MethodSignature.CountInt32: il.Emit(OpCodes.Ldloc_0); break; case MethodSignature.CountIterationInt32: il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldarg_1); break; } il.EmitCall(OpCodes.Call, runner.Method, null); // Increment the counter. il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_0); // Create the loop test. This loads the count variable and compares // it to the second argument (iterations). il.MarkLabel(loopLabel); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Clt); il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Ldloc_1); il.Emit(OpCodes.Brtrue_S, topLabel); } // Finish up with a return IL. il.Emit(OpCodes.Ret); // Create the paramters. method.DefineParameter(0, ParameterAttributes.In, "target"); method.DefineParameter(1, ParameterAttributes.In, "iteration"); // Create the delegate and return it. return((DynamicUnitTiming)method.CreateDelegate(typeof(DynamicUnitTiming))); }