Skip to content

Commit

Permalink
Add auth tests under UWP
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisdunelm committed Sep 11, 2017
1 parent a44a3d1 commit 17e8529
Show file tree
Hide file tree
Showing 17 changed files with 232 additions and 107 deletions.
33 changes: 24 additions & 9 deletions Src/Support/Google.Apis.Auth.Tests/Google.Apis.Auth.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,35 +1,50 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">

<PropertyGroup>
<!-- net452 is the earliest desktop version supported by xunit runner -->
<TargetFrameworks>netcoreapp1.0;net452;net46</TargetFrameworks>
<TargetFrameworks>netcoreapp1.0;net452;net46;uap10.0</TargetFrameworks>
<!-- On non-Windows platforms only net core can be built -->
<TargetFrameworks Condition="'$(OS)' != 'Windows_NT'">netcoreapp1.0</TargetFrameworks>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<AssemblyOriginatorKeyFile>..\..\..\google.apis.snk</AssemblyOriginatorKeyFile>
<IsPackable>false</IsPackable>
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.0-beta5-build3769" />
<PackageReference Include="Xunit.Combinatorial" Version="1.2.7" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta5-build3769" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="Moq" Version="4.7.99" />
<ProjectReference Include="..\Google.Apis.Auth\Google.Apis.Auth.csproj" />
<ProjectReference Include="..\Google.Apis\Google.Apis.csproj" />
<ProjectReference Include="..\Google.Apis.Core\Google.Apis.Core.csproj" />
<ProjectReference Include="..\Google.Apis.Tests\Google.Apis.Tests.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)'=='net452' or '$(TargetFramework)'=='net46'">
<PackageReference Include="BouncyCastle" Version="1.8.1" />
<PropertyGroup Condition="'$(TargetFramework)'=='uap10.0'">
<TargetFrameworkIdentifier>.NETStandard</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v1.4</TargetFrameworkVersion>
<TargetFrameworkMoniker>UAP,Version=v10.0</TargetFrameworkMoniker>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.14393.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker>
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
<DefineConstants>$(DefineConstants);UAP10_0</DefineConstants>
<DefaultLanguage>en-US</DefaultLanguage>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)'!='uap10.0'">
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta5-build3769" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
</ItemGroup>

<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
<ItemGroup Condition="'$(TargetFramework)'=='uap10.0'">
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform" Version="5.4.0" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)'=='net452' or '$(TargetFramework)'=='net46'">
<PackageReference Include="BouncyCastle" Version="1.8.1" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ public async Task Invalid_Aud()
[Fact]
public async Task Validate_Signature_Time()
{

var clockInvalid1 = new MockClock() { UtcNow = new DateTime(2017, 5, 31, 10, 22, 0, DateTimeKind.Utc) };
var clockValid1 = new MockClock() { UtcNow = new DateTime(2017, 5, 31, 10, 24, 0, DateTimeKind.Utc) };
var clockValid2 = new MockClock() { UtcNow = new DateTime(2017, 5, 31, 11, 22, 0, DateTimeKind.Utc) };
Expand Down Expand Up @@ -188,14 +187,17 @@ public async Task Invalid_HostedDomain()
[Fact]
public async Task Validate_CertCache()
{
// Reset GoogleJsonWebSignature before starting this test
GoogleJsonWebSignature._certCacheDownloadTime = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);

var clock1 = new MockClock() { UtcNow = new DateTime(2017, 5, 31, 11, 24, 0, DateTimeKind.Utc) };
var clock2Cached = new MockClock() { UtcNow = clock1.UtcNow + GoogleJsonWebSignature.CertCacheRefreshInterval - TimeSpan.FromSeconds(1) };
var clock3Uncached = new MockClock() { UtcNow = clock1.UtcNow + GoogleJsonWebSignature.CertCacheRefreshInterval + TimeSpan.FromSeconds(1) };

var rsas1 = await GoogleJsonWebSignature.GetGoogleCertsAsync(clock1, false, GoogleCertsJson);
var rsas2Cached = await GoogleJsonWebSignature.GetGoogleCertsAsync(clock2Cached, false, GoogleCertsJson);
var rsas3Refreshed = await GoogleJsonWebSignature.GetGoogleCertsAsync(clock3Uncached, false, GoogleCertsJson);
var rsas4Forced = await GoogleJsonWebSignature.GetGoogleCertsAsync(clock3Uncached, true, GoogleCertsJson);
var rsas1 = await GoogleJsonWebSignature.GetGoogleCertsAsync(clock1, false, GoogleCertsJson).ConfigureAwait(false);
var rsas2Cached = await GoogleJsonWebSignature.GetGoogleCertsAsync(clock2Cached, false, GoogleCertsJson).ConfigureAwait(false);
var rsas3Refreshed = await GoogleJsonWebSignature.GetGoogleCertsAsync(clock3Uncached, false, GoogleCertsJson).ConfigureAwait(false);
var rsas4Forced = await GoogleJsonWebSignature.GetGoogleCertsAsync(clock3Uncached, true, GoogleCertsJson).ConfigureAwait(false);

Assert.NotNull(rsas1);
Assert.Same(rsas1, rsas2Cached);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
using Google.Apis.Tests.Mocks;
using Google.Apis.Util;
using Google.Apis.Util.Store;
using Moq;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -98,9 +97,7 @@ public void LoadTokenAsync_NoDataStore()
[Fact]
public void LoadTokenAsync_NullResponse()
{
TaskCompletionSource<TokenResponse> tcs = new TaskCompletionSource<TokenResponse>();
tcs.SetResult(null);
Assert.Null(SubtestLoadTokenAsync(tcs));
Assert.Null(SubtestLoadTokenAsync(null));
}

[Fact]
Expand All @@ -110,21 +107,18 @@ public void LoadTokenAsync_TokenResponse()
{
AccessToken = "access"
};

TaskCompletionSource<TokenResponse> tcs = new TaskCompletionSource<TokenResponse>();
tcs.SetResult(response);
var result = SubtestLoadTokenAsync(tcs);
var result = SubtestLoadTokenAsync(response);
Assert.Equal(response, result);
}

