Update PathMatch and add tests

This commit is contained in:
Matt Nadareski
2024-11-24 23:50:02 -05:00
parent 2d4f974623
commit f10585aa32
2 changed files with 305 additions and 15 deletions

View File

@@ -0,0 +1,285 @@
using System;
using System.Collections.Generic;
using System.IO;
using SabreTools.Matching.Paths;
using Xunit;
namespace SabreTools.Matching.Test.Paths
{
public class PathMatchTests
{
[Fact]
public void InvalidNeedleThrowsException()
{
Assert.Throws<InvalidDataException>(() => new PathMatch(string.Empty));
}
#region Array
[Fact]
public void NullArrayReturnsNoMatch()
{
var pm = new PathMatch("test");
string? actual = pm.Match((string[]?)null);
Assert.Null(actual);
}
[Fact]
public void EmptyArrayReturnsNoMatch()
{
var pm = new PathMatch("test");
string? actual = pm.Match(Array.Empty<string>());
Assert.Null(actual);
}
[Fact]
public void SingleItemArrayMatchingReturnsMatch()
{
string needle = "test";
string[] stack = [needle];
var pm = new PathMatch(needle);
string? actual = pm.Match(stack);
Assert.Equal(needle, actual);
}
[Fact]
public void SingleItemArrayMismatchedReturnsNoMatch()
{
string needle = "test";
string[] stack = ["not"];
var pm = new PathMatch(needle);
string? actual = pm.Match(stack);
Assert.Null(actual);
}
[Fact]
public void MultiItemArrayMatchingReturnsMatch()
{
string needle = "test";
string[] stack = ["not", needle, "far"];
var pm = new PathMatch(needle);
string? actual = pm.Match(stack);
Assert.Equal(needle, actual);
}
[Fact]
public void MultiItemArrayMismatchedReturnsNoMatch()
{
string needle = "test";
string[] stack = ["not", "too", "far"];
var pm = new PathMatch(needle);
string? actual = pm.Match(stack);
Assert.Null(actual);
}
#endregion
#region List
[Fact]
public void NullListReturnsNoMatch()
{
var pm = new PathMatch("test");
string? actual = pm.Match((List<string>?)null);
Assert.Null(actual);
}
[Fact]
public void EmptyListReturnsNoMatch()
{
var pm = new PathMatch("test");
string? actual = pm.Match(new List<string>());
Assert.Null(actual);
}
[Fact]
public void SingleItemListMatchingReturnsMatch()
{
string needle = "test";
List<string> stack = [needle];
var pm = new PathMatch(needle);
string? actual = pm.Match(stack);
Assert.Equal(needle, actual);
}
[Fact]
public void SingleItemListMismatchedReturnsNoMatch()
{
string needle = "test";
List<string> stack = ["not"];
var pm = new PathMatch(needle);
string? actual = pm.Match(stack);
Assert.Null(actual);
}
[Fact]
public void MultiItemListMatchingReturnsMatch()
{
string needle = "test";
List<string> stack = ["not", needle, "far"];
var pm = new PathMatch(needle);
string? actual = pm.Match(stack);
Assert.Equal(needle, actual);
}
[Fact]
public void MultiItemListMismatchedReturnsNoMatch()
{
string needle = "test";
List<string> stack = ["not", "too", "far"];
var pm = new PathMatch(needle);
string? actual = pm.Match(stack);
Assert.Null(actual);
}
#endregion
#region Match Case
[Fact]
public void MatchCaseEqualReturnsMatch()
{
string needle = "test";
List<string> stack = [needle];
var pm = new PathMatch(needle, matchCase: true);
string? actual = pm.Match(stack);
Assert.Equal(needle, actual);
}
[Fact]
public void NoMatchCaseEqualReturnsMatch()
{
string needle = "test";
List<string> stack = [needle];
var pm = new PathMatch(needle, matchCase: false);
string? actual = pm.Match(stack);
Assert.Equal(needle, actual);
}
[Fact]
public void MatchCaseInequalReturnsNoMatch()
{
string needle = "test";
List<string> stack = [needle.ToUpperInvariant()];
var pm = new PathMatch(needle, matchCase: true);
string? actual = pm.Match(stack);
Assert.Null(actual);
}
[Fact]
public void NoMatchCaseInequalReturnsMatch()
{
string needle = "test";
List<string> stack = [needle.ToUpperInvariant()];
var pm = new PathMatch(needle, matchCase: false);
string? actual = pm.Match(stack);
Assert.Equal(needle.ToUpperInvariant(), actual);
}
[Fact]
public void MatchCaseContainsReturnsMatch()
{
string needle = "test";
List<string> stack = [$"prefix_{needle}_postfix"];
var pm = new PathMatch(needle, matchCase: true);
string? actual = pm.Match(stack);
Assert.Equal($"prefix_{needle}_postfix", actual);
}
[Fact]
public void NoMatchCaseContainsReturnsMatch()
{
string needle = "test";
List<string> stack = [$"prefix_{needle}_postfix"];
var pm = new PathMatch(needle, matchCase: false);
string? actual = pm.Match(stack);
Assert.Equal($"prefix_{needle}_postfix", actual);
}
#endregion
#region Use Ends With
[Fact]
public void EndsWithEqualReturnsMatch()
{
string needle = "test";
List<string> stack = [needle];
var pm = new PathMatch(needle, useEndsWith: true);
string? actual = pm.Match(stack);
Assert.Equal(needle, actual);
}
[Fact]
public void NoEndsWithEqualReturnsMatch()
{
string needle = "test";
List<string> stack = [needle];
var pm = new PathMatch(needle, useEndsWith: false);
string? actual = pm.Match(stack);
Assert.Equal(needle, actual);
}
[Fact]
public void EndsWithInequalReturnsMatch()
{
string needle = "test";
List<string> stack = [needle.ToUpperInvariant()];
var pm = new PathMatch(needle, useEndsWith: true);
string? actual = pm.Match(stack);
Assert.Equal(needle.ToUpperInvariant(), actual);
}
[Fact]
public void NoEndsWithInequalReturnsMatch()
{
string needle = "test";
List<string> stack = [needle.ToUpperInvariant()];
var pm = new PathMatch(needle, useEndsWith: false);
string? actual = pm.Match(stack);
Assert.Equal(needle.ToUpperInvariant(), actual);
}
[Fact]
public void EndsWithContainsReturnsNoMatch()
{
string needle = "test";
List<string> stack = [$"prefix_{needle}_postfix"];
var pm = new PathMatch(needle, useEndsWith: true);
string? actual = pm.Match(stack);
Assert.Null(actual);
}
[Fact]
public void NoEndsWithContainsReturnsMatch()
{
string needle = "test";
List<string> stack = [$"prefix_{needle}_postfix"];
var pm = new PathMatch(needle, useEndsWith: false);
string? actual = pm.Match(stack);
Assert.Equal($"prefix_{needle}_postfix", actual);
}
#endregion
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.IO;
namespace SabreTools.Matching.Paths
{
@@ -10,29 +11,33 @@ namespace SabreTools.Matching.Paths
/// <summary>
/// String to match
/// </summary>
public string? Needle { get; }
public string Needle { get; }
/// <summary>
/// Match exact casing instead of invariant
/// Match casing instead of invariant
/// </summary>
public bool MatchExact { get; }
private readonly bool _matchCase;
/// <summary>
/// Match that values end with the needle and not just contains
/// </summary>
public bool UseEndsWith { get; }
private readonly bool _useEndsWith;
/// <summary>
/// Constructor
/// </summary>
/// <param name="needle">String representing the search</param>
/// <param name="matchExact">True to match exact casing, false otherwise</param>
/// <param name="useEndsWith">True to match the end only, false for all contents</param>
public PathMatch(string? needle, bool matchExact = false, bool useEndsWith = false)
/// <param name="matchCase">True to match exact casing, false otherwise</param>
/// <param name="useEndsWith">True to match the end only, false for contains</param>
public PathMatch(string needle, bool matchCase = false, bool useEndsWith = false)
{
// Validate the inputs
if (needle.Length == 0)
throw new InvalidDataException(nameof(needle));
Needle = needle;
MatchExact = matchExact;
UseEndsWith = useEndsWith;
_matchCase = matchCase;
_useEndsWith = useEndsWith;
}
#region Matching
@@ -40,7 +45,7 @@ namespace SabreTools.Matching.Paths
/// <summary>
/// Get if this match can be found in a stack
/// </summary>
/// <param name="stack">List of strings to search for the given content</param>
/// <param name="stack">Array of strings to search for the given content</param>
/// <returns>Matched item on success, null on error</returns>
public string? Match(string[]? stack)
=> Match(stack == null ? null : new List<string>(stack));
@@ -53,20 +58,20 @@ namespace SabreTools.Matching.Paths
public string? Match(List<string>? stack)
{
// If either array is null or empty, we can't do anything
if (stack == null || Needle == null || Needle.Length == 0)
if (stack == null || stack.Count == 0 || Needle.Length == 0)
return null;
// Preprocess the needle, if necessary
string procNeedle = MatchExact ? Needle : Needle.ToLowerInvariant();
string procNeedle = _matchCase ? Needle : Needle.ToLowerInvariant();
foreach (string stackItem in stack)
{
// Preprocess the stack item, if necessary
string procStackItem = MatchExact ? stackItem : stackItem.ToLowerInvariant();
string procStackItem = _matchCase ? stackItem : stackItem.ToLowerInvariant();
if (UseEndsWith && procStackItem.EndsWith(procNeedle))
if (_useEndsWith && procStackItem.EndsWith(procNeedle))
return stackItem;
else if (!UseEndsWith && procStackItem.Contains(procNeedle))
else if (!_useEndsWith && procStackItem.Contains(procNeedle))
return stackItem;
}