Skip to content

Commit 1cefe59

Browse files
committed
osx: dynamically skip keychain test if invalid
Dynamically skip the macOS Keychain read/write/delete test if the Keychain is in a "strange" state. There is an unknown issue that the keychain can sometimes get itself in where all API calls result in an errSecAuthFailed error. The only solution seems to be a machine restart; not possible in CI! The problem has plagued others who are calling the same Keychain APIs from C# such as the MSAL.NET team - they don't know either. It might have something to do with the code signing signature of the binary (our collective best theory). It's probably only diagnosable at this point by Apple, but we don't have a reliable way to reproduce the problem.
1 parent 29404a2 commit 1cefe59

File tree

4 files changed

+56
-1
lines changed

4 files changed

+56
-1
lines changed

src/shared/Microsoft.Git.CredentialManager.Tests/Interop/MacOS/MacOSKeychainTests.cs

+16-1
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22
// Licensed under the MIT license.
33
using System;
44
using Xunit;
5+
using Microsoft.Git.CredentialManager.Interop;
56
using Microsoft.Git.CredentialManager.Interop.MacOS;
7+
using Microsoft.Git.CredentialManager.Interop.MacOS.Native;
68

79
namespace Microsoft.Git.CredentialManager.Tests.Interop.MacOS
810
{
911
public class MacOSKeychainTests
1012
{
1113
private const string TestNamespace = "git-test";
1214

13-
[PlatformFact(Platforms.MacOS)]
15+
[SkippablePlatformFact(Platforms.MacOS)]
1416
public void MacOSKeychain_ReadWriteDelete()
1517
{
1618
var keychain = new MacOSKeychain(TestNamespace);
@@ -32,6 +34,19 @@ public void MacOSKeychain_ReadWriteDelete()
3234
Assert.Equal(account, outCredential.Account);
3335
Assert.Equal(password, outCredential.Password);
3436
}
37+
// There is an unknown issue that the keychain can sometimes get itself in where all API calls
38+
// result in an errSecAuthFailed error. The only solution seems to be a machine restart, which
39+
// isn't really possible in CI!
40+
// The problem has plagued others who are calling the same Keychain APIs from C# such as the
41+
// MSAL.NET team - they don't know either. It might have something to do with the code signing
42+
// signature of the binary (our collective best theory).
43+
// It's probably only diagnosable at this point by Apple, but we don't have a reliable way to
44+
// reproduce the problem.
45+
// For now we will just mark the test as "skipped" when we hit this problem.
46+
catch (InteropException iex) when (iex.ErrorCode == SecurityFramework.ErrorSecAuthFailed)
47+
{
48+
AssertEx.Skip("macOS Keychain is in an invalid state (errSecAuthFailed)");
49+
}
3550
finally
3651
{
3752
// Ensure we clean up after ourselves even in case of 'get' failures
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using Xunit;
2+
3+
namespace Microsoft.Git.CredentialManager.Tests
4+
{
5+
public static class AssertEx
6+
{
7+
/// <summary>
8+
/// Requires the fact or theory be marked with the <see cref="SkippableFactAttribute"/>
9+
/// or <see cref="SkippableTheoryAttribute"/>.
10+
/// </summary>
11+
/// <param name="reason">Reason the test has been skipped.</param>
12+
public static void Skip(string reason)
13+
{
14+
Xunit.Skip.If(true, reason);
15+
}
16+
}
17+
}

src/shared/TestInfrastructure/PlatformAttributes.cs

+22
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,28 @@ public PlatformTheoryAttribute(Platforms platforms)
2828
}
2929
}
3030

31+
public class SkippablePlatformFactAttribute : SkippableFactAttribute
32+
{
33+
public SkippablePlatformFactAttribute(Platforms platforms)
34+
{
35+
Xunit.Skip.IfNot(
36+
XunitHelpers.IsSupportedPlatform(platforms),
37+
"Test not supported on this platform."
38+
);
39+
}
40+
}
41+
42+
public class SkippablePlatformTheoryAttribute : SkippableTheoryAttribute
43+
{
44+
public SkippablePlatformTheoryAttribute(Platforms platforms)
45+
{
46+
Xunit.Skip.IfNot(
47+
XunitHelpers.IsSupportedPlatform(platforms),
48+
"Test not supported on this platform."
49+
);
50+
}
51+
}
52+
3153
internal static class XunitHelpers
3254
{
3355
public static bool IsSupportedPlatform(Platforms platforms)

src/shared/TestInfrastructure/TestInfrastructure.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<ItemGroup>
1212
<PackageReference Include="Moq" Version="4.10.1" />
1313
<PackageReference Include="xunit" Version="2.4.1" />
14+
<PackageReference Include="Xunit.SkippableFact" Version="1.4.13" />
1415
</ItemGroup>
1516

1617
<ItemGroup>

0 commit comments

Comments
 (0)