package org.limewire.ui.swing.search;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.limewire.core.api.FilePropertyKey;
import org.limewire.core.api.search.SearchCategory;
import org.limewire.ui.swing.util.FilePropertyKeyUtils;
import org.limewire.ui.swing.util.Translator;
import org.limewire.util.BaseTestCase;
/**
* Tests for {@link KeywordAssistedSearchBuilder}.
*/
public class AdvancedSearchBuilderTest extends BaseTestCase {
public AdvancedSearchBuilderTest(String name) {
super(name);
}
/**
* Specifically test translation of the key separator works or almost all other tests
* in this package will fail.
*/
public void testGetKeySeparator() {
Mockery context = new Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
final Translator translator = context.mock(Translator.class);
final KeywordAssistedSearchBuilder searchBuilder = new KeywordAssistedSearchBuilder(translator);
context.checking(new Expectations() {{
allowing(translator).translateWithComment(with(any(String.class)), with(equal(":")));
will(returnValue("-"));
}});
assertEquals("-", searchBuilder.getTranslatedKeySeprator());
}
/**
* Tests {@link KeywordAssistedSearchBuilder#createCompositeQuery(Map)}.
*/
public void testCreateCompositeQueryBasic() {
Mockery context = new Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
final Translator translator = context.mock(Translator.class);
final KeywordAssistedSearchBuilder searchBuilder = new KeywordAssistedSearchBuilder(translator);
context.checking(new Expectations() {{
allowing(translator).translate(
FilePropertyKeyUtils.getUntraslatedDisplayName(FilePropertyKey.YEAR, SearchCategory.DOCUMENT));
will(returnValue("hello"));
allowing(translator).translate(
FilePropertyKeyUtils.getUntraslatedDisplayName(FilePropertyKey.AUTHOR, SearchCategory.DOCUMENT));
will(returnValue("bye"));
allowing(translator).translateWithComment(with(any(String.class)), with(equal(":")));
will(returnValue(":"));
}});
assertEquals("", searchBuilder.createCompositeQuery(new HashMap<FilePropertyKey, String>(), SearchCategory.DOCUMENT));
Map<FilePropertyKey,String> map = new HashMap<FilePropertyKey,String>();
map.put(FilePropertyKey.YEAR, "1982");
String query = searchBuilder.createCompositeQuery(map, SearchCategory.DOCUMENT);
assertTrue(query.startsWith("hello"));
assertTrue(query.endsWith("1982"));
char seperator = query.charAt(5);
assertEquals(':', seperator);
map.put(FilePropertyKey.AUTHOR, "lpsadsac");
query = searchBuilder.createCompositeQuery(map, SearchCategory.ALL);
// Verify there is some sanity when constructing key/value list
int firstKeyLen = query.indexOf(seperator);
String firstKey = query.substring(0, firstKeyLen);
if (firstKey.equals("bye")) {
assertTrue(query.indexOf("lpsadsac") > 0);
int secondKeyLen = query.indexOf(seperator, firstKeyLen+1);
assertEquals("1982", query.substring(secondKeyLen+1));
} else if (firstKey.equals("hello")) {
assertTrue(query.indexOf("1982") > 0);
int secondKeyLen = query.indexOf(seperator, firstKeyLen+1);
assertEquals("lpsadsac", query.substring(secondKeyLen+1));
} else {
fail("Keys not found in composite search string");
}
}
/**
* Tests creations of a composite query String with a longer than one character
* key/value separator.
*/
public void testCreateCompositeQueryWithNewSeparator() {
Mockery context = new Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
final Translator translator = context.mock(Translator.class);
final KeywordAssistedSearchBuilder searchBuilder = new KeywordAssistedSearchBuilder(translator);
context.checking(new Expectations() {{
allowing(translator).translate(
FilePropertyKeyUtils.getUntraslatedDisplayName(FilePropertyKey.YEAR, SearchCategory.DOCUMENT));
will(returnValue("hello"));
allowing(translator).translateWithComment(with(any(String.class)), with(equal(":")));
will(returnValue("---"));
}});
Map<FilePropertyKey,String> map = new HashMap<FilePropertyKey,String>();
map.put(FilePropertyKey.YEAR, "1982");
String query = searchBuilder.createCompositeQuery(map, SearchCategory.DOCUMENT);
assertTrue(query.startsWith("hello"));
assertTrue(query.endsWith("1982"));
String seperator = query.substring(5,8);
assertEquals("---", seperator);
}
/**
* Tests creations of a composite query String with right to left text.
*
* <p> In this case Arabic is used.
*/
/* public void testCreateCompositeQueryWithRightToLeft() {
Mockery context = new Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
final Translator translator = context.mock(Translator.class);
final AdvancedSearchBuilder searchBuilder = new AdvancedSearchBuilder(translator);
context.checking(new Expectations() {{
allowing(translator).translate(
FilePropertyKeyUtils.getUntraslatedDisplayName(FilePropertyKey.YEAR, SearchCategory.ALL));
will(returnValue("العربية"));
allowing(translator).translateWithComment(with(any(String.class)), with(equal(":")));
will(returnValue("ل"));
}});
Map<FilePropertyKey,String> map = new HashMap<FilePropertyKey,String>();
map.put(FilePropertyKey.YEAR, "لا أتكلم العربية");
String query = searchBuilder.createCompositeQuery(map, SearchCategory.ALL);
assertTrue(query.startsWith("العربية"));
assertTrue(query.endsWith("لا أتكلم العربية"));
char seperator = query.charAt(7);
assertEquals('ل', seperator);
}
*/
/**
* Tests creations of a composite query String with right to left and left to right text
* mixed.
*
* <p> In this case Arabic is used with the Roman colon.
*/
/* public void testCreateCompositeQueryWithRightToLeftAndLeftToRightMix() {
Mockery context = new Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
final Translator translator = context.mock(Translator.class);
final AdvancedSearchBuilder searchBuilder = new AdvancedSearchBuilder(translator);
context.checking(new Expectations() {{
allowing(translator).translate(
FilePropertyKeyUtils.getUntraslatedDisplayName(FilePropertyKey.YEAR, SearchCategory.ALL));
will(returnValue("العربية"));
allowing(translator).translateWithComment(with(any(String.class)), with(equal(":")));
will(returnValue(":"));
}});
Map<FilePropertyKey,String> map = new HashMap<FilePropertyKey,String>();
map.put(FilePropertyKey.YEAR, "لا أتكلم العربية");
String query = searchBuilder.createCompositeQuery(map, SearchCategory.ALL);
assertTrue(query.startsWith("العربية"));
assertTrue(query.endsWith("لا أتكلم العربية"));
char seperator = query.charAt(7);
assertEquals(':', seperator);
}
*/
/**
* Test the entirety of {@link KeywordAssistedSearchBuilder#createAdvancedSearch(Map, SearchCategory)}.
*/
public void testCreateAdvancedSearch() {
Mockery context = new Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
final Translator translator = context.mock(Translator.class);
final KeywordAssistedSearchBuilder searchBuilder = new KeywordAssistedSearchBuilder(translator);
context.checking(new Expectations() {{
allowing(translator).translate(
FilePropertyKeyUtils.getUntraslatedDisplayName(FilePropertyKey.YEAR, SearchCategory.DOCUMENT));
will(returnValue("key"));
allowing(translator).translateWithComment(with(any(String.class)), with(equal(":")));
will(returnValue(":"));
}});
Map<FilePropertyKey,String> map = new HashMap<FilePropertyKey,String>();
map.put(FilePropertyKey.YEAR, "value");
SearchInfo search = searchBuilder.createAdvancedSearch(map, SearchCategory.AUDIO);
assertEquals(SearchCategory.AUDIO, search.getSearchCategory());
assertTrue(search.getTitle().indexOf("key") > -1);
}
/**
* Test {@link KeywordAssistedSearchBuilder#attemptToCreateAdvancedSearch(String, SearchCategory)
*/
public void testAttemptToCreateAdvancedSearchSingleTuple() {
Mockery context = new Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
final Translator mockedTranslator = context.mock(Translator.class);
final Translator translator = new MockableTranslator(mockedTranslator);
final KeywordAssistedSearchBuilder searchBuilder = new KeywordAssistedSearchBuilder(translator);
context.checking(new Expectations() {{
allowing(mockedTranslator).isCurrentLanguageEnglish();
will(returnValue(false));
allowing(mockedTranslator).translate(
FilePropertyKeyUtils.getUntraslatedDisplayName(FilePropertyKey.YEAR, SearchCategory.DOCUMENT));
will(returnValue("key"));
allowing(mockedTranslator).translate(
FilePropertyKeyUtils.getUntraslatedDisplayName(FilePropertyKey.YEAR, SearchCategory.PROGRAM));
will(returnValue("key"));
allowing(mockedTranslator).translate(
FilePropertyKeyUtils.getUntraslatedDisplayName(FilePropertyKey.YEAR, SearchCategory.AUDIO));
will(returnValue("key"));
// Do not match any other translations
allowing(mockedTranslator).translate(with(any(String.class)));
will(returnValue("@$%@$#@SDFSDF@#%@#$DFD"));
allowing(mockedTranslator).translateWithComment(with(any(String.class)), with(equal(":")));
will(returnValue(":"));
}});
SearchInfo search1 = searchBuilder.attemptToCreateAdvancedSearch("key:value", SearchCategory.DOCUMENT);
assertNotNull(search1);
assertEquals(SearchCategory.DOCUMENT, search1.getSearchCategory());
assertEquals("value", search1.getAdvancedDetails().get(FilePropertyKey.YEAR));
SearchInfo search2 = searchBuilder.attemptToCreateAdvancedSearch(" key: value ", SearchCategory.PROGRAM);
assertNotNull(search2);
assertEquals(SearchCategory.PROGRAM, search2.getSearchCategory());
assertEquals("value", search2.getAdvancedDetails().get(FilePropertyKey.YEAR));
SearchInfo search3 = searchBuilder.attemptToCreateAdvancedSearch("key: aartist:value:", SearchCategory.AUDIO);
assertNotNull(search3);
assertEquals(SearchCategory.AUDIO, search3.getSearchCategory());
assertEquals("aartist:value:", search3.getAdvancedDetails().get(FilePropertyKey.YEAR));
SearchInfo search4 = searchBuilder.attemptToCreateAdvancedSearch(" kEY: value ", SearchCategory.PROGRAM);
assertNotNull(search4);
assertEquals(SearchCategory.PROGRAM, search4.getSearchCategory());
assertEquals("value", search4.getAdvancedDetails().get(FilePropertyKey.YEAR));
SearchInfo search5 = searchBuilder.attemptToCreateAdvancedSearch("yEaR: aartist:value:", SearchCategory.AUDIO);
assertNotNull(search5);
assertEquals(SearchCategory.AUDIO, search5.getSearchCategory());
assertEquals("aartist:value:", search5.getAdvancedDetails().get(FilePropertyKey.YEAR));
SearchInfo search6 = searchBuilder.attemptToCreateAdvancedSearch("GenrE:: asddsd sddafas: asdsad:: genre: classical", SearchCategory.AUDIO);
assertNotNull(search6);
assertEquals(SearchCategory.AUDIO, search6.getSearchCategory());
assertEquals(": asddsd sddafas: asdsad:: genre: classical", search6.getAdvancedDetails().get(FilePropertyKey.GENRE));
context.assertIsSatisfied();
}
/**
* Test a variety of cases where an advanced search can not and should not be parsed from a query String.
*/
public void testAttemptToCreateAdvancedSearchImpossible() {
Mockery context = new Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
final Translator mockedTranslator1 = context.mock(Translator.class);
final Translator translator1 = new MockableTranslator(mockedTranslator1);
final Translator mockedTranslator2 = context.mock(Translator.class);
final Translator translator2 = new MockableTranslator(mockedTranslator2);
final KeywordAssistedSearchBuilder searchBuilder1 = new KeywordAssistedSearchBuilder(translator1);
final KeywordAssistedSearchBuilder searchBuilder2 = new KeywordAssistedSearchBuilder(translator2);
context.checking(new Expectations() {{
allowing(mockedTranslator1).isCurrentLanguageEnglish();
will(returnValue(false));
allowing(mockedTranslator1).translate(
FilePropertyKeyUtils.getUntraslatedDisplayName(FilePropertyKey.YEAR, SearchCategory.AUDIO));
will(returnValue("key"));
// Do not match any other translations
allowing(mockedTranslator1).translate(with(any(String.class)));
will(returnValue("@$%@$#@SDFSDF@#%@#$DFD"));
allowing(mockedTranslator1).translateWithComment(with(any(String.class)), with(equal(":")));
will(returnValue(":"));
allowing(mockedTranslator2).isCurrentLanguageEnglish();
will(returnValue(false));
allowing(mockedTranslator2).translate(
FilePropertyKeyUtils.getUntraslatedDisplayName(FilePropertyKey.YEAR, SearchCategory.AUDIO));
will(returnValue("key"));
// Do not match any other translations
allowing(mockedTranslator2).translate(with(any(String.class)));
will(returnValue("@$%@$#@SDFSDF@#%@#$DFD"));
allowing(mockedTranslator2).translateWithComment(with(any(String.class)), with(equal(":")));
will(returnValue("-"));
}});
SearchInfo search1 = searchBuilder1.attemptToCreateAdvancedSearch("not a key: not a value name: impossible",
SearchCategory.AUDIO);
assertNull(search1);
SearchInfo search2 = searchBuilder1.attemptToCreateAdvancedSearch("not a key, impossible",
SearchCategory.AUDIO);
assertNull(search2);
SearchInfo search3 = searchBuilder1.attemptToCreateAdvancedSearch("artist: is not a key in all",
SearchCategory.DOCUMENT);
assertNull(search3);
SearchInfo search4 = searchBuilder1.attemptToCreateAdvancedSearch("",
SearchCategory.AUDIO);
assertNull(search4);
SearchInfo search5 = searchBuilder1.attemptToCreateAdvancedSearch(" ",
SearchCategory.AUDIO);
assertNull(search5);
SearchInfo search6 = searchBuilder1.attemptToCreateAdvancedSearch(" name-insert my name here ",
SearchCategory.AUDIO);
assertNull(search6);
SearchInfo search7 = searchBuilder1.attemptToCreateAdvancedSearch(" name-insert my name here ",
SearchCategory.AUDIO);
assertNull(search7);
SearchInfo search8 = searchBuilder2.attemptToCreateAdvancedSearch(" artist-insert my name here ",
SearchCategory.AUDIO);
assertNull(search8);
context.assertIsSatisfied();
}
/**
* Tests {@link KeywordAssistedSearchBuilder#attemptToCreateAdvancedSearch(String, SearchCategory)} with
* queries including multi character separators and multi token keys.
*/
public void testAttemptToCreateAdvancedSearchWithComplexSeparatorsAndKeys() {
Mockery context = new Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
final Translator mockedTranslator1 = context.mock(Translator.class);
final Translator translator1 = new MockableTranslator(mockedTranslator1);
final KeywordAssistedSearchBuilder searchBuilder1 = new KeywordAssistedSearchBuilder(translator1);
context.checking(new Expectations() {{
allowing(mockedTranslator1).isCurrentLanguageEnglish();
will(returnValue(false));
allowing(mockedTranslator1).translate(
FilePropertyKeyUtils.getUntraslatedDisplayName(FilePropertyKey.YEAR, SearchCategory.AUDIO));
will(returnValue("key hat cat rANDo-mAt:"));
// Do not match any other translations
allowing(mockedTranslator1).translate(with(any(String.class)));
will(returnValue("@$%@$#@SDFSDF@#%@#$DFD"));
allowing(mockedTranslator1).translateWithComment(with(any(String.class)), with(equal(":")));
will(returnValue(":: a ::"));
}});
SearchInfo search1 = searchBuilder1.attemptToCreateAdvancedSearch("key hat cat rando-mat::: a ::hello",
SearchCategory.AUDIO);
assertNotNull(search1);
assertEquals(SearchCategory.AUDIO, search1.getSearchCategory());
assertEquals("hello", search1.getAdvancedDetails().get(FilePropertyKey.YEAR));
context.assertIsSatisfied();
}
/**
* Test parsing advanced quieries with mutiple key/value pairs.
*/
public void testAttemptToCreateAdvancedSearchMultiKeyQuery() {
final KeywordAssistedSearchBuilder searchBuilder1 = new KeywordAssistedSearchBuilder(new Translator() {
@Override
public boolean isCurrentLanguageEnglish() {
return true;
}
});
SearchInfo search1 = searchBuilder1.attemptToCreateAdvancedSearch("genre:::::a title:cawr pawr artist:flabbats ",
SearchCategory.AUDIO);
assertNotNull(search1);
assertEquals(SearchCategory.AUDIO, search1.getSearchCategory());
assertEquals("::::a", search1.getAdvancedDetails().get(FilePropertyKey.GENRE));
assertEquals("cawr pawr", search1.getAdvancedDetails().get(FilePropertyKey.TITLE));
assertEquals("flabbats", search1.getAdvancedDetails().get(FilePropertyKey.AUTHOR));
}
/**
* Helper class to allow a partial overlay of {@link Translator}.
*/
private class MockableTranslator extends Translator {
private final Translator baseTranslator;
private Locale caseLocale = Locale.US;
public MockableTranslator(Translator baseTranslator) {
this.baseTranslator = baseTranslator;
}
public void setCaseLocale(Locale locale) {
caseLocale = locale;
}
@Override
public String translate(String text) {
return baseTranslator.translate(text);
}
@Override
public String translateWithComment(String comment, String text) {
return baseTranslator.translateWithComment(comment, text);
}
@Override
public boolean isCurrentLanguageEnglish() {
return baseTranslator.isCurrentLanguageEnglish();
}
@Override
public String toLowerCaseEnglish(String text) {
return text.toLowerCase(Locale.US);
}
@Override
public String toLowerCaseCurrentLocale(String text) {
return text.toLowerCase(caseLocale);
}
}
}