Improve integration tests; fix combinations in templates

This commit is contained in:
Hananiel Sarella 2019-10-16 23:50:51 -04:00
Родитель ef812d0180
Коммит baee271620
16 изменённых файлов: 268 добавлений и 118 удалений

Просмотреть файл

@ -39,12 +39,12 @@ stages:
command: 'test'
arguments: '--filter Category!=Integration'
testRunTitle: 'Unit Tests'
# - task: DotNetCoreCLI@2
# displayName: Dotnet test (Integration Tests)
# inputs:
# command: 'test'
# arguments: '--filter Category=Integration'
# testRunTitle: 'Unit Tests'
- task: DotNetCoreCLI@2
displayName: Dotnet test (Integration Tests)
inputs:
command: 'test'
arguments: '--filter Category=Integration'
testRunTitle: 'Unit Tests'
- task: DotNetCoreCLI@2
displayName: Dotnet publish
inputs:

Просмотреть файл

@ -53,7 +53,7 @@ namespace Steeltoe.Initializr.Services.Mustache
public async Task<string> EvaluateExpressionAsync(Dictionary<string, string> dataView)
{
using (Timing.Over(_logger, "Build MoreThanOne Expression"))
using (Timing.Over(_logger, "Evaluate MoreThanOne Expression"))
{
return await Task.Run(() => _evaluationExpression(dataView));
}

Просмотреть файл

@ -15,6 +15,7 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
@ -89,6 +90,11 @@ namespace Steeltoe.Initializr.Services.Mustache
case ExpressionTypeEnum.String:
expression = new CaseExpression(_logger, calculatedParam, schema);
break;
case ExpressionTypeEnum.MoreThanOne:
expression = new MoreThanOneExpression(_logger, calculatedParam, schema);
break;
default:
throw new InvalidEnumArgumentException("Calculated Expression", (int)calculatedParam.ExpressionType, typeof(ExpressionTypeEnum));
}
if (expression != null)

Просмотреть файл

@ -12,7 +12,9 @@ using Steeltoe.Extensions.Logging;
#endif
#if (CloudFoundry)
using Steeltoe.Extensions.Configuration;
#if(!ConfigServer)
using Steeltoe.Extensions.Configuration.CloudFoundry;
#endif
#endif
#if (ConfigServer)
using Steeltoe.Extensions.Configuration.ConfigServer;
@ -43,7 +45,9 @@ namespace Company.WebApplication1
.UseDefaultServiceProvider(configure => configure.ValidateScopes = false)
#if (CloudFoundry)
.UseCloudFoundryHosting() //Enable listening on a Env provided port
#if(!ConfigServer)
.AddCloudFoundry() //Add cloudfoundry environment variables as a configuration source
#endif
#endif
#if (ConfigServer)
.AddConfigServer()

Просмотреть файл

@ -12,7 +12,9 @@ using Steeltoe.Extensions.Logging;
#endif
#if (CloudFoundry)
using Steeltoe.Extensions.Configuration;
#if(!ConfigServer)
using Steeltoe.Extensions.Configuration.CloudFoundry;
#endif
#endif
#if (ConfigServer)
using Steeltoe.Extensions.Configuration.ConfigServer;
@ -43,7 +45,9 @@ namespace Company.WebApplication1
.UseDefaultServiceProvider(configure => configure.ValidateScopes = false)
#if (CloudFoundry)
.UseCloudFoundryHosting() //Enable listening on a Env provided port
#if(!ConfigServer)
.AddCloudFoundry() //Add cloudfoundry environment variables as a configuration source
#endif
#endif
#if (ConfigServer)
.AddConfigServer()

Просмотреть файл

