mirror of
https://github.com/ppy/osu.git
synced 2026-05-28 08:30:00 +08:00
Add tests coverage for filters with not equal
This commit is contained in:
committed by
Dean Herbert
Unverified
parent
02f835dbc3
commit
997b8a0bba
@@ -521,6 +521,199 @@ namespace osu.Game.Tests.NonVisual.Filtering
|
||||
Assert.That(visibleBeatmaps, Is.EqualTo(expectedBeatmapIndexes));
|
||||
}
|
||||
|
||||
[TestCase("title!=Title", new[] { 2, 4, 6 })]
|
||||
[TestCase("title!=\"Title1\"", new[] { 2, 3, 4, 5, 6 })]
|
||||
[TestCase("title!=\"Title1\"!", new[] { 2, 3, 4, 5, 6 })]
|
||||
[TestCase("artist!=artist", new int[] { })]
|
||||
[TestCase("artist!=\"artist2\"", new[] { 1, 2, 4, 6 })]
|
||||
[TestCase("artist!=\"artist2\"!", new[] { 1, 2, 4, 6 })]
|
||||
[TestCase("diff!=Diff", new[] { 2, 5 })]
|
||||
[TestCase("diff!=\"Diff1\"", new[] { 1, 2, 3, 4, 5, 6 })]
|
||||
[TestCase("diff!=\"Diff1\"!", new[] { 1, 2, 3, 4, 5, 6 })]
|
||||
public void TestNotEqualSearchForTextFilters(string query, int[] expectedBeatmapIndexes)
|
||||
{
|
||||
var carouselBeatmaps = (((string title, string difficultyName, string artist)[])new[]
|
||||
{
|
||||
("Title1", "Diff1", "artist2"),
|
||||
("Title1", "Diff2", "artist1"),
|
||||
("My[Favourite]Song", "Expert", "artist1"),
|
||||
("Title", "My Favourite Diff", "artist2"),
|
||||
("Another One", "diff ]with [[ brackets]]]", "artist3"),
|
||||
("Diff in title", "a", "artist2"),
|
||||
("a", "Diff in diff", "artist3")
|
||||
}).Select(info => new CarouselBeatmap(new BeatmapInfo
|
||||
{
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = info.title,
|
||||
Artist = info.artist
|
||||
},
|
||||
DifficultyName = info.difficultyName
|
||||
|
||||
})).ToList();
|
||||
|
||||
var criteria = new FilterCriteria();
|
||||
|
||||
FilterQueryParser.ApplyQueries(criteria, query);
|
||||
carouselBeatmaps.ForEach(b => b.Filter(criteria));
|
||||
|
||||
int[] visibleBeatmaps = carouselBeatmaps
|
||||
.Where(b => !b.Filtered.Value)
|
||||
.Select(b => carouselBeatmaps.IndexOf(b)).ToArray();
|
||||
|
||||
Assert.That(visibleBeatmaps, Is.EqualTo(expectedBeatmapIndexes));
|
||||
}
|
||||
|
||||
[TestCase("ar!=5", new[] { 0, 2, 3, 5 })]
|
||||
[TestCase("cs!=7", new[] { 0, 2, 3, 6 })]
|
||||
[TestCase("od!=3", new[] { 0, 2, 4, 6 })]
|
||||
[TestCase("hp!=6", new[] { 0, 1, 3, 5, 6 })]
|
||||
[TestCase("star!=1.78", new[] { 0, 2, 3, 5, 6 })]
|
||||
[TestCase("bpm!=144", new[] { 0, 1, 3, 5 })]
|
||||
[TestCase("length!=120", new[] { 2, 3, 4, 6 })]
|
||||
public void TestNotEqualSearchForNumberFilters(string query, int[] expectedBeatmapIndexes)
|
||||
{
|
||||
var carouselBeatmaps = (((float ar, float cs, float od, float hp, double star, double bpm, double length)[])new[]
|
||||
{
|
||||
(10.0f, 5.0f, 1.0f, 6.5f, 2.78, 100.0, 120000.0),
|
||||
(5.0f, 7.0f, 3.0f, 8.0f, 1.78, 244.0, 120000.0),
|
||||
(5.5f, 7.5f, 4.0f, 6.0f, 1.55, 144.0, 60000.0),
|
||||
(6.0f, 2.0f, 3.0f, 7.0f, 3.78, 774.0, 440000.0),
|
||||
(5.0f, 7.0f, 4.0f, 6.0f, 1.78, 144.0, 310000.0),
|
||||
(5.8f, 7.0f, 3.0f, 6.5f, 1.55, 344.0, 120000.0),
|
||||
(5.0f, 3.0f, 7.0f, 10.0f, 2.78, 144.0, 260000.0)
|
||||
}).Select(info => new CarouselBeatmap(new BeatmapInfo
|
||||
{
|
||||
Difficulty = new BeatmapDifficulty{
|
||||
ApproachRate = info.ar,
|
||||
OverallDifficulty = info.od,
|
||||
DrainRate = info.hp,
|
||||
CircleSize = info.cs
|
||||
},
|
||||
BPM = info.bpm,
|
||||
StarRating = info.star,
|
||||
Length = info.length
|
||||
|
||||
})).ToList();
|
||||
|
||||
var criteria = new FilterCriteria();
|
||||
|
||||
FilterQueryParser.ApplyQueries(criteria, query);
|
||||
carouselBeatmaps.ForEach(b => b.Filter(criteria));
|
||||
|
||||
int[] visibleBeatmaps = carouselBeatmaps
|
||||
.Where(b => !b.Filtered.Value)
|
||||
.Select(b => carouselBeatmaps.IndexOf(b)).ToArray();
|
||||
|
||||
Assert.That(visibleBeatmaps, Is.EqualTo(expectedBeatmapIndexes));
|
||||
}
|
||||
|
||||
[TestCase("status!=ranked", new[] { 1, 2, 4, 5 })]
|
||||
[TestCase("status!=r", new[] { 1, 2, 4, 5 })]
|
||||
[TestCase("status!=loved", new[] { 0, 1, 2, 3, 4, 6 })]
|
||||
[TestCase("status!=l", new[] { 0, 1, 2, 3, 4, 6 })]
|
||||
public void TestNotEqualSearchForEnumFilter(string query, int[] expectedBeatmapIndexes)
|
||||
{
|
||||
var carouselBeatmaps = (new BeatmapOnlineStatus[]
|
||||
{
|
||||
BeatmapOnlineStatus.Ranked,
|
||||
BeatmapOnlineStatus.Qualified,
|
||||
BeatmapOnlineStatus.Approved,
|
||||
BeatmapOnlineStatus.Ranked,
|
||||
BeatmapOnlineStatus.Approved,
|
||||
BeatmapOnlineStatus.Loved,
|
||||
BeatmapOnlineStatus.Ranked
|
||||
}).Select(info => new CarouselBeatmap(new BeatmapInfo
|
||||
{
|
||||
Status = info
|
||||
|
||||
})).ToList();
|
||||
|
||||
var criteria = new FilterCriteria();
|
||||
|
||||
FilterQueryParser.ApplyQueries(criteria, query);
|
||||
carouselBeatmaps.ForEach(b => b.Filter(criteria));
|
||||
|
||||
int[] visibleBeatmaps = carouselBeatmaps
|
||||
.Where(b => !b.Filtered.Value)
|
||||
.Select(b => carouselBeatmaps.IndexOf(b)).ToArray();
|
||||
|
||||
Assert.That(visibleBeatmaps, Is.EqualTo(expectedBeatmapIndexes));
|
||||
}
|
||||
|
||||
//played
|
||||
[TestCase("played!=1", new[] { 1, 4, 5 })]
|
||||
[TestCase("played!=0", new[] { 0, 2, 3, 6, 7 })]
|
||||
public void TestNotEqualSearchForBooleanFilter(string query, int[] expectedBeatmapIndexes)
|
||||
{
|
||||
var carouselBeatmaps = (new DateTimeOffset?[]
|
||||
{
|
||||
new DateTime(2012, 10, 21),
|
||||
null,
|
||||
new DateTime(2012, 11, 12),
|
||||
new DateTime(2013, 2, 13),
|
||||
null,
|
||||
null,
|
||||
new DateTime(2014, 1, 15),
|
||||
new DateTime(2014, 11, 16),
|
||||
}).Select(info => new CarouselBeatmap(new BeatmapInfo
|
||||
{
|
||||
LastPlayed = info
|
||||
})).ToList();
|
||||
|
||||
var criteria = new FilterCriteria();
|
||||
|
||||
FilterQueryParser.ApplyQueries(criteria, query);
|
||||
carouselBeatmaps.ForEach(b => b.Filter(criteria));
|
||||
|
||||
int[] visibleBeatmaps = carouselBeatmaps
|
||||
.Where(b => !b.Filtered.Value)
|
||||
.Select(b => carouselBeatmaps.IndexOf(b)).ToArray();
|
||||
|
||||
Assert.That(visibleBeatmaps, Is.EqualTo(expectedBeatmapIndexes));
|
||||
}
|
||||
|
||||
//submitted, ranked
|
||||
[TestCase("ranked!=2012", new[] { 3, 4, 5, 6, 7 })]
|
||||
[TestCase("ranked!=2012.11", new[] { 0, 1, 3, 4, 5, 6, 7 })]
|
||||
[TestCase("ranked!=2012.10.21", new[] { 1, 2, 3, 4, 5, 6, 7 })]
|
||||
[TestCase("submitted!=2012", new[] { 3, 4, 5, 6, 7 })]
|
||||
[TestCase("submitted!=2012.11", new[] { 0, 1, 3, 4, 5, 6, 7 })]
|
||||
[TestCase("submitted!=2012.10.21", new[] { 1, 2, 3, 4, 5, 6, 7 })]
|
||||
public void TestNotEqualSearchForDateFilter(string query, int[] expectedBeatmapIndexes)
|
||||
{
|
||||
var carouselBeatmaps = (new DateTime[]
|
||||
{
|
||||
new DateTime(2012, 10, 21),
|
||||
new DateTime(2012, 10, 11),
|
||||
new DateTime(2012, 11, 12),
|
||||
new DateTime(2013, 2, 13),
|
||||
new DateTime(2013, 2, 13),
|
||||
new DateTime(2013, 3, 14),
|
||||
new DateTime(2014, 1, 15),
|
||||
new DateTime(2014, 11, 16),
|
||||
}).Select(info => new CarouselBeatmap(new BeatmapInfo
|
||||
{
|
||||
BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
DateRanked = new DateTimeOffset(info),
|
||||
DateSubmitted = new DateTimeOffset(info),
|
||||
}
|
||||
|
||||
})).ToList();
|
||||
|
||||
var criteria = new FilterCriteria();
|
||||
|
||||
FilterQueryParser.ApplyQueries(criteria, query);
|
||||
carouselBeatmaps.ForEach(b => b.Filter(criteria));
|
||||
|
||||
int[] visibleBeatmaps = carouselBeatmaps
|
||||
.Where(b => !b.Filtered.Value)
|
||||
.Select(b => carouselBeatmaps.IndexOf(b)).ToArray();
|
||||
|
||||
Assert.That(visibleBeatmaps, Is.EqualTo(expectedBeatmapIndexes));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestApplySourceQueries()
|
||||
{
|
||||
|
||||
@@ -212,16 +212,16 @@ namespace osu.Game.Screens.Select
|
||||
case MatchMode.Substring:
|
||||
// Note that we are using ordinal here to avoid performance issues caused by globalisation concerns.
|
||||
// See https://github.com/ppy/osu/issues/11571 / https://github.com/dotnet/docs/issues/18423.
|
||||
return value.Contains(SearchTerm, StringComparison.OrdinalIgnoreCase);
|
||||
return InvertSearch != value.Contains(SearchTerm, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
case MatchMode.IsolatedPhrase:
|
||||
return Regex.IsMatch(value, $@"(^|\s){Regex.Escape(searchTerm)}($|\s)", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||
return InvertSearch != Regex.IsMatch(value, $@"(^|\s){Regex.Escape(searchTerm)}($|\s)", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||
|
||||
case MatchMode.FullPhrase:
|
||||
return CultureInfo.InvariantCulture.CompareInfo.Compare(value, searchTerm, CompareOptions.OrdinalIgnoreCase) == 0;
|
||||
return InvertSearch != (CultureInfo.InvariantCulture.CompareInfo.Compare(value, searchTerm, CompareOptions.OrdinalIgnoreCase) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
public bool InvertSearch;
|
||||
private string searchTerm;
|
||||
|
||||
public string SearchTerm
|
||||
|
||||
@@ -76,7 +76,8 @@ namespace osu.Game.Screens.Select
|
||||
return false;
|
||||
|
||||
// Unplayed beatmaps are filtered on DateTimeOffset.MinValue.
|
||||
|
||||
if (op == Operator.NotEqual)
|
||||
played = !played;
|
||||
if (played)
|
||||
{
|
||||
criteria.LastPlayed.Min = DateTimeOffset.MinValue;
|
||||
@@ -233,6 +234,11 @@ namespace osu.Game.Screens.Select
|
||||
textFilter.SearchTerm = value;
|
||||
return true;
|
||||
|
||||
case Operator.NotEqual:
|
||||
textFilter.InvertSearch = true;
|
||||
textFilter.SearchTerm = value;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -493,7 +499,6 @@ namespace osu.Game.Screens.Select
|
||||
private static bool tryUpdateCriteriaRange<T>(ref FilterCriteria.OptionalRange<T> range, Operator op, T value)
|
||||
where T : struct
|
||||
{
|
||||
range.InvertRange = false;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
@@ -587,13 +592,15 @@ namespace osu.Game.Screens.Select
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case Operator.NotEqual:
|
||||
case Operator.Equal:
|
||||
// an equality filter is difficult to define for support here.
|
||||
// an equality or inequality filter is difficult to define for support here.
|
||||
// if "3 months 2 days ago" means a single concrete time instant, such a filter is basically useless.
|
||||
// if it means a range of 24 hours, then that is annoying to write and also comes with its own implications
|
||||
// (does it mean "time instant 3 months 2 days ago, within 12 hours of tolerance either direction"?
|
||||
// does it mean "the full calendar day, from midnight to midnight, 3 months 2 days ago"?)
|
||||
// as such, for simplicity, just refuse to support this.
|
||||
// same applies to inequality, but instead 24 hours would be need to be left out
|
||||
return false;
|
||||
|
||||
// for the remaining operators, since the value provided to this function is an "ago" type value
|
||||
@@ -748,6 +755,7 @@ namespace osu.Game.Screens.Select
|
||||
DateTimeOffset dateTimeOffset;
|
||||
DateTimeOffset minDateTimeOffset;
|
||||
DateTimeOffset maxDateTimeOffset;
|
||||
dateRange.InvertRange = false;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
@@ -831,14 +839,16 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
case Operator.NotEqual:
|
||||
|
||||
dateRange.InvertRange = true;
|
||||
|
||||
if (month == null)
|
||||
{
|
||||
month = 1;
|
||||
day = 1;
|
||||
minDateTimeOffset = dateTimeOffsetFromDateOnly(year.Value, month.Value, day.Value);
|
||||
maxDateTimeOffset = dateTimeOffsetFromDateOnly(year.Value, month.Value, day.Value).AddYears(1);
|
||||
return tryUpdateCriteriaRange(ref dateRange, Operator.Less, minDateTimeOffset)
|
||||
|| tryUpdateCriteriaRange(ref dateRange, Operator.GreaterOrEqual, maxDateTimeOffset);
|
||||
return tryUpdateCriteriaRange(ref dateRange, Operator.GreaterOrEqual, minDateTimeOffset)
|
||||
&& tryUpdateCriteriaRange(ref dateRange, Operator.Less, maxDateTimeOffset);
|
||||
}
|
||||
|
||||
if (day == null)
|
||||
@@ -846,14 +856,14 @@ namespace osu.Game.Screens.Select
|
||||
day = 1;
|
||||
minDateTimeOffset = dateTimeOffsetFromDateOnly(year.Value, month.Value, day.Value);
|
||||
maxDateTimeOffset = dateTimeOffsetFromDateOnly(year.Value, month.Value, day.Value).AddMonths(1);
|
||||
return tryUpdateCriteriaRange(ref dateRange, Operator.Less, minDateTimeOffset)
|
||||
|| tryUpdateCriteriaRange(ref dateRange, Operator.GreaterOrEqual, maxDateTimeOffset);
|
||||
return tryUpdateCriteriaRange(ref dateRange, Operator.GreaterOrEqual, minDateTimeOffset)
|
||||
&& tryUpdateCriteriaRange(ref dateRange, Operator.Less, maxDateTimeOffset);
|
||||
}
|
||||
|
||||
minDateTimeOffset = dateTimeOffsetFromDateOnly(year.Value, month.Value, day.Value);
|
||||
maxDateTimeOffset = dateTimeOffsetFromDateOnly(year.Value, month.Value, day.Value).AddDays(1);
|
||||
return tryUpdateCriteriaRange(ref dateRange, Operator.Less, minDateTimeOffset)
|
||||
|| tryUpdateCriteriaRange(ref dateRange, Operator.GreaterOrEqual, maxDateTimeOffset);
|
||||
minDateTimeOffset = dateTimeOffsetFromDateOnly(year.Value, month.Value, day.Value).AddDays(-1);
|
||||
maxDateTimeOffset = dateTimeOffsetFromDateOnly(year.Value, month.Value, day.Value);
|
||||
return tryUpdateCriteriaRange(ref dateRange, Operator.GreaterOrEqual, minDateTimeOffset)
|
||||
&& tryUpdateCriteriaRange(ref dateRange, Operator.Less, maxDateTimeOffset);
|
||||
|
||||
default:
|
||||
return false;
|
||||
@@ -862,7 +872,7 @@ namespace osu.Game.Screens.Select
|
||||
catch (ArgumentOutOfRangeException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user