private TokenResponse SubtestLoadTokenAsync(TaskCompletionSource<TokenResponse> tcs)
private TokenResponse SubtestLoadTokenAsync(TokenResponse response)
{
var mock = new Mock<IDataStore>();
mock.Setup(ds => ds.GetAsync<TokenResponse>("user")).Returns(tcs.Task);
var flow = CreateFlow(dataStore: mock.Object);
var result = flow.LoadTokenAsync("user", CancellationToken.None).Result;
mock.Verify(ds => ds.GetAsync<TokenResponse>("user"));
return result;
var datastore = new MemoryDataStore();
var flow0 = CreateFlow(dataStore: datastore);
Assert.Null(flow0.LoadTokenAsync("user", CancellationToken.None).Result);
datastore.StoreAsync("user", response).Wait();
var flow1 = CreateFlow(dataStore: datastore);
return flow1.LoadTokenAsync("user", CancellationToken.None).Result;
}

#endregion
Expand All @@ -148,7 +142,7 @@ public void TestCreateAuthorizationCodeRequest()
[Fact]
public void TestExchangeCodeForTokenAsync()
{
var mock = new Mock<IDataStore>();
var datastore = new MemoryDataStore();
var handler = new FetchTokenMessageHandler();
handler.AuthorizationCodeTokenRequest = new AuthorizationCodeTokenRequest()
{
Expand All @@ -158,21 +152,18 @@ public void TestExchangeCodeForTokenAsync()
};
MockHttpClientFactory mockFactory = new MockHttpClientFactory(handler);

TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
tcs.SetResult(null);
mock.Setup(ds => ds.StoreAsync("uSer", It.IsAny<TokenResponse>())).Returns(tcs.Task);

var flow = CreateFlow(httpClientFactory: mockFactory, scopes: new[] { "a" }, dataStore: mock.Object);
var flow = CreateFlow(httpClientFactory: mockFactory, scopes: new[] { "a" }, dataStore: datastore);
var response = flow.ExchangeCodeForTokenAsync("uSer", "c0de", "redIrect", CancellationToken.None).Result;
SubtestTokenResponse(response);

mock.Verify(ds => ds.StoreAsync("uSer", It.IsAny<TokenResponse>()));
Assert.Single(datastore.Items);
Assert.EndsWith("uSer", datastore.Items.First().Key);
}

