tests(git-provider): Add basic registration tests
- make ModuleCore internals visible to ModuleTests
This commit is contained in:
parent
b9f856e716
commit
09236e826a
7 changed files with 135 additions and 38 deletions
|
|
@ -6,12 +6,18 @@ public class GitManager
|
||||||
private static readonly Lazy<GitManager> GitManagerInstance = new(() => new GitManager());
|
private static readonly Lazy<GitManager> GitManagerInstance = new(() => new GitManager());
|
||||||
public static GitManager Instance => GitManagerInstance.Value;
|
public static GitManager Instance => GitManagerInstance.Value;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Always returns a new clean instance of GitManager
|
||||||
|
/// </summary>
|
||||||
|
internal static GitManager InternalFreshInstance => new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Simply <see cref="Path.DirectorySeparatorChar"/>.ToString()
|
/// Simply <see cref="Path.DirectorySeparatorChar"/>.ToString()
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static readonly string DirectorySeparator = Path.DirectorySeparatorChar.ToString();
|
private static readonly string DirectorySeparator = Path.DirectorySeparatorChar.ToString();
|
||||||
|
|
||||||
private readonly InternalDirectory _repositories;
|
private readonly InternalDirectory _repositories;
|
||||||
|
private readonly Lock _readWriteLock = new();
|
||||||
|
|
||||||
private GitManager()
|
private GitManager()
|
||||||
{
|
{
|
||||||
|
|
@ -20,6 +26,7 @@ public class GitManager
|
||||||
_repositories = new InternalDirectory()
|
_repositories = new InternalDirectory()
|
||||||
{
|
{
|
||||||
Name = DirectorySeparator,
|
Name = DirectorySeparator,
|
||||||
|
InternalPath = DirectorySeparator
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -29,18 +36,35 @@ public class GitManager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="absoluteRepositoryLocation"></param>
|
/// <param name="absoluteRepositoryLocation"></param>
|
||||||
/// <param name="registrationName"></param>
|
/// <param name="registrationName"></param>
|
||||||
/// <returns></returns>
|
/// <returns>The normalised string the repository was registered against</returns>
|
||||||
public void RegisterRepo(string absoluteRepositoryLocation, string registrationName)
|
public string RegisterRepo(string absoluteRepositoryLocation, string registrationName)
|
||||||
{
|
{
|
||||||
// Regardless of if we get a name or not, the fully qualified version for us
|
// Depending on the caller, it might be possible that they've scripted automatic repo registration. Because I
|
||||||
// starts with a
|
// don't really want to account to all the subtle ways that can be parallised, I just naively lock on every
|
||||||
var directorySegmentsFromName = NameToSegments(
|
// registration attempt. This method should be quick regardless, and I could use ConcurrentDictionary except
|
||||||
string.IsNullOrWhiteSpace(registrationName)
|
// that means every instance of InternalDirectory would need it and yeah nah fuck that I can just lock at the
|
||||||
|
// top level
|
||||||
|
lock (_readWriteLock)
|
||||||
|
{
|
||||||
|
var normalisedName = NormaliseNamePath(string.IsNullOrWhiteSpace(registrationName)
|
||||||
? new DirectoryInfo(absoluteRepositoryLocation).Name
|
? new DirectoryInfo(absoluteRepositoryLocation).Name
|
||||||
: registrationName
|
: registrationName);
|
||||||
);
|
|
||||||
|
|
||||||
_repositories.Add(absoluteRepositoryLocation, directorySegmentsFromName);
|
// Regardless of if we get a name or not, the fully qualified version for us
|
||||||
|
// starts with a /
|
||||||
|
var directorySegmentsFromName = NameToSegments(normalisedName);
|
||||||
|
|
||||||
|
var added = _repositories.Add(absoluteRepositoryLocation, directorySegmentsFromName);
|
||||||
|
|
||||||
|
// Not sure about this, the Add should throw any exceptions on duplicate/failures but for now I'll leave this
|
||||||
|
// here
|
||||||
|
if (added == null)
|
||||||
|
{
|
||||||
|
throw new Exception("Failed to register location");
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalisedName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -50,7 +74,7 @@ public class GitManager
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private Queue<string> NameToSegments(string name)
|
private Queue<string> NameToSegments(string name)
|
||||||
{
|
{
|
||||||
var segments = NormaliseNamePath(name).Split(DirectorySeparator);
|
var segments = name.Split(DirectorySeparator);
|
||||||
|
|
||||||
return segments.Length == 1
|
return segments.Length == 1
|
||||||
? new Queue<string>([DirectorySeparator, name])
|
? new Queue<string>([DirectorySeparator, name])
|
||||||
|
|
@ -84,48 +108,55 @@ public class GitManager
|
||||||
|
|
||||||
public Dictionary<string, InternalDirectory> Children { get; set; } = [];
|
public Dictionary<string, InternalDirectory> Children { get; set; } = [];
|
||||||
|
|
||||||
|
internal string InternalPath { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If not null, this is the absolute location of a registered git repository
|
/// If not null, this is the absolute location of a registered git repository
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? FullRepositoryPath { get; set; }
|
public string? FullRepositoryPath { get; set; }
|
||||||
|
|
||||||
internal void Add(string absoluteRepositoryLocation, Queue<string> directorySegmentsFromName)
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="absoluteRepositoryLocation"></param>
|
||||||
|
/// <param name="directorySegmentsFromName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
internal InternalDirectory? Add(string absoluteRepositoryLocation, Queue<string> directorySegmentsFromName)
|
||||||
{
|
{
|
||||||
var topStack = directorySegmentsFromName.Dequeue();
|
var topStack = directorySegmentsFromName.Dequeue();
|
||||||
|
|
||||||
if (topStack == Name)
|
if (topStack != Name)
|
||||||
{
|
|
||||||
// We're at the end of the directory segments so we can safely say we're at the end of the tree so
|
|
||||||
// we add it to the relevant dictionary
|
|
||||||
if (directorySegmentsFromName.Count == 0)
|
|
||||||
{
|
|
||||||
FullRepositoryPath = absoluteRepositoryLocation;
|
|
||||||
//Children.Add(topStack, directory);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var nextSegment = directorySegmentsFromName.Peek();
|
|
||||||
// Attempt to get the next level of the directory. If we don't have a key entry, create one
|
|
||||||
if (!Children.TryGetValue(nextSegment, out var nextChild))
|
|
||||||
{
|
|
||||||
nextChild = new InternalDirectory()
|
|
||||||
{
|
|
||||||
Name = nextSegment,
|
|
||||||
};
|
|
||||||
Children.Add(nextSegment, nextChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the next
|
|
||||||
nextChild.Add(absoluteRepositoryLocation, directorySegmentsFromName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// logically it shouldn't be possible to have a value on top of the stack that _doesn't_ exist, but
|
// logically it shouldn't be possible to have a value on top of the stack that _doesn't_ exist, but
|
||||||
// just incase we throw as this should only happen if an Add is attempted on the root and the queue was
|
// just incase we throw as this should only happen if an Add is attempted on the root and the queue was
|
||||||
// not correctly rooted to /
|
// not correctly rooted to /
|
||||||
throw new Exception($"Directory segment does not seem to exist: {topStack}");
|
throw new Exception($"Directory segment does not seem to exist: {topStack}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We're at the end of the directory segments so we can safely say we're at the end of the tree so
|
||||||
|
// we add it to the relevant dictionary
|
||||||
|
if (directorySegmentsFromName.Count == 0)
|
||||||
|
{
|
||||||
|
FullRepositoryPath = absoluteRepositoryLocation;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nextSegment = directorySegmentsFromName.Peek();
|
||||||
|
|
||||||
|
// Attempt to get the next level of the directory. If we don't have a key entry, create one
|
||||||
|
if (!Children.TryGetValue(nextSegment, out var nextChild))
|
||||||
|
{
|
||||||
|
nextChild = new InternalDirectory()
|
||||||
|
{
|
||||||
|
Name = nextSegment,
|
||||||
|
InternalPath = Path.Combine(InternalPath, nextSegment)
|
||||||
|
};
|
||||||
|
Children.Add(nextSegment, nextChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the next
|
||||||
|
return nextChild.Add(absoluteRepositoryLocation, directorySegmentsFromName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,4 +7,10 @@
|
||||||
<LangVersion>latestmajor</LangVersion>
|
<LangVersion>latestmajor</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
|
||||||
|
<_Parameter1>ModuleTests</_Parameter1>
|
||||||
|
</AssemblyAttribute>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
36
tests/ModuleTests/Git/AddRegistrationTests.cs
Normal file
36
tests/ModuleTests/Git/AddRegistrationTests.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Text;
|
||||||
|
using ModuleCore.Calendar;
|
||||||
|
using ModuleCore.Git;
|
||||||
|
using ModuleTests.Git.TestData;
|
||||||
|
|
||||||
|
namespace ModuleTests.Git;
|
||||||
|
|
||||||
|
public class AddRegistrationTests
|
||||||
|
{
|
||||||
|
private static readonly VerifySettings Settings;
|
||||||
|
|
||||||
|
static AddRegistrationTests()
|
||||||
|
{
|
||||||
|
Settings = new VerifySettings();
|
||||||
|
var testBaseDirectory = Path.Join(TestConstants.SnapshotFolderName, nameof(AddRegistrationTests));
|
||||||
|
|
||||||
|
Settings.UseDirectory(testBaseDirectory);
|
||||||
|
Settings.DisableDiff();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[ClassData(typeof(AddRegistrationTestData))]
|
||||||
|
public Task BasicRepoRegistration((int testId, string path) testData)
|
||||||
|
{
|
||||||
|
Settings.UseFileName($"{nameof(BasicRepoRegistration)}_{testData.testId}");
|
||||||
|
|
||||||
|
var gitManager = GitManager.InternalFreshInstance;
|
||||||
|
|
||||||
|
var repoRegistration = gitManager.RegisterRepo("Test:/some/test/repo", testData.path);
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine($"Attempted to register: {testData.path}")
|
||||||
|
.AppendLine($"Registration result: {repoRegistration}");
|
||||||
|
|
||||||
|
return Verify(sb, Settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
Attempted to register: test
|
||||||
|
Registration result: test
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
Attempted to register: test\path
|
||||||
|
Registration result: test\path
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
Attempted to register: other/path
|
||||||
|
Registration result: other\path
|
||||||
18
tests/ModuleTests/Git/TestData/AddRegistrationTestData.cs
Normal file
18
tests/ModuleTests/Git/TestData/AddRegistrationTestData.cs
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace ModuleTests.Git.TestData;
|
||||||
|
|
||||||
|
public class AddRegistrationTestData : TestDataEnumerator<(int testId, string path)>
|
||||||
|
{
|
||||||
|
public AddRegistrationTestData()
|
||||||
|
{
|
||||||
|
Data = new List<string>()
|
||||||
|
{
|
||||||
|
"test",
|
||||||
|
$"test{Path.DirectorySeparatorChar}path",
|
||||||
|
$"other{Path.AltDirectorySeparatorChar}path"
|
||||||
|
}
|
||||||
|
.Select((x, i) => (i, x))
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue