2019-09-29 13:27:28 +10:00
using System ;
2019-09-29 00:09:03 +10:00
using System.Collections.Generic ;
using System.Diagnostics ;
2014-02-09 00:33:10 +08:00
using System.Linq ;
using NUnit.Framework ;
using Wox.Infrastructure ;
2019-12-03 15:04:02 +01:00
using Wox.Infrastructure.UserSettings ;
2016-01-06 21:34:42 +00:00
using Wox.Plugin ;
2014-02-09 00:33:10 +08:00
namespace Wox.Test
{
[TestFixture]
public class FuzzyMatcherTest
{
2019-12-30 01:13:33 +02:00
private const string Chrome = "Chrome" ;
private const string CandyCrushSagaFromKing = "Candy Crush Saga from King" ;
private const string HelpCureHopeRaiseOnMindEntityChrome = "Help cure hope raise on mind entity Chrome" ;
private const string UninstallOrChangeProgramsOnYourComputer = "Uninstall or change programs on your computer" ;
private const string LastIsChrome = "Last is chrome" ;
private const string OneOneOneOne = "1111" ;
private const string MicrosoftSqlServerManagementStudio = "Microsoft SQL Server Management Studio" ;
2019-12-09 21:08:17 +01:00
public List < string > GetSearchStrings ( )
2019-09-29 00:09:03 +10:00
= > new List < string >
{
2019-12-30 01:13:33 +02:00
Chrome ,
2019-09-29 00:09:03 +10:00
"Choose which programs you want Windows to use for activities like web browsing, editing photos, sending e-mail, and playing music." ,
2019-12-30 01:13:33 +02:00
HelpCureHopeRaiseOnMindEntityChrome ,
CandyCrushSagaFromKing ,
UninstallOrChangeProgramsOnYourComputer ,
2019-09-29 00:09:03 +10:00
"Add, change, and manage fonts on your computer" ,
2019-12-30 01:13:33 +02:00
LastIsChrome ,
OneOneOneOne
2019-09-29 00:09:03 +10:00
} ;
public List < int > GetPrecisionScores ( )
2019-09-29 13:27:28 +10:00
{
var listToReturn = new List < int > ( ) ;
Enum . GetValues ( typeof ( StringMatcher . SearchPrecisionScore ) )
. Cast < StringMatcher . SearchPrecisionScore > ( )
. ToList ( )
. ForEach ( x = > listToReturn . Add ( ( int ) x ) ) ;
return listToReturn ;
}
2019-09-29 00:09:03 +10:00
2014-02-09 00:33:10 +08:00
[Test]
public void MatchTest ( )
{
2016-01-06 21:34:42 +00:00
var sources = new List < string >
2014-02-09 00:33:10 +08:00
{
"file open in browser-test" ,
"Install Package" ,
"add new bsd" ,
"Inste" ,
2016-01-06 21:34:42 +00:00
"aac"
2014-02-09 00:33:10 +08:00
} ;
2016-01-06 21:34:42 +00:00
var results = new List < Result > ( ) ;
2014-02-09 00:33:10 +08:00
foreach ( var str in sources )
{
2016-01-06 21:34:42 +00:00
results . Add ( new Result
2014-02-09 00:33:10 +08:00
{
Title = str ,
2019-12-09 21:08:17 +01:00
Score = StringMatcher . FuzzySearch ( "inst" , str ) . RawScore
2014-02-09 00:33:10 +08:00
} ) ;
}
results = results . Where ( x = > x . Score > 0 ) . OrderByDescending ( x = > x . Score ) . ToList ( ) ;
Assert . IsTrue ( results . Count = = 3 ) ;
Assert . IsTrue ( results [ 0 ] . Title = = "Inste" ) ;
Assert . IsTrue ( results [ 1 ] . Title = = "Install Package" ) ;
Assert . IsTrue ( results [ 2 ] . Title = = "file open in browser-test" ) ;
}
2019-09-29 00:09:03 +10:00
[TestCase("Chrome")]
public void WhenGivenNotAllCharactersFoundInSearchStringThenShouldReturnZeroScore ( string searchString )
{
var compareString = "Can have rum only in my glass" ;
2019-12-09 21:08:17 +01:00
var scoreResult = StringMatcher . FuzzySearch ( searchString , compareString ) . RawScore ;
2019-09-29 00:09:03 +10:00
Assert . True ( scoreResult = = 0 ) ;
}
2019-12-30 01:13:33 +02:00
2019-09-29 13:27:28 +10:00
[TestCase("chr")]
2019-09-29 00:09:03 +10:00
[TestCase("chrom")]
2019-12-30 01:13:33 +02:00
[TestCase("chrome")]
2019-09-30 21:51:15 +10:00
[TestCase("cand")]
[TestCase("cpywa")]
2019-09-29 00:09:03 +10:00
[TestCase("ccs")]
public void WhenGivenStringsAndAppliedPrecisionFilteringThenShouldReturnGreaterThanPrecisionScoreResults ( string searchTerm )
{
var results = new List < Result > ( ) ;
2019-12-30 01:13:33 +02:00
2019-09-29 00:09:03 +10:00
foreach ( var str in GetSearchStrings ( ) )
{
results . Add ( new Result
{
Title = str ,
2019-10-17 13:37:09 +03:00
Score = StringMatcher . FuzzySearch ( searchTerm , str ) . Score
2019-09-29 00:09:03 +10:00
} ) ;
2019-12-30 01:13:33 +02:00
}
2019-09-29 00:09:03 +10:00
foreach ( var precisionScore in GetPrecisionScores ( ) )
{
var filteredResult = results . Where ( result = > result . Score > = precisionScore ) . Select ( result = > result ) . OrderByDescending ( x = > x . Score ) . ToList ( ) ;
Debug . WriteLine ( "" ) ;
Debug . WriteLine ( "###############################################" ) ;
Debug . WriteLine ( "SEARCHTERM: " + searchTerm + ", GreaterThanSearchPrecisionScore: " + precisionScore ) ;
foreach ( var item in filteredResult )
{
Debug . WriteLine ( "SCORE: " + item . Score . ToString ( ) + ", FoundString: " + item . Title ) ;
}
Debug . WriteLine ( "###############################################" ) ;
Debug . WriteLine ( "" ) ;
Assert . IsFalse ( filteredResult . Any ( x = > x . Score < precisionScore ) ) ;
}
}
2019-12-30 01:13:33 +02:00
[TestCase]
public void WhenGivenStringsForCalScoreMethodThenShouldReturnCurrentScoring ( )
2019-09-29 00:09:03 +10:00
{
2019-12-30 01:13:33 +02:00
// Arrange
string searchTerm = "chrome" ; // since this looks for specific results it will always be one case
2019-09-29 00:09:03 +10:00
var searchStrings = new List < string >
{
2019-12-30 01:13:33 +02:00
Chrome , //SCORE: 107
LastIsChrome , //SCORE: 53
HelpCureHopeRaiseOnMindEntityChrome , //SCORE: 21
UninstallOrChangeProgramsOnYourComputer , //SCORE: 15
CandyCrushSagaFromKing //SCORE: 0
2019-09-29 00:09:03 +10:00
}
. OrderByDescending ( x = > x )
. ToList ( ) ;
2019-12-30 01:13:33 +02:00
// Act
2019-09-29 00:09:03 +10:00
var results = new List < Result > ( ) ;
foreach ( var str in searchStrings )
{
results . Add ( new Result
{
Title = str ,
2019-12-09 21:08:17 +01:00
Score = StringMatcher . FuzzySearch ( searchTerm , str ) . RawScore
2019-09-29 00:09:03 +10:00
} ) ;
}
2019-12-30 01:13:33 +02:00
// Assert
VerifyResult ( 147 , Chrome ) ;
VerifyResult ( 93 , LastIsChrome ) ;
VerifyResult ( 41 , HelpCureHopeRaiseOnMindEntityChrome ) ;
VerifyResult ( 35 , UninstallOrChangeProgramsOnYourComputer ) ;
VerifyResult ( 0 , CandyCrushSagaFromKing ) ;
2019-09-29 00:09:03 +10:00
2019-12-30 01:13:33 +02:00
void VerifyResult ( int expectedScore , string expectedTitle )
2019-09-29 00:09:03 +10:00
{
2019-12-30 01:13:33 +02:00
var result = results . FirstOrDefault ( x = > x . Title = = expectedTitle ) ;
if ( result = = null )
{
Assert . Fail ( $"Fail to find result: {expectedTitle} in result list" ) ;
}
Assert . AreEqual ( expectedScore , result . Score , $"Expected score for {expectedTitle}: {expectedScore}, Actual: {result.Score}" ) ;
2019-09-29 00:09:03 +10:00
}
}
2019-09-29 14:27:07 +10:00
2019-09-30 21:51:15 +10:00
[TestCase("goo", "Google Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
2019-09-29 14:27:07 +10:00
[TestCase("chr", "Google Chrome", (int)StringMatcher.SearchPrecisionScore.Low, true)]
2019-09-30 21:51:15 +10:00
[TestCase("chr", "Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
2019-09-29 13:27:28 +10:00
[TestCase("chr", "Help cure hope raise on mind entity Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("chr", "Help cure hope raise on mind entity Chrome", (int)StringMatcher.SearchPrecisionScore.Low, true)]
[TestCase("chr", "Candy Crush Saga from King", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
2019-09-29 14:27:07 +10:00
[TestCase("chr", "Candy Crush Saga from King", (int)StringMatcher.SearchPrecisionScore.None, true)]
[TestCase("ccs", "Candy Crush Saga from King", (int)StringMatcher.SearchPrecisionScore.Low, true)]
[TestCase("cand", "Candy Crush Saga from King", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("cand", "Help cure hope raise on mind entity Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
2019-12-03 15:04:02 +01:00
public void WhenGivenDesiredPrecisionThenShouldReturnAllResultsGreaterOrEqual (
2019-12-30 01:13:33 +02:00
string queryString ,
string compareString ,
int expectedPrecisionScore ,
2019-12-03 15:04:02 +01:00
bool expectedPrecisionResult )
2019-09-29 13:27:28 +10:00
{
2019-12-30 01:13:33 +02:00
// Arrange
var expectedPrecisionString = ( StringMatcher . SearchPrecisionScore ) expectedPrecisionScore ;
StringMatcher . UserSettingSearchPrecision = expectedPrecisionScore ; // this is why static state is evil...
// Act
2019-10-17 13:37:09 +03:00
var matchResult = StringMatcher . FuzzySearch ( queryString , compareString ) ;
2019-09-29 14:27:07 +10:00
2020-01-02 08:04:16 +11:00
Debug . WriteLine ( "" ) ;
Debug . WriteLine ( "###############################################" ) ;
Debug . WriteLine ( $"QueryString: {queryString} CompareString: {compareString}" ) ;
Debug . WriteLine ( $"RAW SCORE: {matchResult.RawScore.ToString()}, PrecisionLevelSetAt: {expectedPrecisionString} ({expectedPrecisionScore})" ) ;
Debug . WriteLine ( "###############################################" ) ;
Debug . WriteLine ( "" ) ;
2019-12-30 01:13:33 +02:00
// Assert
Assert . AreEqual ( expectedPrecisionResult , matchResult . IsSearchPrecisionScoreMet ( ) ,
$"Query:{queryString}{Environment.NewLine} " +
$"Compare:{compareString}{Environment.NewLine}" +
$"Raw Score: {matchResult.RawScore}{Environment.NewLine}" +
$"Precision Level: {expectedPrecisionString}={expectedPrecisionScore}" ) ;
}
[TestCase("exce", "OverLeaf-Latex: An online LaTeX editor", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("term", "Windows Terminal (Preview)", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("sql s managa", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("sql' s manag", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("sql s manag", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("sql manag", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("sql", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("sql serv", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
2020-01-07 07:12:34 +11:00
[TestCase("sql studio", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
2019-12-30 01:13:33 +02:00
[TestCase("mic", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("chr", "Shutdown", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("a test", "This is a test", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("test", "This is a test", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
public void WhenGivenQueryShouldReturnResultsContainingAllQuerySubstrings (
string queryString ,
string compareString ,
int expectedPrecisionScore ,
bool expectedPrecisionResult )
{
// Arrange
var expectedPrecisionString = ( StringMatcher . SearchPrecisionScore ) expectedPrecisionScore ;
StringMatcher . UserSettingSearchPrecision = expectedPrecisionScore ; // this is why static state is evil...
// Act
var matchResult = StringMatcher . FuzzySearch ( queryString , compareString ) ;
2019-09-29 14:27:07 +10:00
2020-01-02 08:04:16 +11:00
Debug . WriteLine ( "" ) ;
Debug . WriteLine ( "###############################################" ) ;
Debug . WriteLine ( $"QueryString: {queryString} CompareString: {compareString}" ) ;
Debug . WriteLine ( $"RAW SCORE: {matchResult.RawScore.ToString()}, PrecisionLevelSetAt: {expectedPrecisionString} ({expectedPrecisionScore})" ) ;
Debug . WriteLine ( "###############################################" ) ;
Debug . WriteLine ( "" ) ;
2019-12-30 01:13:33 +02:00
// Assert
Assert . AreEqual ( expectedPrecisionResult , matchResult . IsSearchPrecisionScoreMet ( ) ,
$"Query:{queryString}{Environment.NewLine} " +
$"Compare:{compareString}{Environment.NewLine}" +
$"Raw Score: {matchResult.RawScore}{Environment.NewLine}" +
$"Precision Level: {expectedPrecisionString}={expectedPrecisionScore}" ) ;
2019-09-29 13:27:28 +10:00
}
2014-02-09 00:33:10 +08:00
}
2019-12-30 01:13:33 +02:00
}