License
Microsoft Research License Agreement
Non-Commercial Use Only
Pex
_______________________________________________________
This Microsoft Research License Agreement, including all exhibits ("MSR-LA") is a legal agreement between you and Microsoft Corporation (“Microsoft” or “we”) for the software or data identified above, which may include source code, and any associated materials, text or speech files, associated media and "online" or electronic documentation and any updates we provide in our discretion (together, the "Software").
By installing, copying, or otherwise using this Software, found at http://research.microsoft.com/downloads, you agree to be bound by the terms of this MSR-LA. If you do not agree, do not install copy or use the Software. The Software is protected by copyright and other intellectual property laws and is licensed, not sold.
SCOPE OF RIGHTS:
You may use, copy, reproduce, and distribute this Software for any non-commercial purpose, subject to the restrictions in this MSR-LA. Some purposes which can be non-commercial are teaching, academic research, public demonstrations and personal experimentation. You may also distribute this Software with books or other teaching materials, or publish the Software on websites, that are intended to teach the use of the Software for academic or other non-commercial purposes.
You may not use or distribute this Software or any derivative works in any form for commercial purposes. Examples of commercial purposes would be running business operations, licensing, leasing, or selling the Software, distributing the Software for use with commercial products, using the Software in the creation or use of commercial products or any other activity which purpose is to procure a commercial gain to you or others.
If the Software includes source code or data, you may create derivative works of such portions of the Software and distribute the modified Software for non-commercial purposes, as provided herein.
If you distribute the Software or any derivative works of the Software, you will distribute them under the same terms and conditions as in this license, and you will not grant other rights to the Software or derivative works that are different from those provided by this MSR-LA.
If you have created derivative works of the Software, and distribute such derivative works, you will cause the modified files to carry prominent notices so that recipients know that they are not receiving the original Software. Such notices must state: (i) that you have changed the Software; and (ii) the date of any changes.
In return, we simply require that you agree:
1. That you will not remove any copyright or other notices from the Software.
2. That if any of the Software is in binary format, you will not attempt to modify such portions of the Software, or to reverse engineer or decompile them, except and only to the extent authorized by applicable law.
3. That Microsoft is granted back, without any restrictions or limitations, a non-exclusive, perpetual, irrevocable, royalty-free, assignable and sub-licensable license, to reproduce, publicly perform or display, install, use, modify, post, distribute, make and have made, sell and transfer your modifications to and/or derivative works of the Software source code or data, for any purpose.
4. That any feedback about the Software provided by you to us is voluntarily given, and Microsoft shall be free to use the feedback as it sees fit without obligation or restriction of any kind, even if the feedback is designated by you as confidential.
5. THAT THE SOFTWARE COMES "AS IS", WITH NO WARRANTIES. THIS MEANS NO EXPRESS, IMPLIED OR STATUTORY WARRANTY, INCLUDING WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ANY WARRANTY AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE SOFTWARE OR ANY WARRANTY OF TITLE OR NON-INFRINGEMENT. THERE IS NO WARRANTY THAT THIS SOFTWARE WILL FULFILL ANY OF YOUR PARTICULAR PURPOSES OR NEEDS. ALSO, YOU MUST PASS THIS DISCLAIMER ON WHENEVER YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS.
6. THAT NEITHER MICROSOFT NOR ANY CONTRIBUTOR TO THE SOFTWARE WILL BE LIABLE FOR ANY DAMAGES RELATED TO THE SOFTWARE OR THIS MSR-LA, INCLUDING DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL OR INCIDENTAL DAMAGES, TO THE MAXIMUM EXTENT THE LAW PERMITS, NO MATTER WHAT LEGAL THEORY IT IS BASED ON. ALSO, YOU MUST PASS THIS LIMITATION OF LIABILITY ON WHENEVER YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS.
7. That we have no duty of reasonable care or lack of negligence, and we are not obligated to (and will not) provide technical support for the Software.
8. That if you breach this MSR-LA or if you sue anyone over patents that you think may apply to or read on the Software or anyone's use of the Software, this MSR-LA (and your license and rights obtained herein) terminate automatically. Upon any such termination, you shall destroy all of your copies of the Software immediately. Sections 3, 4, 5, 6, 7, 8, 11 and 12 of this MSR-LA shall survive any termination of this MSR-LA.
9. That the patent rights, if any, granted to you in this MSR-LA only apply to the Software, not to any derivative works you make.
10. That the Software may be subject to U.S. export jurisdiction at the time it is licensed to you, and it may be subject to additional export or import laws in other places. You agree to comply with all such laws and regulations that may apply to the Software after delivery of the software to you.
11. That all rights not expressly granted to you in this MSR-LA are reserved.
12. That this MSR-LA shall be construed and controlled by the laws of the State of Washington, USA, without regard to conflicts of law. If any provision of this MSR-LA shall be deemed unenforceable or contrary to law, the rest of this MSR-LA shall remain in full effect and interpreted in an enforceable manner that most nearly captures the intent of the original language.
Copyright (c) Microsoft Corporation. All rights reserved.
Revised September 15, 2006
_______________________________________________________
Microsoft Automatic Graph Layout 2007
This Microsoft Research Shared Source license agreement ("MSR-SSLA") is a legal agreement between you and Microsoft Corporation ("Microsoft" or "we") for the software or data identified above, which may include source code, and any associated materials, text or speech files, associated media and "online" or electronic documentation and any updates we provide in our discretion (together, the "Software").
By installing this software you agree to these terms. If you do not agree, do not install, copy or use the Software. The Software is protected by copyright and other intellectual property laws and is licensed, not sold.
SCOPE OF RIGHTS:
You may use, copy, reproduce, and distribute this Software for any non-commercial purpose, subject to the restrictions in this MSR-SSLA. Some purposes which can be non-commercial are teaching, academic research, public demonstrations and personal experimentation. You may also distribute this Software with books or other teaching materials, or publish the Software on websites, that are intended to teach the use of the Software for academic or other non-commercial purposes.
You may not use or distribute this Software or any derivative works in any form for commercial purposes. Examples of commercial purposes would be running business operations, licensing, leasing, or selling the Software, distributing the Software for use with commercial products, using the Software in the creation or use of commercial products or any other activity which purpose is to procure a commercial gain to you or others.
If the Software includes source code or data, you may create derivative works of such portions of the Software and distribute the modified Software for non-commercial purposes, as provided herein.
In return, we simply require that you agree:
1. That you will not remove any copyright or other notices from the Software.
2. That if any of the Software is in binary format, you will not attempt to modify such portions of the Software, or to reverse engineer or decompile them, except and only to the extent authorized by applicable law.
3. That if you distribute the Software or any derivative works of the Software, you will distribute them under the same terms and conditions as in this license, and you will not grant other rights to the Software or derivative works that are different from those provided by this MSR-SSLA.
4. That if you have created derivative works of the Software, and distribute such derivative works, you will cause the modified files to carry prominent notices so that recipients know that they are not receiving the original Software. Such notices must state: (i) that you have changed the Software; and (ii) the date of any changes.
5. That Microsoft is granted back, without any restrictions or limitations, a non-exclusive, perpetual, irrevocable, royalty-free, assignable and sub-licensable license, to reproduce, publicly perform or display, install, use, modify, distribute, make and have made, sell and transfer your modifications to and/or derivative works of the Software source code or data, for any purpose.
6. That any feedback about the Software provided by you to us is voluntarily given, and Microsoft shall be free to use the feedback as it sees fit without obligation or restriction of any kind, even if the feedback is designated by you as confidential.
7. THAT THE SOFTWARE COMES "AS IS", WITH NO WARRANTIES. THIS MEANS NO EXPRESS, IMPLIED OR STATUTORY WARRANTY, INCLUDING WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ANY WARRANTY AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE SOFTWARE OR ANY WARRANTY OF TITLE OR NON-INFRINGEMENT. THERE IS NO WARRANTY THAT THIS SOFTWARE WILL FULFILL ANY OF YOUR PARTICULAR PURPOSES OR NEEDS. ALSO, YOU MUST PASS THIS DISCLAIMER ON WHENEVER YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS.
8. THAT NEITHER MICROSOFT NOR ANY CONTRIBUTOR TO THE SOFTWARE WILL BE LIABLE FOR ANY DAMAGES RELATED TO THE SOFTWARE OR THIS MSR-SSLA, INCLUDING DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL OR INCIDENTAL DAMAGES, TO THE MAXIMUM EXTENT THE LAW PERMITS, NO MATTER WHAT LEGAL THEORY IT IS BASED ON. ALSO, YOU MUST PASS THIS LIMITATION OF LIABILITY ON WHENEVER YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS.
9. That we have no duty of reasonable care or lack of negligence, and we are not obligated to (and will not) provide technical support for the Software.
10. That if you breach this MSR-SSLA or if you sue anyone over patents that you think may apply to or read on the Software or anyone's use of the Software, this MSR-SSLA (and your license and rights obtained herein) terminate automatically. Upon any such termination, you shall destroy all of your copies of the Software immediately. Sections 5, 6, 7, 8, 9, 10, 13 and 14 of this MSR-SSLA shall survive any termination of this MSR-SSLA.
11. That the patent rights, if any, granted to you in this MSR-SSLA only apply to the Software, not to any derivative works you make.
12. That the Software may be subject to U.S. export jurisdiction at the time it is licensed to you, and it may be subject to additional export or import laws in other places. You agree to comply with all such laws and regulations that may apply to the Software after delivery of the software to you.
13. That all rights not expressly granted to you in this MSR-SSLA are reserved.
14. That this MSR-SSLA shall be construed and controlled by the laws of the State of Washington, USA, without regard to conflicts of law. If any provision of this MSR-SSLA shall be deemed unenforceable or contrary to law, the rest of this MSR-SSLA shall remain in full effect and interpreted in an enforceable manner that most nearly captures the intent of the original language.
Copyright (c) Microsoft Corporation. All rights reserved.
Mocks
How to test a method which has a parameter of an interface type? Or of a non-sealed class? We don't know which implementations will later be used when this method is called! And maybe we don't even have any real implementation available at test time.
The conventional answer: mock objects with explicit behavior
A
mock object implements an interface (or extends a non-sealed class). It does not represent a real implementation, but just a shortcut that allows the execution of tests using the mock object. It's behavior is manually written as part of the each test case where it is used. Many tools exist which make it easier to write such mock objects and their expected behavior. But it must still be written by hand.
Generated mock objects with generated behavior
Instead of manually writing the expected behavior of a mock object for each individual test case, Pex can generate relevant behavior:
Choose and Replay
Pex mocks have two different execution modes:
- choosing, when exploring code, Pex mocks are a source of additional test inputs, and Pex will try its best to choose interesting values,
- replay, when executing a previously generated test, Pex mocks behave like stubs with behavior (i.e. predefined behavior).
Pex comes with a
wizard that can automatically generate those mocks.
Example
Let's illustrate this with a simple mock of a toy interface
INamed:
interface INamed {
string GetName();
}
Writing the mock
The mock for this interface looks as follows:
[PexMock] // specifies to Pex that this type is a mock
public class MNamed : INamed {
public string GetName() {
IPexMethodCallOracle call = PexOracle.MethodCall(this);
return call.ChooseResult<string>();
}
}
So what did we do really... The mock implementation of
GetName fetches a oracle (i.e. an interface from which new values can be queried).
IPexMethodCallOracle call = PexOracle.MethodCall(this);
The oracle can be used to
choose new values. It's like adding parameters to the test, but not through the signature. In this case, we ask Pex to get a new
result value.
return call.ChooseResult<string>();
Let's try it!
The following test takes a
INamed instance (which we assumed to be non-null) and displays a message on the console if the name is 'Marc'. Notice that the test was also tagged with the
PexUseType to tell Pex that the
MNamed type can be used, which will be needed to get a
INamed instance.
[PexMethod, PexUseType(typeof(MNamed))]
public void GetName([PexAssumeNotNull]INamed name) {
if (name.GetName() == "Marc")
Console.WriteLine("hello marc");
}
Generated tests
Pex generates 2 unit tests that cover that method.
The first test has
GetName return a default value. The second generated test is more interesting as it shows how Pex sets up the behavior of the
replay stub:
// test 2
MockTest.MNamed mn0 = new MockTest.MNamed();
IPexOracleRecorder oracle = PexOracle.NewTest();
oracle.OnCall(0, "MNamed.GetName()")
.Returns("Marc");
this.GetName(mn0);
The
oracle instance is used to set up the result value on the first call to GetName:
// on the call '0' to the method GetName of MockType.MNamed,
oracle.OnCall(0, "MNamed.GetName()")
// return "Marc"
.Returns("Marc");
Adding behavior
Behavior can simply be added to mock as code since Pex will explore the mock code as well. For example, let's refine the
MNamed implementation to always return the same name:
[PexMock] // specifies to pex that this type is a mock
public class MNamed : INamed {
private string name;
public string GetName() {
if(this.name == null)
this.name = PexOracle.MethodCall(this).ChooseNotNull<string>("name");
return this.name;
}
}
Note that we no longer choose a
result value, but make a named choice (with the name 'name'). It doesn't matter much to Pex, it just changes the generated code that sets up the mock objects.
More on mocks
The following topics discuss how to mock particular elements:
See Also
Martin Fowler's Mocks Aren't Stubs ,
AppendFormat.
Overview
The
ClrMonitor is an unmanaged COM component that implements the
CLR profiling API. It uses this API mainly to rewrite
MSIL instructions of selected methods, types or assemblies on-the-fly at JIT time. It can redirect calls and insert callbacks in the
MSIL instruction sequence, enabling the observation of the execution of the program at a fine grained level:
- (Static) calls can be redirected. The redirection target may call the original call target.
- Similar to the standard CLR profiling API, the ClrMonitor monitors when a method is entered or exited.
- It also monitors the concrete parameter values that are passed to a monitored method.
- The execution of every instruction can be monitored.
- The control flow is monitored, i.e. the evaluation of all explicit conditional branches, and of all implicit checks that can cause exceptions.
- Every monitored event causes a callback into the core Microsoft.ExtendedReflection assembly, which can dispatch the callbacks to a user-provided Execution Monitor.
Code instrumentation
The instruction sequence of each instrumented method is rewritten. It starts by inserted instructions which check whether monitoring is currently on. If not, the original instructions are executed. It if it turned on, the instrumented version of the instructions is execution, starting with a callback to
EnterMethod(m, c), and eventually finished by a callback to
LeaveMethod(m), where
m identifies the current method, and
c is the number of branch identifiers that the instrumented code will refer to within the method body.
EnterMethod returns a Boolean value that indicates whether the monitor is interested in the concrete arguments to the method. If it returns true, a sequence of calls to
Argument<T>(i, v),
ArgumentPtr(i, v, t),
ArgumentTypedReference(i, v) and
ArgumentByRef<T>(i, a) is inserted, one for each argument, where
i is the index of the argument,
v is a value,
t a type, and
a a managed pointer.
Each exception filter starts with a callback to
StartFilter(r) where
r is the reference to the exception object that is currently being filtered. Each exception handler starts with a callback to
StartExceptionHandler(r).
Each instruction that can throw a
NullReferenceException,
InvalidCastException,
IndexOutOfRangeException,
ArrayTypeMismatchException,
DivideByZeroException or
OverflowException is immediately followed by a callback that indicates that the instruction did not throw the exception. Also, all such instructions are surrounded by an exception handler, that catches the corresponding exception type, performs a callback to a method that indicates that the exception was thrown, and rethrows the exception.
See the file
checks.def in the
Microsoft.ExtendedReflection.ClrMonitor project for detailed information about which instructions may throw which exceptions.
In general, each instruction causes a callback named after the instruction itself. The callback is issued before the execution of the actual instruction.
In order to capture all relevant information to track the execution path taken by the program, some instructions get a
special treatment.
Substitutions
Call instruction in instrumented
MSIL code can be redirected. Read more
here.
Setup
In order for code to be monitored, certain environment variables must be set before the process starts:
COR_ENABLE_PROFILING=1
COR_PROFILER={C1DAAFC4-10C6-4838-9F89-435E2120F5F1}
CLRMONITOR_FLAGS={flags that decide the extend of the instrumentation}
- which type and assemblies should be instrumented?
CLRMONITOR_INSTRUMENT_TYPES={comma-separated list of type names; case matters; generic types must end in '`n' annotations; nested types are separated by '+'; <Module> stands for all module-level members}
CLRMONITOR_INSTRUMENT_ASSEMBLIES={comma-separated list of display names of assemblies; case does not matter; use '*' for all assemblies}
CLRMONITOR_INSTRUMENT_TYPES_EXCLUSIONS={list of types which should not be instrumented, despite the above}
CLRMONITOR_INSTRUMENT_ASSEMBLIES_EXCLUSIONS={list of assemblies which should not be instrumented, despite the above}
CLRMONITOR_DISABLE_MSCORLIB_SUPPRESSIONS=1, disable mscorlib exclusions. Use with *Great* care.
- which types and assemblies should be instrumented so that values can be injected at any place in the execution
CLRMONITOR_INJECT_TYPES={comma-separated list of type names; case matters; generic types must end in '`n' annotations; nested types are separated by '+'; <Module> stands for all module-level members}
CLRMONITOR_INJECT_ASSEMBLIES={comma-separated list of display names of assemblies; case does not matter; use '*' for all assemblies}
CLRMONITOR_INJECT_TYPES_EXCLUSIONS={list of types which should not be instrumented, despite the above}
CLRMONITOR_INJECT_ASSEMBLIES_EXCLUSIONS={list of assemblies which should not be instrumented, despite the above}
CLRMONITOR_SUBSTITUTIONS={comma-separated list of file names, pointing to assemblies containing substitutions}
- which instructions should be monitored by inserted callbacks?
See
here for a detailed description of possible
CLRMONITOR_FLAGS.
The class
Monitoring.Controller in the
Microsoft.ExtendedReflection project provides support to check if code in the current process can be monitored, and to setup monitoring for a new process.
Activation
There are two ways to direct the instrumented code's callbacks to a user-written managed class:
- In a running process, the Monitoring.Controller class provides Start and Stop methods to direct the callbacks to a particular Execution Monitor and to stop the redirection.
- When the following environment variables are set, a user-provided Execution Monitor is loaded automatically into any monitored process. Note that in addition to setting up the environment variables, the Microsoft.ExtendedReflection assembly must either be in the monitored process' application directory, or in the GAC.
CLRMONITOR_USER_ASSEMBLY={file name of assembly containing [Execution Monitor]}
CLRMONITOR_USER_TYPE={type in assembly implementing [Execution Monitor]}
Logging (Only available in Debug-builds)
If compiled in Debug configuration, setting the environment variable
CLRMONITOR_LOGFILE={filename}
CLRMONITOR_VERBOSE=1
causes detailed information about the code instrumentation to be stored in the indicated file.
Debugging (Only available in Debug-builds)
If set, this environment variable will cause the
ClrMonitor to break into the debugger when launched.