[Fact]
public void TestRefreshTokenAsync()
{
var mock = new Mock<IDataStore>();
var datastore = new MemoryDataStore();
var handler = new FetchTokenMessageHandler();
handler.RefreshTokenRequest = new RefreshTokenRequest()
{
Expand All @@ -181,16 +172,12 @@ public void TestRefreshTokenAsync()
};
MockHttpClientFactory mockFactory = new MockHttpClientFactory(handler);

TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
tcs.SetResult(null);
mock.Setup(ds => ds.StoreAsync("uSer", It.IsAny<TokenResponse>())).Returns(tcs.Task);

var flow = CreateFlow(httpClientFactory: mockFactory, scopes: new[] { "a" }, dataStore: mock.Object);
var flow = CreateFlow(httpClientFactory: mockFactory, scopes: new[] { "a" }, dataStore: datastore);
var response = flow.RefreshTokenAsync("uSer", "REFRESH", CancellationToken.None).Result;
SubtestTokenResponse(response);


mock.Verify(ds => ds.StoreAsync("uSer", It.IsAny<TokenResponse>()));
Assert.Single(datastore.Items);
Assert.EndsWith("uSer", datastore.Items.First().Key);
}

#region FetchToken
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,10 @@
limitations under the License.
*/

using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

using Moq;

using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Requests;
using Google.Apis.Auth.OAuth2.Responses;
using Google.Apis.Http;
using Google.Apis.Util.Store;
using Google.Apis.Auth.OAuth2;
using System.Collections.Generic;
using Xunit;

namespace Google.Apis.Auth.Tests.OAuth2.Flows
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
limitations under the License.
*/

#if !UAP10_0

using Google.Apis.Auth.OAuth2;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -152,3 +154,5 @@ public async Task InvalidRequestTooManyHeaders()

}
}

#endif
2 changes: 1 addition & 1 deletion Src/Support/Google.Apis.Auth.Tests/OAuth2/Pkcs8Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public void RsaFuzzTest()
Assert.Equal(publicKey.Modulus.ToByteArrayUnsigned(), Pkcs8.TrimLeadingZeroes(exportedParams.Modulus, false));
}
}
#elif NETCOREAPP1_0 || NETCOREAPP1_1
#elif NETCOREAPP1_0 || NETCOREAPP1_1 || UAP10_0
// RsaFuzzTest() can't run on net core.
#else
#error Unsupported platform.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public void Pkcs8Decoding_FromPrivateKey()
[Fact]
public async Task ValidLocallySignedAccessToken_FromX509Certificate()
{
#if NETCOREAPP1_0 || NETCOREAPP1_1
#if NETCOREAPP1_0 || NETCOREAPP1_1 || UAP10_0
const string sPfx = @"
MIIGMQIBAzCCBfcGCSqGSIb3DQEHAaCCBegEggXkMIIF4DCCAt8GCSqGSIb3DQEHBqCCAtAwggLM
AgEAMIICxQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQImgNbotR3pnACAggAgIICmMHYqn7R
Expand Down Expand Up @@ -192,7 +192,7 @@ public async Task ValidLocallySignedAccessToken_FromX509Certificate()
privateKey.ImportParameters(rsaParameters);
x509Cert.PrivateKey = privateKey;
#else
#error Unsupported target
#error Unsupported platform
#endif
Assert.True(x509Cert.HasPrivateKey);

Expand Down
2 changes: 1 addition & 1 deletion Src/Support/Google.Apis.Auth/GoogleJsonWebSignature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ private static byte[] Base64UrlDecode(string base64Url)
}

private static SemaphoreSlim _certCacheLock = new SemaphoreSlim(1);
private static DateTime _certCacheDownloadTime;
internal static DateTime _certCacheDownloadTime; // internal for testing
private static List<RSA> _certCache;

