Browse Source

added unit tests for GitRepositoryBuildStatus class

pull/5418/head
İsmail ÇAĞDAŞ 6 years ago
parent
commit
588040cfa5
  1. 67
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/DefaultBuildProjectListSorter.cs
  2. 9
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/DefaultChangedProjectFinder.cs
  3. 32
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/FileSystemRepositoryBuildStatusStore.cs
  4. 56
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/GitRepositoryBuildStatus.cs
  5. 11
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/IBuildProjectListSorter.cs
  6. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/IRepositoryBuildStatusStore.cs
  7. 64
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/BuildCommand.cs
  8. 86
      framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/Build/GitRepositoryBuildStatus_Tests.cs

67
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/DefaultBuildProjectListSorter.cs

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.Build
{
public class DefaultBuildProjectListSorter : IBuildProjectListSorter, ITransientDependency
{
public List<DotNetProjectInfo> SortByDependencies(
List<DotNetProjectInfo> source,
IEqualityComparer<DotNetProjectInfo> comparer = null)
{
/* See: http://www.codeproject.com/Articles/869059/Topological-sorting-in-Csharp
* http://en.wikipedia.org/wiki/Topological_sorting
*/
var sorted = new List<DotNetProjectInfo>();
var visited = new Dictionary<DotNetProjectInfo, bool>(comparer);
foreach (var item in source)
{
SortByDependenciesVisit(source, item, sorted, visited);
}
return sorted;
}
private void SortByDependenciesVisit(
List<DotNetProjectInfo> source,
DotNetProjectInfo item,
List<DotNetProjectInfo> sorted,
Dictionary<DotNetProjectInfo, bool> visited)
{
bool inProcess;
var alreadyVisited = visited.TryGetValue(item, out inProcess);
if (alreadyVisited)
{
if (inProcess)
{
throw new ArgumentException("Cyclic dependency found! Item: " + item);
}
}
else
{
visited[item] = true;
var dependencies = item.Dependencies;
if (dependencies != null)
{
foreach (var dependency in dependencies)
{
var dependencyItem = source.FirstOrDefault(e => e.CsProjPath == dependency.CsProjPath);
if (dependencyItem != null)
{
SortByDependenciesVisit(source, dependencyItem, sorted, visited);
}
}
}
visited[item] = false;
sorted.Add(item);
}
}
}
}

9
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/DefaultChangedProjectFinder.cs

@ -174,6 +174,15 @@ namespace Volo.Abp.Cli.Build
foreach (var file in allCsProjFiles) foreach (var file in allCsProjFiles)
{ {
if (status == null)
{
changedFiles.Add(
new DotNetProjectInfo(repository.Name, Path.Combine(repository.RootPath, file))
);
continue;
}
if (status.GetSelfOrChild(repository.Name).SucceedProjects.Any(e=> e.CsProjPath == file)) if (status.GetSelfOrChild(repository.Name).SucceedProjects.Any(e=> e.CsProjPath == file))
{ {
continue; continue;

32
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/FileSystemRepositoryBuildStatusStore.cs

@ -17,7 +17,8 @@ namespace Volo.Abp.Cli.Build
Directory.CreateDirectory(BaseBuildStatusStorePath); Directory.CreateDirectory(BaseBuildStatusStorePath);
} }
var buildStatusFile = Path.Combine(BaseBuildStatusStorePath, repository.GetUniqueName(buildNamePrefix)) + ".json"; var buildStatusFile = Path.Combine(BaseBuildStatusStorePath, repository.GetUniqueName(buildNamePrefix)) +
".json";
if (!File.Exists(buildStatusFile)) if (!File.Exists(buildStatusFile))
{ {
@ -29,12 +30,9 @@ namespace Volo.Abp.Cli.Build
return JsonConvert.DeserializeObject<GitRepositoryBuildStatus>(buildStatusText); return JsonConvert.DeserializeObject<GitRepositoryBuildStatus>(buildStatusText);
} }
public void Set(string buildNamePrefix, GitRepositoryBuildStatus status) public void Set(string buildNamePrefix, GitRepository repository, GitRepositoryBuildStatus status)
{ {
if (!Directory.Exists(BaseBuildStatusStorePath)) var existingRepositoryStatus = Get(buildNamePrefix, repository);
{
Directory.CreateDirectory(BaseBuildStatusStorePath);
}
var buildStatusFile = Path.Combine(BaseBuildStatusStorePath, status.GetUniqueName(buildNamePrefix)) + ".json"; var buildStatusFile = Path.Combine(BaseBuildStatusStorePath, status.GetUniqueName(buildNamePrefix)) + ".json";
if (File.Exists(buildStatusFile)) if (File.Exists(buildStatusFile))
@ -42,10 +40,28 @@ namespace Volo.Abp.Cli.Build
FileHelper.DeleteIfExists(buildStatusFile); FileHelper.DeleteIfExists(buildStatusFile);
} }
existingRepositoryStatus.MergeWith(status);
using (var file = File.CreateText(buildStatusFile)) using (var file = File.CreateText(buildStatusFile))
{ {
new JsonSerializer {Formatting = Formatting.Indented}.Serialize(file, status); new JsonSerializer {Formatting = Formatting.Indented}.Serialize(file, existingRepositoryStatus);
} }
} }
// private void UpdateBuildStatus(
// GitRepositoryBuildStatus existingBuildStatus,
// GitRepositoryBuildStatus newBuildStatus)
// {
//
// foreach (var succeedProject in newBuildStatus.SucceedProjects)
// {
// existingBuildStatus.UpdateProjectStatus(succeedProject);
//
// foreach (var dependingRepositoryBuildStatus in newBuildStatus.DependingRepositories)
// {
// UpdateBuildStatus(existingBuildStatus, dependingRepositoryBuildStatus);
// }
// }
// }
} }
} }

