From 588040cfa504426fc4fc82bb874960039008773e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0smail=20=C3=87A=C4=9EDA=C5=9E?= Date: Mon, 7 Sep 2020 12:47:09 +0300 Subject: [PATCH] added unit tests for GitRepositoryBuildStatus class --- .../Build/DefaultBuildProjectListSorter.cs | 67 +++++++++++++++ .../Cli/Build/DefaultChangedProjectFinder.cs | 9 ++ .../FileSystemRepositoryBuildStatusStore.cs | 32 +++++-- .../Abp/Cli/Build/GitRepositoryBuildStatus.cs | 56 +++++++++--- .../Abp/Cli/Build/IBuildProjectListSorter.cs | 11 +++ .../Cli/Build/IRepositoryBuildStatusStore.cs | 2 +- .../Volo/Abp/Cli/Commands/BuildCommand.cs | 64 ++------------ .../Build/GitRepositoryBuildStatus_Tests.cs | 86 +++++++++++++++++++ 8 files changed, 247 insertions(+), 80 deletions(-) create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/DefaultBuildProjectListSorter.cs create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/IBuildProjectListSorter.cs create mode 100644 framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/Build/GitRepositoryBuildStatus_Tests.cs diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/DefaultBuildProjectListSorter.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/DefaultBuildProjectListSorter.cs new file mode 100644 index 0000000000..6df892b472 --- /dev/null +++ b/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 SortByDependencies( + List source, + IEqualityComparer comparer = null) + { + /* See: http://www.codeproject.com/Articles/869059/Topological-sorting-in-Csharp + * http://en.wikipedia.org/wiki/Topological_sorting + */ + + var sorted = new List(); + var visited = new Dictionary(comparer); + + foreach (var item in source) + { + SortByDependenciesVisit(source, item, sorted, visited); + } + + return sorted; + } + + private void SortByDependenciesVisit( + List source, + DotNetProjectInfo item, + List sorted, + Dictionary 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); + } + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/DefaultChangedProjectFinder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/DefaultChangedProjectFinder.cs index 996d49a285..759f0734ff 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/DefaultChangedProjectFinder.cs +++ b/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) { + 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)) { continue; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/FileSystemRepositoryBuildStatusStore.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/FileSystemRepositoryBuildStatusStore.cs index 339ea13374..aa1207388d 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/FileSystemRepositoryBuildStatusStore.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/FileSystemRepositoryBuildStatusStore.cs @@ -17,7 +17,8 @@ namespace Volo.Abp.Cli.Build 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)) { @@ -29,12 +30,9 @@ namespace Volo.Abp.Cli.Build return JsonConvert.DeserializeObject(buildStatusText); } - public void Set(string buildNamePrefix, GitRepositoryBuildStatus status) + public void Set(string buildNamePrefix, GitRepository repository, GitRepositoryBuildStatus status) { - if (!Directory.Exists(BaseBuildStatusStorePath)) - { - Directory.CreateDirectory(BaseBuildStatusStorePath); - } + var existingRepositoryStatus = Get(buildNamePrefix, repository); var buildStatusFile = Path.Combine(BaseBuildStatusStorePath, status.GetUniqueName(buildNamePrefix)) + ".json"; if (File.Exists(buildStatusFile)) @@ -42,10 +40,28 @@ namespace Volo.Abp.Cli.Build FileHelper.DeleteIfExists(buildStatusFile); } + existingRepositoryStatus.MergeWith(status); + 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); + // } + // } + // } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/GitRepositoryBuildStatus.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/GitRepositoryBuildStatus.cs index 96e88f935b..04c4eb188f 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/GitRepositoryBuildStatus.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/GitRepositoryBuildStatus.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; namespace Volo.Abp.Cli.Build { @@ -58,6 +59,48 @@ namespace Volo.Abp.Cli.Build 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, string repositoryName) { @@ -73,18 +116,7 @@ namespace Volo.Abp.Cli.Build 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) { name += "_" + gitRepository.RepositoryName + "_" + gitRepository.BranchName; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/IBuildProjectListSorter.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/IBuildProjectListSorter.cs new file mode 100644 index 0000000000..ed97ca27c8 --- /dev/null +++ b/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 SortByDependencies( + List source, + IEqualityComparer comparer = null); + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/IRepositoryBuildStatusStore.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/IRepositoryBuildStatusStore.cs index c71f007f9d..99be400ec8 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/IRepositoryBuildStatusStore.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/IRepositoryBuildStatusStore.cs @@ -4,6 +4,6 @@ { GitRepositoryBuildStatus Get(string buildNamePrefix, GitRepository repository); - void Set(string buildNamePrefix, GitRepositoryBuildStatus status); + void Set(string buildNamePrefix, GitRepository repository, GitRepositoryBuildStatus status); } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/BuildCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/BuildCommand.cs index 4792129742..1e1a24d77c 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/BuildCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/BuildCommand.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -28,6 +26,8 @@ namespace Volo.Abp.Cli.Commands public IBuildStatusGenerator BuildStatusGenerator { get; set; } + public IBuildProjectListSorter BuildProjectListSorter { get; set; } + public Task ExecuteAsync(CommandLineArgs commandLineArgs) { var sw = new Stopwatch(); @@ -63,7 +63,7 @@ namespace Volo.Abp.Cli.Commands DotNetProjectDependencyFiller.Fill(changedProjectFiles); - var sortedProjects = SortByDependencies( + var sortedProjects = BuildProjectListSorter.SortByDependencies( changedProjectFiles, new DotNetProjectInfoEqualityComparer() ); @@ -80,68 +80,14 @@ namespace Volo.Abp.Cli.Commands buildSucceededProjects ); - RepositoryBuildStatusStore.Set(buildName, buildStatus); + RepositoryBuildStatusStore.Set(buildName, buildConfig.GitRepository, buildStatus); sw.Stop(); Console.WriteLine("Build operation is completed in " + sw.ElapsedMilliseconds + " (ms)"); return Task.CompletedTask; } - - private List SortByDependencies( - List source, - IEqualityComparer comparer = null) - { - /* See: http://www.codeproject.com/Articles/869059/Topological-sorting-in-Csharp - * http://en.wikipedia.org/wiki/Topological_sorting - */ - - var sorted = new List(); - var visited = new Dictionary(comparer); - - foreach (var item in source) - { - SortByDependenciesVisit(source, item, sorted, visited); - } - - return sorted; - } - - private void SortByDependenciesVisit( - List source, - DotNetProjectInfo item, - List sorted, - Dictionary 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() { var sb = new StringBuilder(); diff --git a/framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/Build/GitRepositoryBuildStatus_Tests.cs b/framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/Build/GitRepositoryBuildStatus_Tests.cs new file mode 100644 index 0000000000..6e1cf2fddf --- /dev/null +++ b/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 + { + new DotNetProjectBuildStatus + { + CsProjPath = "project1.csproj", + CommitId = "1" + } + } + }; + + var newBuildStatus = new GitRepositoryBuildStatus( + existingBuildStatus.RepositoryName, + existingBuildStatus.BranchName + ) + { + SucceedProjects = new List + { + 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 + { + new DotNetProjectBuildStatus + { + CsProjPath = "project1.csproj", + CommitId = "1" + } + } + }; + + var newBuildStatus = new GitRepositoryBuildStatus( + existingBuildStatus.RepositoryName, + existingBuildStatus.BranchName + ) + { + SucceedProjects = new List + { + 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"); + } + } +}