// internal for testing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">c:\chrisdunelm\uwp2\Src\Support\Google.Apis.IntegrationTests.Uwp\project.lock.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">c:\chrisdunelm\uwp2\Packages</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">c:\chrisdunelm\uwp2\Packages</NuGetPackageFolders>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">C:\chrisdunelm\uwp2\Src\Support\Google.Apis.IntegrationTests.Uwp\project.lock.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">C:\chrisdunelm\uwp2\Packages</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\chrisdunelm\uwp2\Packages</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">ProjectJson</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">4.3.0</NuGetToolVersion>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@
<Project>{b8d261f0-4c17-4887-bbc3-cbbfdf0d5328}</Project>
<Name>Google.Apis.Tests</Name>
</ProjectReference>
<ProjectReference Include="..\Google.Apis.Auth.Tests\Google.Apis.Auth.Tests.csproj">
<Project>{f106e24e-49f8-4d86-8cbf-9616178ca08c}</Project>
<Name>Google.Apis.Auth.Tests</Name>
</ProjectReference>
<ProjectReference Include="..\Google.Apis\Google.Apis.csproj">
<Project>{a0e0f5aa-6a5f-44a1-8dc7-0443f01c72e2}</Project>
<Name>Google.Apis</Name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">C:\chrisdunelm\uwp2\Src\Support\Google.Apis.Tests.Uwp\project.lock.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">C:\chrisdunelm\uwp2\Packages</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\chrisdunelm\uwp2\Packages</NuGetPackageFolders>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">c:\chrisdunelm\uwp2\Src\Support\Google.Apis.Tests.Uwp\project.lock.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">c:\chrisdunelm\uwp2\Packages</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">c:\chrisdunelm\uwp2\Packages</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">ProjectJson</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">4.3.0</NuGetToolVersion>
</PropertyGroup>
Expand Down
70 changes: 36 additions & 34 deletions Src/Support/Google.Apis.Tests.Uwp/XunitProxy.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using Google.Apis.Tests.Apis.Logging;
using Google.Apis.Auth.Tests;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace Google.Apis.Tests.Uwp
{
Expand All @@ -21,46 +22,47 @@ public XunitException(MethodInfo method, Exception inner)
public void RunAllXunitTests()
{
// TODO: Theory tests
int testCount = 0;
var googleApiTests = typeof(NullLoggerTests).GetTypeInfo().Assembly.GetTypes();
foreach (var type in googleApiTests)
{
var typeInfo = type.GetTypeInfo();
// Only public classes
if (!typeInfo.IsPublic)
{
continue;
}
// Only classes that have a parameterless public constructor
var ctor = typeInfo.DeclaredConstructors.FirstOrDefault(x => x.IsPublic && !x.GetParameters().Any());
if (ctor == null)
var googleApiTypes = typeof(ApplicationContextTests).GetTypeInfo().Assembly.GetTypes();
var googleApiAuthTypes = typeof(GoogleJsonWebSignatureTests).GetTypeInfo().Assembly.GetTypes();
var allTypes = googleApiTypes.Concat(googleApiAuthTypes);
var facts = allTypes
.Select(type => type.GetTypeInfo())
.Where(typeInfo => typeInfo.IsPublic)
.Select(typeInfo => new
{
continue;
}
var methods = type.GetTypeInfo().DeclaredMethods;
foreach (var method in typeInfo.DeclaredMethods)
typeInfo,
ctor = typeInfo.DeclaredConstructors.FirstOrDefault(x => x.IsPublic && !x.GetParameters().Any())
})
.Where(x => x.ctor != null)
.SelectMany(x => x.typeInfo.DeclaredMethods.Select(method => new { x.ctor, method }))
.Where(x => x.method.GetCustomAttribute<Xunit.FactAttribute>()?.GetType() == typeof(Xunit.FactAttribute))
.ToList();
// Execute all xunit Fact tests
foreach (var fact in facts)
{
var test = fact.ctor.Invoke(new object[0]);
var method = fact.method;
// TODO: Perhaps collect all test failures, throw at end
try
{
// TheoryAttribute derives from FactAttribute
var isFact = method.GetCustomAttribute<Xunit.FactAttribute>()?.GetType() == typeof(Xunit.FactAttribute);
if (isFact)
var ret = method.Invoke(test, new object[0]);
if (method.ReturnType == typeof(Task))
{
testCount += 1;
var test = ctor.Invoke(new object[0]);
// TODO: Collect all test failures, throw at end
try
{
method.Invoke(test, new object[0]);
}
catch (Exception e)
{
e = (e as TargetInvocationException)?.InnerException ?? e;
throw new XunitException(method, e);
}
((Task)ret).Wait();
}
else if (method.ReturnType != typeof(void))
{
throw new InvalidOperationException($"Unexpected return type {method.ReturnType} in test method {method}");
}
}
catch (Exception e)
{
e = (e as TargetInvocationException)?.InnerException ?? e;
throw new XunitException(method, e);
}
}
// Confirm that the correct number of tests has actually run.
Assert.AreEqual(156, testCount);
Assert.AreEqual(224, facts.Count);
}
}
}

0 comments on commit 17e8529

Please sign in to comment.