Skip to content

Commit ce099fd

Browse files
authored
test: add API parity tests (#666)
This commit adds some tests that assert the parity of the "real" `System.IO` APIs and our abstractions. This will hopefully make adding support for .NET 5 a bit easier.
2 parents 50594a9 + c74750f commit ce099fd

24 files changed

Lines changed: 348 additions & 22 deletions

.github/issue_label_bot.yaml

Lines changed: 0 additions & 4 deletions
This file was deleted.

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
with:
1919
fetch-depth: 0
2020
- name: Run tests
21-
run: dotnet test --verbosity normal --collect:"XPlat Code Coverage"
21+
run: dotnet test --collect:"XPlat Code Coverage"
2222
- name: Upload coverage
2323
uses: actions/upload-artifact@v2
2424
with:

.github/workflows/stale.yml

Lines changed: 0 additions & 17 deletions
This file was deleted.

Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)StrongName.snk</AssemblyOriginatorKeyFile>
88
<IncludeSymbols>true</IncludeSymbols>
99
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
10+
<LangVersion>8.0</LangVersion>
1011
<DefineConstants Condition="'$(TargetFramework)' == 'netcoreapp3.0' OR '$(TargetFramework)' == 'netstandard2.1'">$(DefineConstants);FEATURE_ASYNC_FILE;FEATURE_ENUMERATION_OPTIONS;FEATURE_ADVANCED_PATH_OPERATIONS</DefineConstants>
1112
</PropertyGroup>
1213
<ItemGroup>
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Reflection;
4+
using NUnit.Framework;
5+
using Snapshooter;
6+
using Snapshooter.NUnit;
7+
using static System.Reflection.BindingFlags;
8+
9+
namespace System.IO.Abstractions.Tests
10+
{
11+
[TestFixture]
12+
public class ApiParityTests
13+
{
14+
[Test]
15+
public void File() =>
16+
AssertParity(
17+
typeof(System.IO.File),
18+
typeof(System.IO.Abstractions.FileBase)
19+
);
20+
21+
[Test]
22+
public void FileInfo() =>
23+
AssertParity(
24+
typeof(System.IO.FileInfo),
25+
typeof(System.IO.Abstractions.FileInfoBase)
26+
);
27+
28+
[Test]
29+
public void Directory() =>
30+
AssertParity(
31+
typeof(System.IO.Directory),
32+
typeof(System.IO.Abstractions.DirectoryBase)
33+
);
34+
35+
[Test]
36+
public void DirectoryInfo() =>
37+
AssertParity(
38+
typeof(System.IO.DirectoryInfo),
39+
typeof(System.IO.Abstractions.DirectoryInfoBase)
40+
);
41+
42+
[Test]
43+
public void DriveInfo() =>
44+
AssertParity(
45+
typeof(System.IO.DriveInfo),
46+
typeof(System.IO.Abstractions.DriveInfoBase)
47+
);
48+
49+
[Test]
50+
public void Path() =>
51+
AssertParity(
52+
typeof(System.IO.Path),
53+
typeof(System.IO.Abstractions.PathBase)
54+
);
55+
56+
private void AssertParity(Type referenceType, Type abstractionType)
57+
{
58+
static IEnumerable<string> GetMembers(Type type) => type
59+
.GetMembers(bindingAttr: Instance | Static | Public | FlattenHierarchy)
60+
.Select(x => x.ToString())
61+
.OrderBy(x => x, StringComparer.Ordinal);
62+
var referenceMembers = GetMembers(referenceType)
63+
.Select(x => x.Replace("System.IO.FileStream", "System.IO.Stream"))
64+
.Select(x => x.Replace("System.IO.FileSystemInfo", "System.IO.Abstractions.IFileSystemInfo"))
65+
.Select(x => x.Replace("System.IO.FileInfo", "System.IO.Abstractions.IFileInfo"))
66+
.Select(x => x.Replace("System.IO.DirectoryInfo", "System.IO.Abstractions.IDirectoryInfo"))
67+
.Select(x => x.Replace("System.IO.DriveInfo", "System.IO.Abstractions.IDriveInfo"));
68+
var abstractionMembers = GetMembers(abstractionType)
69+
.Where(x => !x.Contains("op_Implicit"))
70+
.Where(x => x != "System.IO.Abstractions.IFileSystem get_FileSystem()")
71+
.Where(x => x != "System.IO.Abstractions.IFileSystem FileSystem");
72+
var diff = new ApiDiff(
73+
extraMembers: abstractionMembers.Except(referenceMembers),
74+
missingMembers: referenceMembers.Except(abstractionMembers)
75+
);
76+
Snapshot.Match(diff, SnapshotNameExtension.Create(snapshotSuffix));
77+
}
78+
79+
private readonly struct ApiDiff
80+
{
81+
public ApiDiff(IEnumerable<string> extraMembers, IEnumerable<string> missingMembers)
82+
{
83+
ExtraMembers = extraMembers.ToArray();
84+
MissingMembers = missingMembers.ToArray();
85+
86+
}
87+
88+
public string[] ExtraMembers { get; }
89+
public string[] MissingMembers { get; }
90+
}
91+
92+
#if NETCOREAPP3_1
93+
private const string snapshotSuffix = ".NET Core 3.1";
94+
#elif NETCOREAPP2_1
95+
private const string snapshotSuffix = ".NET Core 2.1";
96+
#elif NET461
97+
private const string snapshotSuffix = ".NET Framework 4.6.1";
98+
#else
99+
#error Unknown target framework.
100+
#endif
101+
}
102+
}

