/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.api.vfs.search.impl;
import com.google.common.base.Optional;
import org.eclipse.che.api.vfs.ArchiverFactory;
import org.eclipse.che.api.vfs.VirtualFile;
import org.eclipse.che.api.vfs.VirtualFileFilter;
import org.eclipse.che.api.vfs.VirtualFileSystem;
import org.eclipse.che.api.vfs.impl.memory.MemoryVirtualFileSystem;
import org.eclipse.che.api.vfs.search.QueryExpression;
import org.eclipse.che.api.vfs.search.SearchResult;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentMatcher;
import java.util.Collections;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class MemoryLuceneSearcherTest {
private static final String[] TEST_CONTENT = {
"Apollo set several major human spaceflight milestones",
"Maybe you should think twice",
"To be or not to be",
"In early 1961, direct ascent was generally the mission mode in favor at NASA"
};
private MemoryLuceneSearcher searcher;
private VirtualFileFilter filter;
private AbstractLuceneSearcherProvider.CloseCallback closeCallback;
@Before
public void setUp() throws Exception {
filter = mock(VirtualFileFilter.class);
when(filter.accept(any(VirtualFile.class))).thenReturn(false);
closeCallback = mock(AbstractLuceneSearcherProvider.CloseCallback.class);
searcher = new MemoryLuceneSearcher(filter, closeCallback);
}
@After
public void tearDown() throws Exception {
searcher.close();
}
@Test
public void initializesIndexForExistedFiles() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
VirtualFile folder = virtualFileSystem.getRoot().createFolder("folder");
folder.createFile("xxx.txt", TEST_CONTENT[2]);
folder.createFile("zzz.txt", TEST_CONTENT[1]);
searcher.init(virtualFileSystem);
List<String> paths = searcher.search(new QueryExpression().setText("think")).getFilePaths();
assertEquals(newArrayList("/folder/zzz.txt"), paths);
}
@Test
public void addsSingleFileInIndex() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
searcher.init(virtualFileSystem);
VirtualFile file = virtualFileSystem.getRoot().createFolder("aaa").createFile("aaa.txt", TEST_CONTENT[1]);
searcher.add(file);
List<String> paths = searcher.search(new QueryExpression().setText("should")).getFilePaths();
assertEquals(newArrayList(file.getPath().toString()), paths);
}
@Test
public void addsFileTreeInIndex() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
searcher.init(virtualFileSystem);
VirtualFile folder = virtualFileSystem.getRoot().createFolder("folder");
folder.createFile("xxx.txt", TEST_CONTENT[2]);
folder.createFile("zzz.txt", TEST_CONTENT[1]);
searcher.add(virtualFileSystem.getRoot());
List<String> paths = searcher.search(new QueryExpression().setText("be")).getFilePaths();
assertEquals(newArrayList("/folder/xxx.txt"), paths);
paths = searcher.search(new QueryExpression().setText("should")).getFilePaths();
assertEquals(newArrayList("/folder/zzz.txt"), paths);
}
@Test
public void updatesSingleFileInIndex() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
VirtualFile file = virtualFileSystem.getRoot().createFolder("aaa").createFile("aaa.txt", TEST_CONTENT[2]);
searcher.init(virtualFileSystem);
List<String> paths = searcher.search(new QueryExpression().setText("should")).getFilePaths();
assertTrue(paths.isEmpty());
file.updateContent(TEST_CONTENT[1]);
searcher.update(file);
paths = searcher.search(new QueryExpression().setText("should")).getFilePaths();
assertEquals(newArrayList(file.getPath().toString()), paths);
}
@Test
public void deletesSingleFileFromIndex() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
VirtualFile file = virtualFileSystem.getRoot().createFolder("aaa").createFile("aaa.txt", TEST_CONTENT[2]);
searcher.init(virtualFileSystem);
List<String> paths = searcher.search(new QueryExpression().setText("be")).getFilePaths();
assertEquals(newArrayList(file.getPath().toString()), paths);
searcher.delete(file.getPath().toString(), file.isFile());
paths = searcher.search(new QueryExpression().setText("be")).getFilePaths();
assertTrue(paths.isEmpty());
}
@Test
public void deletesFileTreeFromIndex() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
VirtualFile folder = virtualFileSystem.getRoot().createFolder("folder");
folder.createFile("xxx.txt", TEST_CONTENT[2]);
folder.createFile("zzz.txt", TEST_CONTENT[1]);
searcher.init(virtualFileSystem);
List<String> paths = searcher.search(new QueryExpression().setText("be")).getFilePaths();
assertEquals(newArrayList("/folder/xxx.txt"), paths);
paths = searcher.search(new QueryExpression().setText("should")).getFilePaths();
assertEquals(newArrayList("/folder/zzz.txt"), paths);
searcher.delete("/folder", false);
paths = searcher.search(new QueryExpression().setText("be")).getFilePaths();
assertTrue(paths.isEmpty());
paths = searcher.search(new QueryExpression().setText("should")).getFilePaths();
assertTrue(paths.isEmpty());
}
@Test
public void searchesByTextAndFileName() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
VirtualFile folder = virtualFileSystem.getRoot().createFolder("folder");
folder.createFile("xxx.txt", TEST_CONTENT[2]);
folder.createFile("zzz.txt", TEST_CONTENT[2]);
searcher.init(virtualFileSystem);
List<String> paths = searcher.search(new QueryExpression().setText("be").setName("xxx.txt")).getFilePaths();
assertEquals(newArrayList("/folder/xxx.txt"), paths);
}
@Test
public void searchesByTextAndPath() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
VirtualFile folder1 = virtualFileSystem.getRoot().createFolder("folder1/a/b");
VirtualFile folder2 = virtualFileSystem.getRoot().createFolder("folder2");
folder1.createFile("xxx.txt", TEST_CONTENT[2]);
folder2.createFile("zzz.txt", TEST_CONTENT[2]);
searcher.init(virtualFileSystem);
List<String> paths = searcher.search(new QueryExpression().setText("be").setPath("/folder1")).getFilePaths();
assertEquals(newArrayList("/folder1/a/b/xxx.txt"), paths);
}
@Test
public void searchesByTextAndPathAndFileName() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
VirtualFile folder1 = virtualFileSystem.getRoot().createFolder("folder1/a/b");
VirtualFile folder2 = virtualFileSystem.getRoot().createFolder("folder2/a/b");
folder1.createFile("xxx.txt", TEST_CONTENT[2]);
folder1.createFile("yyy.txt", TEST_CONTENT[2]);
folder2.createFile("zzz.txt", TEST_CONTENT[2]);
searcher.init(virtualFileSystem);
List<String> paths = searcher.search(new QueryExpression().setText("be").setPath("/folder1").setName("xxx.txt")).getFilePaths();
assertEquals(newArrayList("/folder1/a/b/xxx.txt"), paths);
}
@Test
public void closesLuceneIndexWriterWhenSearcherClosed() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
searcher.init(virtualFileSystem);
searcher.close();
assertTrue(searcher.isClosed());
assertFalse(searcher.getIndexWriter().isOpen());
}
@Test
public void notifiesCallbackWhenSearcherClosed() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
searcher.init(virtualFileSystem);
searcher.close();
verify(closeCallback).onClose();
}
@Test
public void excludesFilesFromIndexWithFilter() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
VirtualFile folder = virtualFileSystem.getRoot().createFolder("folder");
folder.createFile("xxx.txt", TEST_CONTENT[2]);
folder.createFile("yyy.txt", TEST_CONTENT[2]);
folder.createFile("zzz.txt", TEST_CONTENT[2]);
when(filter.accept(withName("yyy.txt"))).thenReturn(true);
searcher.init(virtualFileSystem);
List<String> paths = searcher.search(new QueryExpression().setText("be")).getFilePaths();
assertEquals(newArrayList("/folder/xxx.txt", "/folder/zzz.txt"), paths);
}
@Test
public void limitsNumberOfSearchResultsWhenMaxItemIsSet() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
for (int i = 0; i < 100; i++) {
virtualFileSystem.getRoot().createFile(String.format("file%02d", i), TEST_CONTENT[i % TEST_CONTENT.length]);
}
searcher.init(virtualFileSystem);
SearchResult result = searcher.search(new QueryExpression().setText("mission").setMaxItems(5));
assertEquals(25, result.getTotalHits());
assertEquals(5, result.getFilePaths().size());
}
@Test
public void generatesQueryExpressionForRetrievingNextPageOfResults() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
for (int i = 0; i < 100; i++) {
virtualFileSystem.getRoot().createFile(String.format("file%02d", i), TEST_CONTENT[i % TEST_CONTENT.length]);
}
searcher.init(virtualFileSystem);
SearchResult result = searcher.search(new QueryExpression().setText("spaceflight").setMaxItems(7));
assertEquals(25, result.getTotalHits());
Optional<QueryExpression> optionalNextPageQueryExpression = result.getNextPageQueryExpression();
assertTrue(optionalNextPageQueryExpression.isPresent());
QueryExpression nextPageQueryExpression = optionalNextPageQueryExpression.get();
assertEquals("spaceflight", nextPageQueryExpression.getText());
assertEquals(7, nextPageQueryExpression.getSkipCount());
assertEquals(7, nextPageQueryExpression.getMaxItems());
}
@Test
public void retrievesSearchResultWithPages() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
for (int i = 0; i < 100; i++) {
virtualFileSystem.getRoot().createFile(String.format("file%02d", i), TEST_CONTENT[i % TEST_CONTENT.length]);
}
searcher.init(virtualFileSystem);
SearchResult firstPage = searcher.search(new QueryExpression().setText("spaceflight").setMaxItems(8));
assertEquals(8, firstPage.getFilePaths().size());
QueryExpression nextPageQueryExpression = firstPage.getNextPageQueryExpression().get();
nextPageQueryExpression.setMaxItems(100);
SearchResult lastPage = searcher.search(nextPageQueryExpression);
assertEquals(17, lastPage.getFilePaths().size());
assertTrue(Collections.disjoint(firstPage.getFilePaths(), lastPage.getFilePaths()));
}
private VirtualFileSystem virtualFileSystem() throws Exception {
return new MemoryVirtualFileSystem(mock(ArchiverFactory.class), null);
}
private static VirtualFile withName(String name) {
return argThat(new ArgumentMatcher<VirtualFile>() {
@Override
public boolean matches(Object argument) {
return name.equals(((VirtualFile)argument).getName());
}
});
}
}