56
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/GitRepositoryBuildStatus.cs

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace Volo.Abp.Cli.Build namespace Volo.Abp.Cli.Build
{ {
@ -58,6 +59,48 @@ namespace Volo.Abp.Cli.Build
return null; return null;
} }
public string GetUniqueName(string uniqueName)
{
var name = RepositoryName + "_" + BranchName;
foreach (var dependingRepository in DependingRepositories)
{
AddToUniqueName(dependingRepository, name);
}
return (uniqueName.IsNullOrEmpty() ? "" : uniqueName + "_") + name.ToMd5();
}
public void AddOrUpdateProjectStatus(DotNetProjectBuildStatus status)
{
var existingProjectStatus = SucceedProjects.FirstOrDefault(p => p.CsProjPath == status.CsProjPath);
if (existingProjectStatus != null)
{
existingProjectStatus.CommitId = status.CommitId;
}
else
{
SucceedProjects.Add(status);
}
foreach (var dependingRepository in DependingRepositories)
{
dependingRepository.AddOrUpdateProjectStatus(status);
}
}
public void MergeWith(GitRepositoryBuildStatus newBuildStatus)
{
foreach (var succeedProject in newBuildStatus.SucceedProjects)
{
AddOrUpdateProjectStatus(succeedProject);
foreach (var dependingRepositoryBuildStatus in newBuildStatus.DependingRepositories)
{
MergeWith(dependingRepositoryBuildStatus);
}
}
}
private GitRepositoryBuildStatus GetChildInternal(GitRepositoryBuildStatus repositoryBuildStatus, private GitRepositoryBuildStatus GetChildInternal(GitRepositoryBuildStatus repositoryBuildStatus,
string repositoryName) string repositoryName)
{ {
@ -73,18 +116,7 @@ namespace Volo.Abp.Cli.Build
return null; return null;
} }
public string GetUniqueName(string uniqueName)
{
var name = RepositoryName + "_" + BranchName;
foreach (var dependingRepository in DependingRepositories)
{
AddToUniqueName(dependingRepository, name);
}
return (uniqueName.IsNullOrEmpty() ? "" : uniqueName + "_") + name.ToMd5();
}
private void AddToUniqueName(GitRepositoryBuildStatus gitRepository, string name) private void AddToUniqueName(GitRepositoryBuildStatus gitRepository, string name)
{ {
name += "_" + gitRepository.RepositoryName + "_" + gitRepository.BranchName; name += "_" + gitRepository.RepositoryName + "_" + gitRepository.BranchName;

11
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/IBuildProjectListSorter.cs

@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace Volo.Abp.Cli.Build
{
public interface IBuildProjectListSorter
{
List<DotNetProjectInfo> SortByDependencies(
List<DotNetProjectInfo> source,
IEqualityComparer<DotNetProjectInfo> comparer = null);
}
}

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/IRepositoryBuildStatusStore.cs

@ -4,6 +4,6 @@
{ {
GitRepositoryBuildStatus Get(string buildNamePrefix, GitRepository repository); GitRepositoryBuildStatus Get(string buildNamePrefix, GitRepository repository);
void Set(string buildNamePrefix, GitRepositoryBuildStatus status); void Set(string buildNamePrefix, GitRepository repository, GitRepositoryBuildStatus status);
} }
} }

64
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/BuildCommand.cs