tests/System.IO.Abstractions.Tests/System.IO.Abstractions.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@
2020
<PackageReference Include="Moq" Version="4.14.5" />
2121
<PackageReference Include="nunit" Version="3.12.0" />
2222
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
23+
<PackageReference Include="Snapshooter.NUnit" Version="0.5.8" />
2324
</ItemGroup>
2425
</Project>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"ExtraMembers": [
3+
"System.Security.AccessControl.DirectorySecurity GetAccessControl()",
4+
"System.Security.AccessControl.DirectorySecurity GetAccessControl(System.Security.AccessControl.AccessControlSections)",
5+
"Void Create(System.Security.AccessControl.DirectorySecurity)",
6+
"Void SetAccessControl(System.Security.AccessControl.DirectorySecurity)"
7+
],
8+
"MissingMembers": [
9+
"System.Collections.Generic.IEnumerable`1[System.IO.Abstractions.IDirectoryInfo] EnumerateDirectories(System.String, System.IO.EnumerationOptions)",
10+
"System.Collections.Generic.IEnumerable`1[System.IO.Abstractions.IFileInfo] EnumerateFiles(System.String, System.IO.EnumerationOptions)",
11+
"System.Collections.Generic.IEnumerable`1[System.IO.Abstractions.IFileSystemInfo] EnumerateFileSystemInfos(System.String, System.IO.EnumerationOptions)",
12+
"System.IO.Abstractions.IDirectoryInfo[] GetDirectories(System.String, System.IO.EnumerationOptions)",
13+
"System.IO.Abstractions.IFileInfo[] GetFiles(System.String, System.IO.EnumerationOptions)",
14+
"System.IO.Abstractions.IFileSystemInfo[] GetFileSystemInfos(System.String, System.IO.EnumerationOptions)",
15+
"System.Object GetLifetimeService()",
16+
"System.Object InitializeLifetimeService()",
17+
"Void .ctor(System.String)",
18+
"Void GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)"
19+
]
20+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"ExtraMembers": [
3+
"System.Security.AccessControl.DirectorySecurity GetAccessControl()",
4+
"System.Security.AccessControl.DirectorySecurity GetAccessControl(System.Security.AccessControl.AccessControlSections)",
5+
"Void Create(System.Security.AccessControl.DirectorySecurity)",
6+
"Void SetAccessControl(System.Security.AccessControl.DirectorySecurity)"
7+
],
8+
"MissingMembers": [
9+
"System.Object GetLifetimeService()",
10+
"System.Object InitializeLifetimeService()",
11+
"Void .ctor(System.String)",
12+
"Void GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)"
13+
]
14+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"ExtraMembers": [],
3+
"MissingMembers": [
4+
"System.IO.Abstractions.IDirectoryInfo CreateSubdirectory(System.String, System.Security.AccessControl.DirectorySecurity)",
5+
"System.Object GetLifetimeService()",
6+
"System.Object InitializeLifetimeService()",
7+
"System.Runtime.Remoting.ObjRef CreateObjRef(System.Type)",
8+
"Void .ctor(System.String)",
9+
"Void GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)"
10+
]
11+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"ExtraMembers": [
3+
"System.IO.Abstractions.IDirectoryInfo CreateDirectory(System.String, System.Security.AccessControl.DirectorySecurity)",
4+
"System.Security.AccessControl.DirectorySecurity GetAccessControl(System.String)",
5+
"System.Security.AccessControl.DirectorySecurity GetAccessControl(System.String, System.Security.AccessControl.AccessControlSections)",
6+
"Void SetAccessControl(System.String, System.Security.AccessControl.DirectorySecurity)"
7+
],
8+
"MissingMembers": [
9+
"System.Collections.Generic.IEnumerable`1[System.String] EnumerateDirectories(System.String, System.String, System.IO.EnumerationOptions)",
10+
"System.Collections.Generic.IEnumerable`1[System.String] EnumerateFileSystemEntries(System.String, System.String, System.IO.EnumerationOptions)",
11+
"System.Collections.Generic.IEnumerable`1[System.String] EnumerateFiles(System.String, System.String, System.IO.EnumerationOptions)",
12+
"System.String[] GetDirectories(System.String, System.String, System.IO.EnumerationOptions)",
13+
"System.String[] GetFileSystemEntries(System.String, System.String, System.IO.EnumerationOptions)",
14+
"System.String[] GetFileSystemEntries(System.String, System.String, System.IO.SearchOption)",
15+
"System.String[] GetFiles(System.String, System.String, System.IO.EnumerationOptions)"
16+
]
17+
}

0 commit comments

Comments
 (0)