Imported Upstream version 5.4.0.167

Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-08-21 15:34:15 +00:00
parent e49d6f06c0
commit 536cd135cc
12856 changed files with 563812 additions and 223249 deletions

View File

@ -28,3 +28,4 @@ Pull Requests
* **DO** ensure each commit successfully builds. The entire PR must pass all tests in the Continuous Integration (CI) system before it'll be merged.
* **DO** address PR feedback in an additional commit(s) rather than ammending the existing commits, and only rebase/squash them when necessary. This makes it easier for reviewers to track changes. If necessary, squashing should be handled by the merger using the ["squash and merge"](https://github.com/blog/2141-squash-your-commits) feature, and should only be done by the contributor upon request.
* **DO NOT** fix merge conflicts using a merge commit. Prefer `git rebase`.
* **DO NOT** mix independent, unrelated changes in one PR. Separate real product/test code changes from larger code formatting/dead code removal changes. Separate unrelated fixes into separate PRs, especially if they are in different assemblies.

View File

@ -0,0 +1,255 @@
Cross-Platform Cryptography
===========================
Cryptographic operations in .NET are performed by existing system libraries.
As with most technological decisions, there are various pros and cons.
Since the system already has a vested interest in making the cryptography libraries safe from security vulnerabilities,
and already has an update mechanism that system administrators should be using, .NET gets to benefit from this reliability.
Users who have requirements to use FIPS-validated algorithm implementations also get that benefit for free (when the system
libraries are FIPS-validated, of course).
The biggest con is that not all system libraries offer the same capabilities.
While the core capabilities are present across the various platforms, there are some rough edges.
### Versioning
In .NET Core 1.0 and .NET Core 1.1 the macOS implementation of the cryptography classes was based on OpenSSL.
In .NET Core 2.0 the dependency was changed to use Apple's Security.framework.
Within this document "macOS" should use the values for "Linux" if running .NET Core 1.x, as .NET Core uses OpenSSL in all Linux versions.
## Hash Algorithms
Hash algorithms, and HMAC algorithms, are very standard bytes-in-bytes-out operations.
All hash algorithm (and HMAC) classes in .NET Core defer to the system libraries (including the \*Managed classes).
While the various system libraries may have different performance, there should not be concerns of compatibility.
In the future there is a possibility that new hash algorithms may be added to .NET Core before one (or more) supported platforms have system support for the algorithm.
This would result in a `PlatformNotSupportedException` when invoking the `Create()` method for the algorithm.
## Symmetric Encryption
The underlying ciphers and chaining are performed by the system libraries.
| Cipher + Mode | Windows | Linux | macOS |
|---------------|---------|-------|-------|
| AES-CBC | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| AES-ECB | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| 3DES-CBC | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| 3DES-ECB | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| DES-CBC | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| DES-ECB | :white_check_mark: | :white_check_mark: | :white_check_mark: |
In the future there is a possibility that new ciphers may be added to .NET Core before one (or more) supported platforms have system support for it.
This would result in a `PlatformNotSupportedException` when invoking the `Create()` method for the algorithm.
In the future there is a possibility that new cipher/chaining modes may be added to .NET Core before one (or more) supported platforms have system support for it.
This would result in a `PlatformNotSupportedException` when invoking the `CreateEncryptor()` or `CreateDecryptor()` methods for the algorithm (or overloads to those methods).
In the future there is a possibility that new cipher/chaining modes may be added to .NET Core and that these new modes may not apply to all symmetric algorithms.
This would likely result in a `NotSupportedException` when using the set-accessor of the `Mode` property on the `SymmetricAlgorithm` object, but this prediction is subject to change.
## Asymmetric Cryptography
### RSA
RSA key generation is performed by the system libraries, and is subject to size limitations and performance characteristics thereof.
RSA key operations are performed by the system libraries, and the types of key that may be loaded are subject to system requirements.
.NET Core does not expose "raw" (unpadded) RSA operations, and .NET Core relies on the system libraries for encryption (and decryption) padding.
Not all platforms support the same padding options.
| Padding Mode | Windows (CNG) | Linux (OpenSSL) | macOS | Windows (CAPI) |
|--------------|---------------|-----------------|-------|----------------|
| PKCS1 Encryption | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| OAEP - SHA-1 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| OAEP - SHA-2 (SHA256, SHA384, SHA512) | :white_check_mark: | :x: | :x: | :x: |
| PKCS1 Signature (MD5, SHA-1) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| PKCS1 Signature (SHA-2) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :question: |
| PSS | :white_check_mark: | :x: | :x: | :x: |
Windows CAPI is capable of PKCS1 signature with a SHA-2 algorithm, but the individual RSA object may be loaded in a CSP which does not support it.
#### RSA on Windows
* Windows CNG is used on Windows whenever `new RSACng()` is used.
* Windows CAPI is used on Windows whenever `new RSACryptoServiceProvider()` is used.
* The object returned by `RSA.Create()` is internally powered by Windows CNG, but this is an implementation detail subject to change.
* The `GetRSAPublicKey()` extension method for X509Certificate2 will currently always return an RSACng instance, but this could change as the platform evolves.
* The `GetRSAPrivateKey()` extension method for X509Certiicate2 will currently prefer an RSACng instance, but if RSACng cannot open the key RSACryptoServiceProvider will be attempted.
* In the future other providers could be preferred over RSACng.
#### Native Interop
.NET Core exposes types to allow programs to interoperate with the system libraries upon which the .NET cryptography code is layered.
The types involved do not translate between platforms, and should only be directly used when necessary.
| Type | Windows | Linux | macOS |
|------|---------|-------|-------|
| RSACryptoServiceProvider | :white_check_mark: | :question: | :question: |
| RSACng | :white_check_mark: | :x: | :x: |
| RSAOpenSsl | :x: | :white_check_mark: | :question: |
RSAOpenSsl on macOS works if OpenSSL is installed in the system and an appropriate libcrypto dylib can be found via dynamic library loading, otherwise exceptions will be thrown.
On non-Windows systems RSACryptoServiceProvider can be used for compatibility with existing programs, but a `PlatformNotSupportedException` will be thrown from any method which requires system interop, such as opening a named key.
### ECDSA
ECDSA key generation is performed by the system libraries, and is subject to size limitations and performance characteristics thereof.
ECDSA key curves are defined by the system libraries, and are subject to the limitations thereof.
| EC Curve | Windows 10 | Windows 7 - 8.1 | Linux | macOS |
|----------|------------|-------|-------|-----------------|
| NIST P-256 (secp256r1) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| NIST P-384 (secp384r1) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| NIST P-521 (secp521r1) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| brainpool curves (as named curves) | :white_check_mark: | :x: | :question: | :x: |
| other named curves | :question: | :x: | :question: | :x: |
| explicit curves | :white_check_mark: | :x: | :white_check_mark: | :x: |
| Export or import as explicit | :white_check_mark: | :x: | :white_check_mark: | :x: |
Support for named curves was added to Windows CNG in Windows 10, and is not available in prior OSes, with the exception of the three curves which had special support in Windows 7.
See [CNG Named Elliptic Curves](https://msdn.microsoft.com/en-us/library/windows/desktop/mt632245(v=vs.85).aspx) for the expected support.
Not all Linux distributions have support for the same named curves.
Exporting with explicit curve parameters requires system library support which is not available on macOS or older versions of Windows.
#### Native Interop
.NET Core exposes types to allow programs to interoperate with the system libraries upon which the .NET cryptography code is layered.
The types involved do not translate between platforms, and should only be directly used when necessary.
| Type | Windows | Linux | macOS |
|------|---------|-------|-------|
| ECDsaCng | :white_check_mark: | :x: | :x: |
| ECDsaOpenSsl | :x: | :white_check_mark: | :question: |
ECDsaOpenSsl on macOS works if OpenSSL is installed in the system and an appropriate libcrypto dylib can be found via dynamic library loading, otherwise exceptions will be raised.
### DSA
DSA key generation is performed by the system libraries, and is subject to size limitations and performance characteristics thereof.
| Function | Windows CNG | Linux | macOS | Windows CAPI |
|----------|-------------|-------|-------|--------------|
| Key creation (<= 1024 bits) | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| Key creation (> 1024 bits) | :white_check_mark: | :white_check_mark: | :x: | :x: |
| Loading keys (<= 1024 bits) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Loading keys (> 1024 bits) | :white_check_mark: | :white_check_mark: | :question: | :x: |
| FIPS 186-2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| FIPS 186-3 (SHA-2 signatures) | :white_check_mark: | :white_check_mark: | :x: | :x: |
macOS seems to be capable of loading DSA keys whose size exceeds 1024-bit, but does not perform FIPS 186-3 behaviors with those keys, so the behavior of those keys is undefined.
#### DSA on Windows
* Windows CNG is used on Windows whenever `new DSACng()` is used.
* Windows CAPI is used on Windows whenever `new DSACryptoServiceProvider()` is used.
* The object returned by `DSA.Create()` is internally powered by Windows CNG, but this is an implementation detail subject to change.
* The `GetDSAPublicKey()` extension method for X509Certificate2 will currently always return an DSACng instance, but this could change as the platform evolves.
* The `GetDSAPrivateKey()` extension method for X509Certiicate2 will currently prefer an DSACng instance, but if DSACng cannot open the key DSACryptoServiceProvider will be attempted.
* In the future other providers could be preferred over DSACng.
#### Native Interop
.NET Core exposes types to allow programs to interoperate with the system libraries upon which the .NET cryptography code is layered.
The types involved do not translate between platforms, and should only be directly used when necessary.
| Type | Windows | Linux | macOS |
|------|---------|-------|-------|
| DSACryptoServiceProvider | :white_check_mark: | :question: | :question: |
| DSACng | :white_check_mark: | :x: | :x: |
| DSAOpenSsl | :x: | :white_check_mark: | :question: |
DSAOpenSsl on macOS works if OpenSSL is installed in the system and an appropriate libcrypto dylib can be found via dynamic library loading, otherwise exceptions will be raised.
On non-Windows systems RSACryptoServiceProvider can be used for compatibility with existing programs, but a `PlatformNotSupportedException` will be thrown from any method which requires system interop, such as opening a named key.
## X.509 Certificates
The majority of support for X.509 certificates in .NET Core comes from system libraries.
All certificates are required to be loaded by the underlying system library to be loaded into an `X509Certificate2` instance in .NET Core (or an `X509Certificate` instance).
### Reading a PKCS12/PFX
| Scenario | Windows | Linux | macOS |
|----------|---------|-------|-------|
| Empty | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| One certificate, no private key | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| One certificate, with private key | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Multiple certificates, no private keys | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Multiple certificates, one private key | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Multiple certificates, multiple private keys | :white_check_mark: | :x: | :white_check_mark: |
### Writing a PKCS12/PFX
| Scenario | Windows | Linux | macOS |
|----------|---------|-------|-------|
| Empty | :white_check_mark: | :white_check_mark: | :x: |
| One certificate, no private key | :white_check_mark: | :white_check_mark: | :x: |
| One certificate, with private key | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Multiple certificates, no private keys | :white_check_mark: | :white_check_mark: | :x: |
| Multiple certificates, one private key | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Multiple certificates, multiple private keys | :white_check_mark: | :x: | :white_check_mark: |
| Ephemeral loading | :white_check_mark: | :white_check_mark: | :x: |
macOS cannot load certificate private keys without a keychain object, which requires writing to disk.
Keychains are created automatically for PFX loading, and are deleted when no longer in use.
Since the `X509KeyStorageFlags.EphemeralKeySet` option means that the private key should not be written to disk, asserting that flag on macOS results in a `PlatformNotSupportedException`.
### Writing a PKCS7 certificate collection
Windows and Linux both emit DER-encoded PKCS7 blobs. macOS emits indefinite-length-CER-encoded PKCS7 blobs.
### X509Store
On Windows the X509Store class is a representation of the Windows Certificate Store APIs, and work the same as they did on .NET Framework.
On Linux the X509Store class is a projection of system trust decisions (read-only), user trust decisions (read-write), and user key storage (read-write).
On macOS the X509Store class is a projection of system trust decisions (read-only), user trust decisions (read-only), and user key storage (read-write).
| Scenario | Windows | Linux | macOS |
|----------|---------|-------|-------|
| Open CurrentUser\My (ReadOnly) | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Open CurrentUser\My (ReadWrite) | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Open CurrentUser\My (ExistingOnly) | :white_check_mark: | :question: | :white_check_mark: |
| Open LocalMachine\My | :white_check_mark: | `CryptographicException` | :white_check_mark: |
| Open CurrentUser\Root (ReadOnly) | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Open CurrentUser\Root (ReadWrite) | :white_check_mark: | :white_check_mark: | `CryptographicException` |
| Open CurrentUser\Root (ExistingOnly) | :white_check_mark: | :question: | :white_check_mark: (if ReadOnly) |
| Open LocalMachine\Root (ReadOnly) | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Open LocalMachine\Root (ReadWrite) | :white_check_mark: | `CryptographicException` | `CryptographicException` |
| Open LocalMachine\Root (ExistingOnly) | :white_check_mark: | :question: | :white_check_mark: (if ReadOnly) |
| Open CurrentUser\Disallowed (ReadOnly) | :white_check_mark: | :question: | :white_check_mark: |
| Open CurrentUser\Disallowed (ReadWrite) | :white_check_mark: | :question: | `CryptographicException` |
| Open CurrentUser\Disallowed (ExistingOnly) | :white_check_mark: | :question: | :white_check_mark: (if ReadOnly) |
| Open LocalMachine\Disallowed (ReadOnly) | :white_check_mark: | `CryptographicException` | :white_check_mark: |
| Open LocalMachine\Disallowed (ReadWrite) | :white_check_mark: | `CryptographicException` | `CryptographicException` |
| Open LocalMachine\Disallowed (ExistingOnly) | :white_check_mark: | `CryptographicException` | :white_check_mark: (if ReadOnly) |
| Open non-existant store (ExistingOnly) | `CryptographicException` | `CryptographicException` | `CryptographicException` |
| Open CurrentUser non-existant store (ReadWrite) | :white_check_mark: | :white_check_mark: | `CryptographicException` |
| Open LocalMachine non-existant store (ReadWrite) | :white_check_mark: | `CryptographicException` | `CryptographicException` |
On Linux stores are created on first-write, and no user stores exist by default, so opening CurrentUser\My with ExistingOnly may fail.
On Linux the Disallowed store is not used in chain building, and attempting to add contents to it will result in a `CryptographicException` being thrown.
A `CryptographicException` will be thrown when opening the Disallowed store on Linux if it has already acquired contents.
The LocalMachnie\Root store on Linux is an interpretation of the CA bundle in the default path for OpenSSL.
The LocalMachine\Intermediate store on Linux is an interpretation of the CA bundle in the default path for OpenSSL.
The CurrentUser\Intermediate store on Linux is used as a cache when downloading intermediate CAs by their Authority Information Access records on successful X509Chain builds.
On macOS the CurrentUser\My store is the user's default keychain (login.keychain, by default).
The LocalMachine\My store is System.keychain.
The CurrentUser\Root store on macOS is an interpretation of the SecTrustSettings results for the user trust domain.
The LocalMachine\Root store on macOS is an interpretation of the SecTrustSettings results for the admin and system trust domains.
The CurrentUser\Disallowed and LocalMachine\Disallowed stores are interpretations of the appropriate SecTrustSettings results for certificates whose trust is set to Always Deny.
Keychain creation on macOS requires more input than is captured with the X509Store API, so attempting to create a new store will fail with a `PlatformNotSupportedException`.
If a keychain is opened by P/Invoke to SecKeychainOpen, the resulting `IntPtr` can be passed to `new X509Store(IntPtr)` to obtain a read/write-capable store (subject to the current user's permissions).
### X509Chain
macOS does not support Offline CRL utilization, so `X509RevocationMode.Offline` is treated as `X509RevocationMode.Online`.
macOS does not support a user-initiated timeout on CRL/OCSP/AIA downloading, so `X509ChainPolicy.UrlRetrievalTimeout` is ignored.
OCSP is not supported on Linux, CRLs are required for `X509RevocationMode.Offline` or `X509RevocationMode.Online`.

View File

@ -226,7 +226,11 @@ msbuild System.Runtime.Tests.csproj /p:TargetGroup=netfx
The tests can also be filtered based on xunit trait attributes defined in [`xunit.netcore.extensions`](https://github.com/dotnet/buildtools/tree/master/src/xunit.netcore.extensions). These attributes are specified above the test method's definition. The available attributes are:
_**`OuterLoop`:**_
#### OuterloopAttribute
```cs
[OuterLoop()]
```
Tests marked as `Outerloop` are for scenarios that don't need to run every build. They may take longer than normal tests, cover seldom hit code paths, or require special setup or resources to execute. These tests are excluded by default when testing through msbuild but can be enabled manually by adding the `Outerloop` property e.g.
```cmd
@ -238,25 +242,136 @@ To run <b>only</b> the Outerloop tests, use the following command:
msbuild <csproj_file> /t:BuildAndTest /p:WithCategories=OuterLoop
```
_**`PlatformSpecific(TestPlatforms platforms)`:**_
#### PlatformSpecificAttribute
```cs
[PlatformSpecific(TestPlatforms platforms)]
```
Use this attribute on test methods to specify that this test may only be run on the specified platforms. This attribute returns the following categories based on platform
- `nonwindowstests` for tests that don't run on Windows
- `nonlinuxtests` for tests that don't run on Linux
- `nonosxtests` for tests that don't run on OS X
**[Available Test Platforms](https://github.com/dotnet/buildtools/blob/master/src/xunit.netcore.extensions/TestPlatforms.cs#L10)**
When running tests by building a test project, tests that don't apply to the `OSGroup` are not run. For example, to run Linux-specific tests on a Linux box, use the following command line:
```sh
<repo-root>/Tools/msbuild.sh <csproj_file> /t:BuildAndTest /p:OSGroup=Linux
```
_**`ActiveIssue(int issue, TestPlatforms platforms)`:**_
Use this attribute over test methods to skip failing tests only on the specific platforms; if no platforms are specified, then the test is skipped on all platforms. This attribute returns the 'failing' category, which is disabled by default.
To run all Linux-compatible tests that are failing:
```sh
<repo-root>/Tools/msbuild.sh <csproj_file> /t:BuildAndTest /p:OSGroup=Linux /p:WithCategories=failing
```
#### ActiveIssueAttribute
This attribute is intended to be used when there is an active issue tracking the test failure and it is needed to be fixed. This is a temporary attribute to skip the test while the issue is fixed. It is important that you limit the scope of the attribute to just the platforms and target monikers where the issue applies.
This attribute can be applied either to a test class (will disable all the tests in that class) or to a test method. It allows multiple usages on the same member.
This attribute returns the 'failing' category, which is disabled by default.
**Disable for all platforms and all target frameworks:**
```cs
[ActiveIssue(int issue)]
[ActiveIssue(string issue)]
```
**Disable for specific platform:**
```cs
[ActiveIssue(int issue, TestPlatforms platforms)]
[ActiveIssue(string issue, TestPlatforms platforms)]
```
**Disable for specific target frameworks:**
```cs
[ActiveIssue(int issue, TargetFrameworkMonikers frameworks)]
[ActiveIssue(string issue, TargetFrameworkMonikers frameworks)]
```
**Disable for specific test platforms and target frameworks:**
```cs
[ActiveIssue(int issue, TestPlatforms platforms, TargetFrameworkMonikers frameworks)]
[ActiveIssue(string issue, TestPlatforms platforms, TargetFrameworkMonikers frameworks)]
```
Use this attribute over test methods to skip failing tests only on the specific platforms and the specific target frameworks.
#### SkipOnTargetFrameworkAttribute
This attribute is intended to disable a test permanently on a framework where an API is not available or there is an intentional difference in behavior in between the tested framework and the skipped framework.
This attribute can be applied either to a test class (will disable all the tests in that class) or to a test method. It allows multiple usages on the same member.
```cs
[SkipOnTargetFramework(TargetFrameworkMonikers frameworks, string reason)]
```
Use this attribute over test methods to skip tests only on the specific target frameworks. The reason parameter doesn't affect the traits but we rather always use it so that when we see this attribute we know why it is being skipped on that framework.
If it needs to be skipped in multiple frameworks and the reasons are different please use two attributes on the same test so that you can specify different reasons for each framework.
**Currently this are the [Framework Monikers](https://github.com/dotnet/buildtools/blob/master/src/xunit.netcore.extensions/TargetFrameworkMonikers.cs#L23-L26) that we support through our test execution infrastructure**
#### ConditionalFactAttribute
Use this attribute to run the test only when a condition is `true`. This attribute is used when `ActiveIssueAttribute` or `SkipOnTargetFrameworkAttribute` are not flexible enough due to needing to run a custom logic at test time. This test behaves as a `[Fact]` test that has no test data passed in as a parameter.
```cs
[ConditionalFact(params string[] conditionMemberNames)]
```
The conditional method needs to be a static method or property on this or any ancestor type, of any visibility, accepting zero arguments, and having a return type of Boolean.
**Example:**
```cs
public class TestClass
{
public static bool ConditionProperty => true;
[ConditionalFact(nameof(ConditionProperty))]
public static void TestMethod()
{
Assert.True(true);
}
}
```
#### ConditionalTheoryAttribute
Use this attribute to run the test only when a condition is `true`. This attribute is used when `ActiveIssueAttribute` or `SkipOnTargetFrameworkAttribute` are not flexible enough due to needing to run a custom logic at test time. This test behaves as a `[Theory]` test that has no test data passed in as a parameter.
```cs
[ConditionalTheory(params string[] conditionMemberNames)]
```
This attribute must have `[MemberData(string member)]` or a `[ClassData(Type class)]` attribute, which represents an `IEnumerable<object>` containing the data that will be passed as a parameter to the test. Another option is to add multiple or one `[InlineData(object params[] parameters)]` attribute.
The conditional method needs to be a static method or property on this or any ancestor type, of any visibility, accepting zero arguments, and having a return type of Boolean.
**Example:**
```cs
public class TestClass
{
public static bool ConditionProperty => true;
public static IEnumerable<object[]> Subtract_TestData()
{
yield return new object[] { new IntPtr(42), 6, (long)36 };
yield return new object[] { new IntPtr(40), 0, (long)40 };
yield return new object[] { new IntPtr(38), -2, (long)40 };
}
[ConditionalTheory(nameof(ConditionProperty))]
[MemberData(nameof(Equals_TestData))]
public static void Subtract(IntPtr ptr, int offset, long expected)
{
IntPtr p1 = IntPtr.Subtract(ptr, offset);
VerifyPointer(p1, expected);
IntPtr p2 = ptr - offset;
VerifyPointer(p2, expected);
IntPtr p3 = ptr;
p3 -= offset;
VerifyPointer(p3, expected);
}
}
```
**Note that all of the attributes above must include an issue number/link and/or have a comment next to them briefly justifying the reason. ActiveIssueAttribute and SkipOnTargetFrameworkAttribute should use their constructor parameters to do this**
_**A few common examples with the above attributes:**_
- Run all tests acceptable on Windows that are not failing:

View File

@ -10,8 +10,8 @@ this experience. Make sure to consult this document often.
1. Acquire the latest nightly .NET Core SDK 2.0
- [Win 64-bit Latest Zip](https://dotnetcli.blob.core.windows.net/dotnet/Sdk/master/dotnet-dev-win-x64.latest.zip) [Installer](https://dotnetcli.blob.core.windows.net/dotnet/Sdk/master/dotnet-dev-win-x64.latest.exe)
- [macOS 64-bit Latest Tar](https://dotnetcli.blob.core.windows.net/dotnet/Sdk/master/dotnet-dev-osx-x64.latest.tar.gz) [Installer](https://dotnetcli.blob.core.windows.net/dotnet/Sdk/master/dotnet-dev-osx-x64.latest.pkg)
- [Win 64-bit Latest Zip](https://dotnetcli.azureedge.net/dotnet/Sdk/master/dotnet-dev-win-x64.latest.zip) [Installer](https://dotnetcli.azureedge.net/dotnet/Sdk/master/dotnet-dev-win-x64.latest.exe)
- [macOS 64-bit Latest Tar](https://dotnetcli.azureedge.net/dotnet/Sdk/master/dotnet-dev-osx-x64.latest.tar.gz) [Installer](https://dotnetcli.azureedge.net/dotnet/Sdk/master/dotnet-dev-osx-x64.latest.pkg)
- [Others](https://github.com/dotnet/cli/blob/master/README.md#installers-and-binaries)
To setup the SDK download the zip and extract it somewhere and add the root folder to your path or always fully
@ -236,4 +236,20 @@ need to modify your .csproj to target netcoreapp2.0 and reference the nightly bu
</PropertyGroup>
```
In a future update to Visual Studio, it will no longer be necessary to make this edit.
In a future update to Visual Studio, it will no longer be necessary to make this edit.
## Finding specific builds
The URL scheme for the runtime is as follows:
```
https://dotnetcli.azureedge.net/dotnet/master/Installers/$version$/dotnet-$os$-$arch$.$version$.exe
https://dotnetcli.azureedge.net/dotnet/master/Installers/2.0.0-preview1-001915-00/dotnet-win-x64.2.0.0-preview1-001915-00.exe
```
The URL scheme for the SDK & CLI is as follows:
```
https://dotnetcli.azureedge.net/dotnet/Sdk/$version$/dotnet-dev-$os$-$arch.$version$.exe
https://dotnetcli.azureedge.net/dotnet/Sdk/2.0.0-preview1-005791/dotnet-dev-win-x86.2.0.0-preview1-005791.exe
```

View File

@ -10,7 +10,7 @@ As noted above, we don't close issues just because we don't plan to address them
2. Cross cutting work better suited for another team. Sometimes the line between the framework, languages and runtime blurs. For some issues, we may feel that the work is better suited for the runtime team, language team or other partner. In these cases, we'll close the issue and open it with the partner team. If they end up not deciding to take on the issue, we can reconsider it here.
3. Nebulous and Large open issues. Large open issues are sometimes better suited for [User Voice](http://visualstudio.uservoice.com/forums/121579-visual-studio/category/31481--net), especially when the work will cross the boundaries of the framework, language and runtime. A good example of this is the SIMD support we recently added to CoreFx. This started as a [User Voice request](https://visualstudio.uservoice.com/forums/121579-visual-studio-2015/suggestions/2212443-c-and-simd), and eventually turned into work for both the core libraries and runtime.
Sometimes after debate, we'll decide an issue isn't a good fit for CoreFx. In that case, we'll also close it. Because of this, we ask that you don't start working on an issue until it's tagged with [up for grabs](https://github.com/dotnet/corefx/labels/up%20for%20grabs) or [api-approved](https://github.com/dotnet/corefx/labels/api-approved). Both you and the team will be unhappy if you spend time and effort working on a change we'll ultimately be unable to take. We try to avoid that.
Sometimes after debate, we'll decide an issue isn't a good fit for CoreFx. In that case, we'll also close it. Because of this, we ask that you don't start working on an issue until it's tagged with [up-for-grabs](https://github.com/dotnet/corefx/labels/up-for-grabs) or [api-approved](https://github.com/dotnet/corefx/labels/api-approved). Both you and the team will be unhappy if you spend time and effort working on a change we'll ultimately be unable to take. We try to avoid that.
### Labels
We use GitHub [labels](https://github.com/dotnet/corefx/labels) on our issues in order to classify them. We have the following categories per issue:
@ -24,7 +24,7 @@ We use GitHub [labels](https://github.com/dotnet/corefx/labels) on our issues in
* [documentation](https://github.com/dotnet/corefx/labels/documentation): Issues related to documentation (e.g. incorrect documentation, enhancement requests).
* [question](https://github.com/dotnet/corefx/labels/question): Questions about the product, source code, etc.
* **Other**:
* [up for grabs](https://github.com/dotnet/corefx/labels/up%20for%20grabs): Small sections of work which we believe are well scoped. These sorts of issues are a good place to start if you are new. Anyone is free to work on these issues.
* [up-for-grabs](https://github.com/dotnet/corefx/labels/up-for-grabs): Small sections of work which we believe are well scoped. These sorts of issues are a good place to start if you are new. Anyone is free to work on these issues.
* [needs more info](https://github.com/dotnet/corefx/labels/needs%20more%20info): Issues which need more information to be actionable. Usually this will be because we can't reproduce a reported bug. We'll close these issues after a little bit if we haven't gotten actionable information, but we welcome folks who have acquired more information to reopen the issue.
In addition to the above, we have a handful of other labels we use to help classify our issues. Some of these tag cross cutting concerns (e.g. [tenet-performance](https://github.com/dotnet/corefx/labels/tenet-performance)), whereas others are used to help us track additional work needed before closing an issue (e.g. [api-needs-exposed](https://github.com/dotnet/corefx/labels/api-needs-exposed)).
@ -42,35 +42,35 @@ Areas are tracked by labels area-&#42; (e.g. area-System.Collections). Each area
| Area | Owners / experts | Description |
|-----------------------------------------------------------------------------------------------|------------------|-------------|
| [area-Infrastructure](https://github.com/dotnet/corefx/labels/area-Infrastructure) | [@mellinoe](https://github.com/mellinoe), [@ericstj](https://github.com/ericstj), [@weshaggard](https://github.com/weshaggard) |Covers:<ul><li>Packaging</li><li>Build and test infra for CoreFX repo</li><li>VS integration</li></ul><br/>**Triage in progress** |
| [area-Meta](https://github.com/dotnet/corefx/labels/area-Meta) | [@tarekgh](https://github.com/tarekgh) | Issues without clear association to any specific API/contract, e.g. <ul><li>new contract proposals</li><li>cross-cutting code/test pattern changes (e.g. FxCop failures)</li><li>project-wide docs</li></ul><br/>**Triage in progress** |
| [area-Infrastructure](https://github.com/dotnet/corefx/labels/area-Infrastructure) | [@mellinoe](https://github.com/mellinoe), [@ericstj](https://github.com/ericstj), [@weshaggard](https://github.com/weshaggard) |Covers:<ul><li>Packaging</li><li>Build and test infra for CoreFX repo</li><li>VS integration</li></ul><br/> |
| [area-Meta](https://github.com/dotnet/corefx/labels/area-Meta) | [@tarekgh](https://github.com/tarekgh) | Issues without clear association to any specific API/contract, e.g. <ul><li>new contract proposals</li><li>cross-cutting code/test pattern changes (e.g. FxCop failures)</li><li>project-wide docs</li></ul><br/> |
| [area-Serialization](https://github.com/dotnet/corefx/labels/area-Serialization) | [@shmao](https://github.com/shmao), [@zhenlan](https://github.com/zhenlan) | Packages:<ul><li>System.Runtime.Serialization.Xml</li><li>System.Runtime.Serialization.Json</li><li>System.Private.DataContractSerialization</li><li>System.Xml.XmlSerialization</li></ul> Excluded:<ul><li>System.Runtime.Serialization.Formatters</li></ul> |
| **System contract assemblies** | | |
| [System.AppContext](https://github.com/dotnet/corefx/labels/area-System.AppContext) | [@AlexGhiondea](https://github.com/AlexGhiondea) | | |
| [System.Buffers](https://github.com/dotnet/corefx/labels/area-System.Buffers) | [@alexperovich](https://github.com/alexperovich), [@safern](https://github.com/safern) | |
| [System.Buffers](https://github.com/dotnet/corefx/labels/area-System.Buffers) | [@safern](https://github.com/safern) | |
| [System.CodeDom](https://github.com/dotnet/corefx/labels/area-System.CodeDom) | [@Priya91](https://github.com/Priya91) | |
| [System.Collections](https://github.com/dotnet/corefx/labels/area-System.Collections) | [@ianhays](https://github.com/ianhays), [@safern](https://github.com/safern) | </ul>Excluded:<ul><li>System.Array -> System.Runtime</li></ul> |
| [System.ComponentModel](https://github.com/dotnet/corefx/labels/area-System.ComponentModel) | [@safern](https://github.com/safern), [@AlexGhiondea](https://github.com/AlexGhiondea) | |
| [System.ComponentModel.DataAnnotations](https://github.com/dotnet/corefx/labels/area-System.ComponentModel.DataAnnotations) | [@lajones](https://github.com/lajones), [@divega](https://github.com/divega), [@ajcvickers](https://github.com/ajcvickers) | **Triage in progress** |
| [System.ComponentModel.DataAnnotations](https://github.com/dotnet/corefx/labels/area-System.ComponentModel.DataAnnotations) | [@lajones](https://github.com/lajones), [@divega](https://github.com/divega), [@ajcvickers](https://github.com/ajcvickers) | |
| [System.Composition](https://github.com/dotnet/corefx/labels/area-System.Composition) | [@AlexGhiondea](https://github.com/AlexGhiondea) | |
| [System.Configuration](https://github.com/dotnet/corefx/labels/area-System.Configuration) | [@JeremyKuhne](https://github.com/JeremyKuhne) | |
| [System.Console](https://github.com/dotnet/corefx/labels/area-System.Console) | [@ianhays](https://github.com/ianhays) | |
| [System.Data](https://github.com/dotnet/corefx/labels/area-System.Data) | [@saurabh500](https://github.com/saurabh500), [@corivera](https://github.com/corivera) | |
| [System.Data.SqlClient](https://github.com/dotnet/corefx/labels/area-System.Data.SqlClient) | [@saurabh500](https://github.com/saurabh500), [@YoungGah](https://github.com/YoungGah) | **Pending triage** |
| [System.Data.SqlClient](https://github.com/dotnet/corefx/labels/area-System.Data.SqlClient) | [@saurabh500](https://github.com/saurabh500), [@corivera](https://github.com/corivera) | |
| [System.Diagnostics](https://github.com/dotnet/corefx/labels/area-System.Diagnostics) | [@joperezr](https://github.com/dotnet/joperezr) | |
| [System.Diagnostics.Process](https://github.com/dotnet/corefx/labels/area-System.Diagnostics.Process) | [@Priya91](https://github.com/Priya91) | |
| [System.Diagnostics.Tracing](https://github.com/dotnet/corefx/labels/area-System.Diagnostics.Tracing) | [@brianrob](https://github.com/brianrob), [@vancem](https://github.com/vancem), [@valenis](https://github.com/valenis)| Packages:<ul><li>System.Diagnostics.DiagnosticSource</li><li>System.Diagnostics.PerformanceCounter</li><li>System.Diagnostics.Tracing</li><li>System.Diagnostics.TraceSource</li></ul><br/>**Pending triage** |
| [System.Diagnostics.Tracing](https://github.com/dotnet/corefx/labels/area-System.Diagnostics.Tracing) | [@brianrob](https://github.com/brianrob), [@vancem](https://github.com/vancem), [@valenis](https://github.com/valenis)| Packages:<ul><li>System.Diagnostics.DiagnosticSource</li><li>System.Diagnostics.PerformanceCounter</li><li>System.Diagnostics.Tracing</li><li>System.Diagnostics.TraceSource</li></ul><br/> |
| [System.DirectoryServices](https://github.com/dotnet/corefx/labels/area-System.DirectoryServices) | [@tquerec](https://github.com/tquerec) | |
| [System.Drawing](https://github.com/dotnet/corefx/labels/area-System.Drawing) | [@alexperovich](https://github.com/alexperovich) | |
| [System.Drawing](https://github.com/dotnet/corefx/labels/area-System.Drawing) | [@mellinoe](https://github.com/mellinoe) | |
| [System.Dynamic.Runtime](https://github.com/dotnet/corefx/labels/area-System.Dynamic.Runtime) | [@VSadov](https://github.com/VSadov), [@OmarTawfik](https://github.com/OmarTawfik) | |
| [System.Globalization](https://github.com/dotnet/corefx/labels/area-System.Globalization) | [@krwq](https://github.com/krwq), [@tarekgh](https://github.com/tarekgh) | |
| [System.IO](https://github.com/dotnet/corefx/labels/area-System.IO) | [@JeremyKuhne](https://github.com/JeremyKuhne), [@ianhays](https://github.com/ianhays) | |
| [System.IO.Compression](https://github.com/dotnet/corefx/labels/area-System.IO.Compression) | [@ianhays](https://github.com/ianhays) | |
| [System.Linq](https://github.com/dotnet/corefx/labels/area-System.Linq) | [@VSadov](https://github.com/VSadov), [@OmarTawfik](https://github.com/OmarTawfik) | |
| [System.Linq.Expressions](https://github.com/dotnet/corefx/labels/area-System.Linq.Expressions) | [@VSadov](https://github.com/VSadov), [@OmarTawfik](https://github.com/OmarTawfik) | |
| [System.Linq.Parallel](https://github.com/dotnet/corefx/labels/area-System.Linq.Parallel) | [@alexperovich](https://github.com/alexperovich), [@kouvel](https://github.com/kouvel) | |
| [System.Memory](https://github.com/dotnet/corefx/labels/area-System.Memory) | [@KrzysztofCwalina](https://github.com/KrzysztofCwalina), [@ahsonkhan](https://github.com/ahsonkhan), [@shiftylogic](https://github.com/shiftylogic) | **Pending triage** |
| [System.Net](https://github.com/dotnet/corefx/labels/area-System.Net) | [@davidsh](https://github.com/davidsh), [@CIPop](https://github.com/CIPop), [@Priya91](https://github.com/Priya91) | **Triage in progress** |
| [System.Linq.Parallel](https://github.com/dotnet/corefx/labels/area-System.Linq.Parallel) | [@kouvel](https://github.com/kouvel) | |
| [System.Memory](https://github.com/dotnet/corefx/labels/area-System.Memory) | [@KrzysztofCwalina](https://github.com/KrzysztofCwalina), [@ahsonkhan](https://github.com/ahsonkhan), [@shiftylogic](https://github.com/shiftylogic) | |
| [System.Net](https://github.com/dotnet/corefx/labels/area-System.Net) | [@davidsh](https://github.com/davidsh), [@CIPop](https://github.com/CIPop), [@Priya91](https://github.com/Priya91) | Included:<ul><li>System.Uri</li></ul> |
| [System.Net.Http](https://github.com/dotnet/corefx/labels/area-System.Net.Http) | [@davidsh](https://github.com/davidsh), [@CIPop](https://github.com/CIPop), [@Priya91](https://github.com/Priya91) | |
| [System.Net.Security](https://github.com/dotnet/corefx/labels/area-System.Net.Security) | [@davidsh](https://github.com/davidsh), [@CIPop](https://github.com/CIPop), [@Priya91](https://github.com/Priya91) | |
| [System.Net.Sockets](https://github.com/dotnet/corefx/labels/area-System.Net.Sockets) | [@davidsh](https://github.com/davidsh), [@CIPop](https://github.com/CIPop), [@Priya91](https://github.com/Priya91) | |
@ -78,10 +78,10 @@ Areas are tracked by labels area-&#42; (e.g. area-System.Collections). Each area
| [System.Reflection](https://github.com/dotnet/corefx/labels/area-System.Reflection) | [@dnlharvey](https://github.com/dnlharvey), [@AtsushiKan](https://github.com/AtsushiKan) | |
| [System.Reflection.Emit](https://github.com/dotnet/corefx/labels/area-System.Reflection.Emit) | [@dnlharvey](https://github.com/dnlharvey), [@AtsushiKan](https://github.com/AtsushiKan) | |
| [System.Reflection.Metadata](https://github.com/dotnet/corefx/labels/area-System.Reflection.Metadata) | [@tmat](https://github.com/tmat), [@nguerrera](https://github.com/nguerrera) | |
| [System.Resources](https://github.com/dotnet/corefx/labels/area-System.Resources) | [@ramarag](https://github.com/ramarag), [@tarekgh](https://github.com/tarekgh) | **Triage in progress** |
| [System.Runtime](https://github.com/dotnet/corefx/labels/area-System.Runtime) | [@AlexGhiondea](https://github.com/AlexGhiondea), [@joperezr](https://github.com/dotnet/joperezr) | Included:<ul><li>System.Runtime.Serialization.Formatters</li><li>System.Runtime.InteropServices.RuntimeInfo</li><li>System.Array</li></ul>Excluded:<ul><li>Path -> System.IO</li><li>StopWatch -> System.Diagnostics</li><li>WebUtility -> System.Net</li></ul> |
| [System.Resources](https://github.com/dotnet/corefx/labels/area-System.Resources) | [@ramarag](https://github.com/ramarag), [@tarekgh](https://github.com/tarekgh) | |
| [System.Runtime](https://github.com/dotnet/corefx/labels/area-System.Runtime) | [@AlexGhiondea](https://github.com/AlexGhiondea), [@joperezr](https://github.com/dotnet/joperezr) | Included:<ul><li>System.Runtime.Serialization.Formatters</li><li>System.Runtime.InteropServices.RuntimeInfo</li><li>System.Array</li></ul>Excluded:<ul><li>Path -> System.IO</li><li>StopWatch -> System.Diagnostics</li><li>Uri -> System.Net</li><li>WebUtility -> System.Net</li></ul> |
| [System.Runtime.CompilerServices](https://github.com/dotnet/corefx/labels/area-System.Runtime.CompilerServices) | [@AlexGhiondea](https://github.com/AlexGhiondea), [@joperezr](https://github.com/dotnet/joperezr) | |
| [System.Runtime.Extensions](https://github.com/dotnet/corefx/labels/area-System.Runtime.Extensions) | [@AlexGhiondea](https://github.com/AlexGhiondea), [@joperezr](https://github.com/dotnet/joperezr) | **Triage in progress** |
| [System.Runtime.Extensions](https://github.com/dotnet/corefx/labels/area-System.Runtime.Extensions) | [@AlexGhiondea](https://github.com/AlexGhiondea), [@joperezr](https://github.com/dotnet/joperezr) | |
| [System.Runtime.InteropServices](https://github.com/dotnet/corefx/labels/area-System.Runtime.InteropServices) | [@tijoytom](https://github.com/tijoytom), [@yizhang82](https://github.com/yizhang82) | Excluded:<ul><li>System.Runtime.InteropServices.RuntimeInfo</li></ul> |
| [System.Security](https://github.com/dotnet/corefx/labels/area-System.Security) | [@bartonjs](https://github.com/bartonjs), [@steveharter](https://github.com/steveharter) | |
| System.ServiceModel | N/A | [dotnet/wcf](https://github.com/dotnet/wcf) |
@ -102,10 +102,23 @@ Note: Area triage will apply the new scheme (issue types and assignee) throughou
### Triage rules - simplified
1. Each issue has exactly one **area-&#42;** label
1. Issue has no **Assignee**, unless someone is working on the issue at the moment
1. Use **up-for-grabs** as much as possible, ideally with a quick note about next steps / complexity of the issue
1. Set milestone to **Future**, unless you can 95%-commit you can fund the issue in specific milestone
1. Each issue has exactly one "*issue type*" label (**bug**, **enhancement**, **api-needs-work**, **test bug**, **test enhancement**, **question**, **documentation**, etc.)
1. Don't be afraid to say no, or close issues - just explain why and be polite
1. Don't be afraid to be wrong - just be flexible when new information appears
Feel free to use other labels if it helps your triage efforts (e.g. **needs more info**, **Design Discussion**, **blocked**, **blocking-partner**, **tenet-performance**, **tenet-compatibility**, **os-linux**/**os-windows**/**os-mac-os-x**/**os-unsupported**, **os-windows-uwp**/**os-windows-wsl**, **arch-arm32**/**arch-arm64**)
#### Motivation for triage rules
1. Each issue has exactly one **area-\*** label
* Motivation: Issues with multiple areas have loose responbility (everyone blames the other side) and issues are double counted in reports.
1. Issue has no **Assignee**, unless someone is working on the issue at the moment
* Motivation: Observation is that contributors are less likely to grab assigned issues, no matter what the repo rules say.
1. Use **up for grabs** as much as possible, ideally with a quick note about next steps / complexity of the issue
1. Use **up-for-grabs** as much as possible, ideally with a quick note about next steps / complexity of the issue
* Note: Per http://up-for-grabs.net, such issues should be no longer than few nights' worth of work. They should be actionable (i.e. no misterious CI failures or UWP issues that can't be tested in the open).
1. Set milestone to **Future**, unless you can 95%-commit you can fund the issue in specific milestone
* Motivation: Helps communicate desire/timeline to community. Can spark further priority/impact discussion.
1. Each issue has exactly one "*issue type*" label (**bug**, **enhancement**, **api-needs-work**, **test bug**, **test enhancement**, **question**, **documentation**, etc.)
@ -113,4 +126,18 @@ Note: Area triage will apply the new scheme (issue types and assignee) throughou
1. Don't be afraid to say no, or close issues - just explain why and be polite
1. Don't be afraid to be wrong - just be flexible when new information appears
Feel free to use other labels if it helps your triage efforts (e.g. **needs more info**, **Design Discussion**, **blocked**, **blocking-partner**, **tenet-performance**, **tenet-compatibility**, **os-linux**/**os-windows**/**os-mac-os-x**/**os-unsupported**, **os-windows-uwp**/**os-windows-wsl**, **arm32**/**arm64**)
#### PR rules
1. Each PR has exactly one **area-\*** label
* Movitation: Area owners will get email notification about new issue in their area.
1. PR has **Assignee** set to author of the PR, if it is non-CoreFX engineer, then area owners are co-assignees
* Motivation: Area owners are responsible to do code reviews for PRs from external contributors. CoreFX engineers know how to get code reviews from others.
1. [Optional] Set milestone according to the branch (master = 2.1, release/2.0.0 = 2.0, release/1.0.0 = 1.0.x, release/1.1.0 = 1.1.x)
* Motivation: Easier to track where which fix ended and if it needs to be ported into another branch
* Note: This is easily done after merge via simple queries & bulk-edits, you don't have to do this one.
1. Any other labels on PRs are superfluous and not needed (exceptions: **blocked**, **NO MERGE**)
* Motivation: All the important info (*issue type* label, api approval label, OS label, etc.) is already captured on the associated issue.
1. Push PRs forward, don't let them go stale (response every 5+ days, ideally no PRs older than 2 weeks)
1. Stuck or long-term blocked PRs (e.g. due to missing API approval, etc.) should be closed and reopened once they are unstuck
* Motivation: Keep only active PRs. WIP (work-in-progress) PRs should be rare and should not become stale (2+ weeks old). If a PR is stale and there is not immediate path forward, consider closing the PR until it is unblocked/unstuck.
1. PR should be linked to related issue, use [auto-closing](https://help.github.com/articles/closing-issues-via-commit-messages/) (add "Fixes #12345" into your PR description)

View File

@ -22,7 +22,9 @@ Running the tests
### Windows
Performance test files (if present) are stored within a library's ```tests/Performance``` directory and contain test methods that are all marked with a perf-specific *Benchmark* attribute. The performance tests will only be run if the ```performance``` property is set to ```true```.
To build and run the tests using msbuild for a project, run ```msbuild /t:BuildAndTest /p:Performance=true /p:ConfigurationGroup=Release /p:TargetOS=Windows_NT``` from the tests directory. If the v5.0 assemblies aren't installed on your system, an error will be raised and no tests will be run.
Before running the performance tests you must run ```build -release``` from the root folder.
To build and run the tests using msbuild for a project, run ```msbuild /t:BuildAndTest /p:Performance=true /p:ConfigurationGroup=Release /p:TargetOS=Windows_NT``` from the Performance directory with Admin privileges. If the v5.0 assemblies aren't installed on your system, an error will be raised and no tests will be run.
Note: Because build.cmd runs tests concurrently, it's not recommended that you execute the perf tests using it.
@ -65,8 +67,11 @@ Next, the project.json for the tests directory also needs to import the xunit li
"xunit": "2.1.0",
"xunit.netcore.extensions": "1.0.0-prerelease-*"
```
Once that’s all done, you can actually add tests to the file. The basic structure of a perf test file with file name Perf.Dictionary.cs should be like so:
```
Once that’s all done, you can actually add tests to the file.
Writing Test Cases
-----------
```C#
using Xunit;
using Microsoft.Xunit.Performance;
@ -74,18 +79,40 @@ namespace System.Collections.Tests
{
public class Perf_Dictionary
{
[Benchmark]
private volatile Dictionary<int, string> dict;
[Benchmark(InnerIterationCount = 2000)]
public void ctor()
{
foreach (var iteration in Benchmark.Iterations)
using (iteration.StartMeasurement())
for (int i = 0; i < 20000; i++)
for (int i = 0; i < Benchmark.InnerIterationCount; i++)
{
new Dictionary<int, string>();
dict = new Dictionary<int, string>();
}
}
}
}
```
The perf-test runner handles a lot of the specifics of the testing for you like iteration control. You won't need to add any Asserts or anything generally used in functional testing to get perf measurements, just make sure the thing within the “using” is big enough to avoid timer resolution errors.
The above benchmark will test the performance of the Dictionary<int, string> constructor. Each iteration of the benchmark will call the constructor 2000 times (`InnerIterationCount`).
Test cases should adhere to the following guidelines, within reason:
* Individual test cases should be of the "microbenchmark" variety. They should test a single function, in as isolated an environment as possible.
* The "real work" must be done inside of the `using (iteration.StartMeasurement())` block. All extra work (setup, cleanup) should be done outside of this block, so as to not pollute the data being collected.
* Individual iterations of a test case should take from 100 milliseconds to 1 second. This is everything inside of the `using (iteration.StartMeasurement())` block.
* Test cases may need to use an "inner iteration" concept in order for individual invocations of the "outer iteration" to last from 100 ms to 1s. The example above shows this.
* Some functions are prone to being entirely optimized out from test cases. For example, if the results of `Vector3.Add()` are not stored anywhere, then there are no observable side-effects, and the entire operation can be optimized out by the JIT. For operations which are susceptible to this, care must be taken to ensure that the operations are not entirely skipped. Try the following:
* Pass intermediate values to a volatile static field. This is done in the example code above.
* If the value is a struct, compute a value dependent on the structure, and store that in a volatile static field.
* There are two main ways to detect when a test case is being "optimized out":
* Look at the disassembly of the function (with the Visual Studio disassembler, for example).
* Observe unusual changes in the duration metric. If your test suddenly takes 1% of its previous time, odds are something has gone wrong.
* Before using intrinsic data types (int, string, etc) to represent value and reference types in your test, consider if the code under test is optimized for those types versus normal classes and structs.
* Also consider interfaces. For example, methods on ```List<T>``` using equality will be much faster on Ts that implement ```IEquatable<T>```.
Avoid the following performance test test anti-patterns:
* Tests for multiple methods which all end up calling the same final overload. This just adds noise and extra duplicate data to sift through.
* Having too many test cases which only differ by "input data". For example, testing the same operation on a collection with size 1, 10, 100, 1000, 10000, etc. This is a common pitfall when using `[Theory]` and `[InlineData]`. Instead, focus on the key scenarios and minimize the numbers of test cases. This results in less noise, less data to sift through, and less test maintenance cost.
* Performing more than a single operation in the "core test loop". There are times when this is necessary, but they are few and far between. Take extra care if you notice that your test case is doing too many things, and try to focus on creating a small, isolated microbenchmark.

View File

@ -85,25 +85,26 @@ Security Transparency | [Details](#security-transparency)
### App Domains
**Justification**. AppDomains require runtime support and are generally quite expensive. While still implemented by CoreCLR it's not available in .NET Native and we don't plan on adding this capability.
**Justification**. AppDomains require runtime support and are generally quite expensive. They are not implemented in .NET Core or .NET Native. We do not plan on adding this capability in future.
**Replacement**. AppDomains were used for different features; for isolation we recommend processes and/or containers. For dynamic loading, we provide `AssemblyLoadContext`. Information (such as the name and base directory) is provided by APIs on other types, for instance `AppContext.BaseDirectory `. Some scenarios, such as getting the list of loaded are unsupported as they are inherently fragile.
**Replacement**. AppDomains were used for different features; for isolation we recommend processes and/or containers. For dynamic loading, we provide `AssemblyLoadContext`. Information (such as the name and base directory) is provided by APIs on other types, for instance `AppContext.BaseDirectory`. Some scenarios, such as getting the list of loaded assemblies are unsupported as they are inherently fragile.
To make code migration from .NET Framework easier, we have exposed some of the `AppDomain` API surface in .NET Core and .NET Native. Some of the APIs work fine (e.g. `UnhandledException`), some of them do nothing (e.g. `SetCachePath`) and some of them throw `PlatformNotSupportedException` (e.g. `CreateDomain`). See more details about particular API differences in [TODO](https://github.com/dotnet/corefx/issues/18405).
### Remoting
**Justification**. The idea of .NET remoting -- which is transparent remote procedure calls -- has been identified as a problematic architecture. Outside of that realm, it's also used for cross AppDomain communication which is no longer supported. On top of that, remoting requires runtime support and is quite heavyweight.
**Replacement**. For communication across processes, inter-process communication (IPC) should be used, such as pipes or memory mapped files. Across machines, you should use a network based solution, preferably a low-overhead plain text protocol such as HTTP.
**Replacement**. For communication across processes, inter-process communication (IPC) should be used, such as pipes or memory mapped files. Across machines, you should use a network based solution, preferably `System.Net.Sockets` (see sample - [TODO](https://github.com/dotnet/corefx/issues/18394)).
### Code Access Security (CAS)
**Justification**. Sand-boxing, i.e. relying on the runtime or the framework to constrain which resources a managed application can run, is considered a non-goal for .NET Core. We've already state previously that relying on sand-boxing for security reasons isn't an approach we're feeling comfortable with; there are simply too many pieces in object oriented framework that can result in elevation of privileges. Thus we don't treat CAS as security boundary anymore. On top of that, it makes the implementation more complicated and often has performance implications for the happy path.
**Justification**. Sandboxing, i.e. relying on the runtime or the framework to constrain which resources a managed application or library can run is [not supported on .NET Framework](https://msdn.microsoft.com/en-us/library/c5tk9z76(v=vs.110).aspx) and therefore is also not supported on .NET Core or .NET Native. We believe that there are simply too many pieces in the .NET Framework and runtime that can result in elevation of privileges. Thus we don't treat [CAS as security boundary](https://msdn.microsoft.com/en-us/library/c5tk9z76(v=vs.110).aspx) anymore. On top of that, it makes the implementation more complicated and often has correctness performance implications for applications that don’t intend to use it.
**Replacement**. Use operating system provided security boundaries, such as user accounts for running processes with the least set of privileges.
**Replacement**. Use operating system provided security boundaries, such as virtualization, containers, or user accounts for running processes with the least set of privileges.
### Security Transparency
**Justification**. Similar to CAS, this feature allows separating sand-boxed code from security critical code in a declarative fashion. This feature was heavily used by Silverlight.
**Replacement**. Use operating system provided security boundaries, such as user accounts for running processes with the least set of privileges.
**Justification**. Similar to CAS, this feature allows separating sandboxed code from security critical code in a declarative fashion, but is [no longer supported as a security boundary](https://msdn.microsoft.com/en-us/library/ee191569(v=vs.110).aspx). This feature was heavily used by Silverlight.
**Replacement**. Use operating system provided security boundaries, such as virtualization, containers, or user accounts for running processes with the least set of privileges.

View File

@ -0,0 +1,98 @@
This document provides an overview of paradigm we are using in our tests.
# RemoteExecutor
In a variety of situations, it's useful to run some code in another process. Some examples:
- Being able to test things that require environment changes, e.g. how environment variables impact the app
- Being able to isolate changes to statics so that they don't affect concurrently or subsequently running tests, and to do so without needing to serialize all tests in the process
- Being able to verify that things that should crash do crash
- Being able to verify that things don't depend on state that's been configured previously, e.g. that some code you're calling doesn't require that some previous related code ran (e.g. that you can deserialize some state without it having previously been serialized in the same process)
- Being able to test cross-process support for various things, e.g. cross-process synchronization, cross-process memory-mapped files, that file locking works correctly cross-process, cross-process communication via stdin/stdout/stderr, etc.
To achieve, this we use `RemoteInvoke` which is defined in `RemoteExecutorTestBase.cs`. It passes information about a static method to be executed and the arguments to be passed to it out to a spawned process that invokes the method. Lambdas / anonymous methods may be used, but they must not close over any state (including `this`); accidentally closing over state will likely result in strange errors. For additional information see https://github.com/dotnet/corefx/blob/master/src/Common/tests/System/Diagnostics/RemoteExecutorTestBase.cs and https://xunit.github.io/docs/running-tests-in-parallel.html
Example (skipping additional usings):
```cs
using System.Diagnostics;
public class HttpWebRequestTest : RemoteExecutorTestBase
{
[Fact]
public void DefaultMaximumResponseHeadersLength_SetAndGetLength_ValuesMatch()
{
RemoteInvoke(() =>
{
const int NewDefaultMaximumResponseHeadersLength = 255;
HttpWebRequest.DefaultMaximumResponseHeadersLength = NewDefaultMaximumResponseHeadersLength;
Assert.Equal(NewDefaultMaximumResponseHeadersLength, HttpWebRequest.DefaultMaximumResponseHeadersLength);
return SuccessExitCode;
}).Dispose();
}
}
```
# LoopbackServer
When writing network related tests we try to avoid running tests against a remote endpoint if possible. We provide simple APIs to create a LoopbackServer and send responses. A high number of scenarios can be tested with it. For additional information see https://github.com/dotnet/corefx/blob/master/src/Common/tests/System/Net/Http/LoopbackServer.cs
Example (skipping additional usings and class scoping):
```cs
using System.Net.Test.Common;
[Fact]
public async Task Headers_SetAfterRequestSubmitted_ThrowsInvalidOperationException()
{
await LoopbackServer.CreateServerAsync(async (server, uri) =>
{
HttpWebRequest request = WebRequest.CreateHttp(uri);
Task<WebResponse> getResponse = request.GetResponseAsync();
await LoopbackServer.ReadRequestAndSendResponseAsync(server);
using (WebResponse response = await getResponse)
{
Assert.Throws<InvalidOperationException>(() => request.AutomaticDecompression = DecompressionMethods.Deflate);
}
});
}
```
# Outerloop
This one is fairly simple but often used incorrectly. When running tests which depend on outside influences like e.g. Hardware (Internet, SerialPort, ...) and you can't mitigate these dependencies, you might consider using the `[Outerloop]` attribute for your test.
With this attribute, tests are executed in a dedicated CI loop and won't break the default CI loops which get created when you submit a PR.
To run Outerloop tests locally you need to set the msbuild property "Outerloop" to true: `/p:Outerloop=true`.
To run Outerloop tests in CI you need to mention dotnet-bot and tell him which tests you want to run. See `@dotnet-bot help` for the exact loop names.
This doesn't mean that you should mark every test which executes against a remote endpoint as Outerloop. See below.
# Relay Server
For network related tests which needs to contact a remote endpoint instead of a LoopbackServer, you can use our Relay Servers. We invest in Infrastructure to provide these "safe" remote endpoints.
For more information see https://github.com/dotnet/corefx/blob/master/src/Common/tests/System/Net/Configuration.Http.cs
Example:
```cs
public static readonly object[][] EchoServers = System.Net.Test.Common.Configuration.Http.EchoServers;
[Theory, MemberData(nameof(EchoServers))]
public async Task ContentLength_Get_ExpectSameAsGetResponseStream(Uri remoteServer)
{
HttpWebRequest request = WebRequest.CreateHttp(remoteServer);
...
}
```
# Temp Directory
To support our tests running on as many target frameworks as possible, we need to be cautious when it comes to system resource access. The best example is trying to access a file outside of an AppContainer (UWP). We should depend on APIs which are specifically designed for these scenarios to work, e.g. TempDirectory. If a test case needs to store data on the FileSystem, consider using TempDirectory and TempFile APIs.
Example (skipping additional usings and class scoping):
```cs
using System.IO;
[Fact]
public void FileSystemWatcher_File_Changed_LastWrite()
{
using (var testDirectory = new TempDirectory())
using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
{
Directory.SetLastWriteTime(file.Path, DateTime.Now + TimeSpan.FromSeconds(10));
...
}
}
```