@ -1,8 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -28,6 +26,8 @@ namespace Volo.Abp.Cli.Commands
public IBuildStatusGenerator BuildStatusGenerator { get; set; } public IBuildStatusGenerator BuildStatusGenerator { get; set; }
public IBuildProjectListSorter BuildProjectListSorter { get; set; }
public Task ExecuteAsync(CommandLineArgs commandLineArgs) public Task ExecuteAsync(CommandLineArgs commandLineArgs)
{ {
var sw = new Stopwatch(); var sw = new Stopwatch();
@ -63,7 +63,7 @@ namespace Volo.Abp.Cli.Commands
DotNetProjectDependencyFiller.Fill(changedProjectFiles); DotNetProjectDependencyFiller.Fill(changedProjectFiles);
var sortedProjects = SortByDependencies( var sortedProjects = BuildProjectListSorter.SortByDependencies(
changedProjectFiles, changedProjectFiles,
new DotNetProjectInfoEqualityComparer() new DotNetProjectInfoEqualityComparer()
); );
@ -80,68 +80,14 @@ namespace Volo.Abp.Cli.Commands
buildSucceededProjects buildSucceededProjects
); );
RepositoryBuildStatusStore.Set(buildName, buildStatus); RepositoryBuildStatusStore.Set(buildName, buildConfig.GitRepository, buildStatus);
sw.Stop(); sw.Stop();
Console.WriteLine("Build operation is completed in " + sw.ElapsedMilliseconds + " (ms)"); Console.WriteLine("Build operation is completed in " + sw.ElapsedMilliseconds + " (ms)");
return Task.CompletedTask; return Task.CompletedTask;
} }
private List<DotNetProjectInfo> SortByDependencies(
List<DotNetProjectInfo> source,
IEqualityComparer<DotNetProjectInfo> comparer = null)
{
/* See: http://www.codeproject.com/Articles/869059/Topological-sorting-in-Csharp
* http://en.wikipedia.org/wiki/Topological_sorting
*/
var sorted = new List<DotNetProjectInfo>();
var visited = new Dictionary<DotNetProjectInfo, bool>(comparer);
foreach (var item in source)
{
SortByDependenciesVisit(source, item, sorted, visited);
}
return sorted;
}
private void SortByDependenciesVisit(
List<DotNetProjectInfo> source,
DotNetProjectInfo item,
List<DotNetProjectInfo> sorted,
Dictionary<DotNetProjectInfo, bool> visited)
{
bool inProcess;
var alreadyVisited = visited.TryGetValue(item, out inProcess);
if (alreadyVisited)
{
if (inProcess)
{
throw new ArgumentException("Cyclic dependency found! Item: " + item);
}
}
else
{
visited[item] = true;
var dependencies = item.Dependencies;
if (dependencies != null)
{
foreach (var dependency in dependencies)
{
var dependencyItem = source.FirstOrDefault(e => e.CsProjPath == dependency.CsProjPath);
SortByDependenciesVisit(source, dependencyItem, sorted, visited);
}
}
visited[item] = false;
sorted.Add(item);
}
}
public string GetUsageInfo() public string GetUsageInfo()
{ {
var sb = new StringBuilder(); var sb = new StringBuilder();

86
framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/Build/GitRepositoryBuildStatus_Tests.cs

@ -0,0 +1,86 @@
using System.Collections.Generic;
using System.Linq;
using Shouldly;
using Xunit;
namespace Volo.Abp.Cli.Build
{
public class GitRepositoryBuildStatus_Tests : AbpCliTestBase
{
[Fact]
public void Add_New_Build_Status_Test()
{
var existingBuildStatus = new GitRepositoryBuildStatus("volo", "dev")
{
SucceedProjects = new List<DotNetProjectBuildStatus>
{
new DotNetProjectBuildStatus
{
CsProjPath = "project1.csproj",
CommitId = "1"
}
}
};
var newBuildStatus = new GitRepositoryBuildStatus(
existingBuildStatus.RepositoryName,
existingBuildStatus.BranchName
)
{
SucceedProjects = new List<DotNetProjectBuildStatus>
{
new DotNetProjectBuildStatus
{
CsProjPath = "project2.csproj",
CommitId = "2"
}
}
};
existingBuildStatus.MergeWith(newBuildStatus);
existingBuildStatus.SucceedProjects.Count.ShouldBe(2);
}
[Fact]
public void Update_Existing_Build_Status_Test()
{
var existingBuildStatus = new GitRepositoryBuildStatus("volo", "dev")
{
SucceedProjects = new List<DotNetProjectBuildStatus>
{
new DotNetProjectBuildStatus
{
CsProjPath = "project1.csproj",
CommitId = "1"
}
}
};
var newBuildStatus = new GitRepositoryBuildStatus(
existingBuildStatus.RepositoryName,
existingBuildStatus.BranchName
)
{
SucceedProjects = new List<DotNetProjectBuildStatus>
{
new DotNetProjectBuildStatus
{
CsProjPath = "project1.csproj",
CommitId = "2"
},
new DotNetProjectBuildStatus
{
CsProjPath = "project2.csproj",
CommitId = "2"
}
}
};
existingBuildStatus.MergeWith(newBuildStatus);
existingBuildStatus.SucceedProjects.Count.ShouldBe(2);
existingBuildStatus.GetSelfOrChild("volo").SucceedProjects.First(p => p.CsProjPath == "project1.csproj").CommitId.ShouldBe("2");
existingBuildStatus.GetSelfOrChild("volo").SucceedProjects.First(p => p.CsProjPath == "project2.csproj").CommitId.ShouldBe("2");
}
}
}
Loading…
Cancel
Save