@ -7,21 +7,20 @@ using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization;
{{/Auth}}
using Microsoft.AspNetCore.Mvc;
{{#AnySqlData}}
using System.Data;
{{/AnySqlData}}
{{#SQLServer}}
using System.Data.SqlClient;
using System.Data;
{{/SQLServer}}
{{#MySql}}
using MySql.Data.MySqlClient;
using System.Data;
{{/MySql}}
{{#Postgres}}
using Npgsql;
using System.Data;
{{/Postgres}}
{{#MongoDB}}
using MongoDB.Driver;
using System.Data;
{{/MongoDB}}
{{#Redis}}
using Microsoft.Extensions.Caching.Distributed;

Просмотреть файл

@ -13,7 +13,9 @@ using Steeltoe.Extensions.Logging;
{{/ActuatorsOrDynamicLogger}}
{{#CloudFoundry}}
using Steeltoe.Extensions.Configuration;
{{^ConfigServer}}
using Steeltoe.Extensions.Configuration.CloudFoundry;
{{/ConfigServer}}
{{/CloudFoundry}}
{{#ConfigServer}}
using Steeltoe.Extensions.Configuration.ConfigServer;
@ -44,7 +46,9 @@ namespace {{ProjectNameSpace}}
.UseDefaultServiceProvider(configure => configure.ValidateScopes = false)
{{#CloudFoundry}}
.UseCloudFoundryHosting() //Enable listening on a Env provided port
{{^ConfigServer}}
.AddCloudFoundry() //Add cloudfoundry environment variables as a configuration source
{{/ConfigServer}}
{{/CloudFoundry}}
{{#ConfigServer}}
.AddConfigServer()

Просмотреть файл

@ -139,6 +139,11 @@
"Expression": "SQLServer,MySql,Postgres,MongoDB,RabbitMQ,Redis,ConfigServer,PlaceholderConfig,RandomValueConfig,CircuitBreaker",
"ExpressionType": "MoreThanOne"
},
{
"Name": "AnySqlData",
"Expression": "SQLServer,MySql,Postgres,MongoDB",
"ExpressionType": "Any"
},
{
"Name": "AnyConnector",
"Expression": "MySql,Postgres,Redis,MongoDB,RabbitMQ,OAuthConnector",

Просмотреть файл

@ -7,21 +7,20 @@ using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization;
{{/Auth}}
using Microsoft.AspNetCore.Mvc;
{{#AnySqlData}}
using System.Data;
{{/AnySqlData}}
{{#SQLServer}}
using System.Data.SqlClient;
using System.Data;
{{/SQLServer}}
{{#MySql}}
using MySql.Data.MySqlClient;
using System.Data;
{{/MySql}}
{{#Postgres}}
using Npgsql;
using System.Data;
{{/Postgres}}
{{#MongoDB}}
using MongoDB.Driver;
using System.Data;
{{/MongoDB}}
{{#Redis}}
using Microsoft.Extensions.Caching.Distributed;

Просмотреть файл

@ -13,7 +13,9 @@ using Steeltoe.Extensions.Logging;
{{/ActuatorsOrDynamicLogger}}
{{#CloudFoundry}}
using Steeltoe.Extensions.Configuration;
{{^ConfigServer}}
using Steeltoe.Extensions.Configuration.CloudFoundry;
{{/ConfigServer}}
{{/CloudFoundry}}
{{#ConfigServer}}
using Steeltoe.Extensions.Configuration.ConfigServer;
@ -45,7 +47,9 @@ namespace {{ProjectNameSpace}}
.UseDefaultServiceProvider(configure => configure.ValidateScopes = false)
{{#CloudFoundry}}
.UseCloudFoundryHosting() //Enable listening on a Env provided port
{{^ConfigServer}}
.AddCloudFoundry() //Add cloudfoundry environment variables as a configuration source
{{/ConfigServer}}
{{/CloudFoundry}}
{{#ConfigServer}}
.AddConfigServer()

Просмотреть файл

@ -139,6 +139,11 @@
"Expression": "SQLServer,MySql,Postgres,MongoDB,RabbitMQ,Redis,ConfigServer,PlaceholderConfig,RandomValueConfig,CircuitBreaker,CloudFoundry",
"ExpressionType": "MoreThanOne"
},
{
"Name": "AnySqlData",
"Expression": "SQLServer,MySql,Postgres,MongoDB",
"ExpressionType": "Any"
},
{
"Name": "AnyConnector",
"Expression": "MySql,Postgres,SQLServer,Redis,MongoDB,RabbitMQ,OAuthConnector",

Просмотреть файл

@ -1,98 +0,0 @@
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Microsoft.Extensions.Logging;
using Steeltoe.Initializr.Services;
using Steeltoe.Initializr.Services.Mustache;
using Steeltoe.InitializrTests;
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
using Version = Steeltoe.Initializr.Services.Mustache.Version;
namespace Steeltoe.Initializr.Tests
{
[Trait("Category", "Integration")]
public class IntegrationTests : XunitLoggingBase
{
private readonly ITestOutputHelper _testOutputHelper;
private readonly LoggerFactory _loggerFactory;
public IntegrationTests(ITestOutputHelper testOutputHelper)
: base(testOutputHelper)
{
_testOutputHelper = testOutputHelper;
_loggerFactory = new LoggerFactory();
_loggerFactory.AddProvider(new XunitLoggerProvider(testOutputHelper));
}
[Theory]
[ClassData(typeof(AllImplementationsAndTemplates))]
public async Task CreateTemplate_Test(ITemplateService templateService, string templateName, TemplateVersion version)
{
if (version == TemplateVersion.V3)
{
return;
}
if (templateName.Contains("React"))
{
return;
}
var deps = templateService.GetDependencies(templateName, version);
foreach (var dep in deps)
{
_testOutputHelper.WriteLine($"testing dep: --" + dep.ShortName);
// if (templateService is MustacheTemplateService) return;
// if (!templateName.Contains("React")) return;
// if (version == TemplateVersion.V3) return;
var archive = await templateService.GenerateProjectArchiveAsync(new Models.GeneratorModel()
{
// Todo : fix this
Dependencies = dep.ShortName,
TemplateShortName = templateName,
ProjectName = "Foo.Bar",
TemplateVersion = version,
});
var zip = new ZipArchive(new MemoryStream(archive));
var dirName = Path.GetTempPath() + Path.DirectorySeparatorChar + Guid.NewGuid();
zip.ExtractToDirectory(dirName);
var startInfo = new ProcessStartInfo();
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.FileName = "dotnet";
startInfo.Arguments = "build";
startInfo.WorkingDirectory = dirName;
var process = Process.Start(startInfo);
while (!process.HasExited)
{
Thread.Sleep(100);
}
var output = process.StandardOutput.ReadToEnd();
Assert.Contains("Build succeeded.", output);
}
}
}
}

Просмотреть файл

@ -0,0 +1,164 @@
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Steeltoe.Initializr.Services;
using Steeltoe.Initializr.Services.DotNetTemplateEngine;
using Steeltoe.Initializr.Services.Mustache;
using Steeltoe.InitializrTests;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
namespace Steeltoe.Initializr.Tests
{
[Trait("Category", "Integration")]
public class IntegrationTests : XunitLoggingBase
{
private readonly ITestOutputHelper _testOutputHelper;
private readonly LoggerFactory _xUnitLoggerFactory;
private readonly LoggerFactory _loggerFactory;
public IntegrationTests(ITestOutputHelper testOutputHelper)
: base(testOutputHelper)
{
_testOutputHelper = testOutputHelper;
_xUnitLoggerFactory = new LoggerFactory();
_xUnitLoggerFactory.AddProvider(new XunitLoggerProvider(testOutputHelper));
_loggerFactory = new LoggerFactory();
}
public static IEnumerable<object[]> GetAllCombinations(Type templateServiceType, string templateName, TemplateVersion version, int take)
{
ITemplateService templateService;
if (templateServiceType == typeof(MustacheTemplateService))
{
templateService = new MustacheTemplateService(
TestHelper.GetConfiguration(),
new LoggerFactory().CreateLogger<MustacheTemplateService>());
}
else
{
templateService = new TemplateService(
TestHelper.GetConfiguration(),
new MemoryCache(new MemoryCacheOptions()),
new LoggerFactory().CreateLogger<TemplateService>());
}
var dependencies = templateService.GetDependencies(templateName, version);
return from deps in GetCombinations(dependencies.Select(d => d.ShortName), take)
select new object[] { templateService, templateName, version, string.Join(",", deps) };
}
[Theory]
[MemberData(nameof(GetAllCombinations), typeof(MustacheTemplateService), "Steeltoe-WebApi", TemplateVersion.V2, 1, DisableDiscoveryEnumeration = true)]
public async Task CreateTemplate_Mustache_WebApi_V2_OneAtaTime_Test(ITemplateService templateService, string templateName, TemplateVersion version, string depString)
{
_testOutputHelper.WriteLine(depString);
await CreateTemplate_Test(templateService, templateName, version, depString);
}
[Theory]
[MemberData(nameof(GetAllCombinations), typeof(MustacheTemplateService), "Steeltoe-WebApi", TemplateVersion.V2, int.MaxValue, DisableDiscoveryEnumeration = true)]
public async Task CreateTemplate_Mustache_WebApi_V2_All_Test(ITemplateService templateService, string templateName, TemplateVersion version, string depString)
{
_testOutputHelper.WriteLine(depString);
await CreateTemplate_Test(templateService, templateName, version, depString);
}
[Theory]
[MemberData(nameof(GetAllCombinations), typeof(TemplateService), "Steeltoe-WebApi", TemplateVersion.V2, 1, DisableDiscoveryEnumeration = true)]
public async Task CreateTemplate_Dotnet_WebApi_V2_OneAtaTime_Test(ITemplateService templateService, string templateName, TemplateVersion version, string depString)
{
_testOutputHelper.WriteLine(depString);
await CreateTemplate_Test(templateService, templateName, version, depString);
}
[Theory]
[MemberData(nameof(GetAllCombinations), typeof(TemplateService), "Steeltoe-WebApi", TemplateVersion.V2, int.MaxValue, DisableDiscoveryEnumeration = true)]
public async Task CreateTemplate_Dotnet_WebApi_V2_All_Test(ITemplateService templateService, string templateName, TemplateVersion version, string depString)
{
_testOutputHelper.WriteLine(depString);
await CreateTemplate_Test(templateService, templateName, version, depString);
}
private static IEnumerable<List<string>> GetCombinations(IEnumerable<string> deps, int take)
{
var returnValue = new List<List<string>>();
var depArray = deps as string[] ?? deps.ToArray();
var length = depArray.Length;
var combinations = Math.Pow(2, length);
for (var i = 0; i < combinations; i++)
{
var combinationDeps = new List<string>();
for (var bit = 0; bit <= length; bit++)
{
// right shift by _bit_ bits and check if set
if (((i >> bit) & 1) == 1)
{
combinationDeps.Add(depArray[bit]);
}
}
if (combinationDeps.Count == take || (take == int.MaxValue && combinationDeps.Count == depArray.Length))
{
returnValue.Add(combinationDeps);
}
}
return returnValue;
}
private async Task CreateTemplate_Test(ITemplateService templateService, string templateName, TemplateVersion version, string depString)
{
_testOutputHelper.WriteLine($"testing dep: --" + depString);
var archive = await templateService.GenerateProjectArchiveAsync(new Models.GeneratorModel()
{
Dependencies = depString,
TemplateShortName = templateName,
ProjectName = "Foo.Bar",
TemplateVersion = version,
});
var zip = new ZipArchive(new MemoryStream(archive));
var dirName = Path.GetTempPath() + Path.DirectorySeparatorChar + Guid.NewGuid();
zip.ExtractToDirectory(dirName);
var startInfo = new ProcessStartInfo();
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.FileName = "dotnet";
startInfo.Arguments = "build";
startInfo.WorkingDirectory = dirName;
var process = Process.Start(startInfo);
await process.WaitForExitAsync();
var output = process.StandardOutput.ReadToEnd();
Assert.True(
output.Contains("Build succeeded."),
$"Error compiling {depString}. \n {output}");
}
}
}

Просмотреть файл

@ -130,14 +130,14 @@ namespace Steeltoe.Initializr.Tests
var dv = new Dictionary<string, string>
{
{ "IsMoreThanOne", "false" },
{ "ConfigServer", "true" },
{ "SQLServer", "true" },
{ "CloudFoundry", "true" },
{ "CircuitBreaker", "true" },
{ "Redis", "false" },
};
var calcParam = new CalculatedParam
{
Name = "IsMoreThanOne",
Expression = "ConfigServer,SQLServer,Redis",
Expression = "ConfigServer,SQLServer,Redis,CircuitBreaker,CloudFoundry",
ExpressionType = ExpressionTypeEnum.MoreThanOne,
};

Просмотреть файл

@ -0,0 +1,55 @@
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
// ReSharper disable MethodSupportsCancellation
namespace Steeltoe.Initializr.Tests
{
public static class ProcessExtensions
{
public static async Task WaitForExitAsync(this Process process, CancellationToken cancellationToken = default)
{
var tcs = new TaskCompletionSource<bool>();
void ProcessExited(object sender, EventArgs e)
{
Task.Run(() => tcs.TrySetResult(true));
}
process.EnableRaisingEvents = true;
process.Exited += ProcessExited;
try
{
if (process.HasExited)
{
return;
}
using (cancellationToken.Register(() => Task.Run(() => tcs.TrySetCanceled())))
{
await tcs.Task;
}
}
finally
{
process.Exited -= ProcessExited;
}
}
}
}

Просмотреть файл

@ -147,7 +147,6 @@ namespace Steeltoe.Initializr.Tests
string appSettings = files.Find(x => x.Key == "appsettings.json").Value;
Assert.DoesNotContain("#if", appSettings);
}
[Theory]
@ -445,7 +444,7 @@ using System.Threading;", valuesController);
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "SQLServer,ConfigServer",
Dependencies = "SQLServer",
ProjectName = "testProject",
TemplateShortName = templateName,
SteeltoeVersion = steeltoeVersion,