/******************************************************************************* * 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.project.server; import com.google.common.io.ByteStreams; import org.eclipse.che.api.core.ConflictException; import org.eclipse.che.api.core.ForbiddenException; import org.eclipse.che.api.core.NotFoundException; import org.eclipse.che.api.core.ServerException; import org.eclipse.che.api.core.model.project.SourceStorage; import org.eclipse.che.api.core.model.project.type.Attribute; import org.eclipse.che.api.core.notification.EventService; import org.eclipse.che.api.core.rest.ApiExceptionMapper; import org.eclipse.che.api.core.rest.HttpJsonRequest; import org.eclipse.che.api.core.rest.HttpJsonRequestFactory; import org.eclipse.che.api.core.rest.HttpJsonResponse; import org.eclipse.che.api.core.rest.shared.dto.Link; import org.eclipse.che.api.core.util.LineConsumerFactory; import org.eclipse.che.api.core.util.ValueHolder; import org.eclipse.che.api.project.server.handlers.CreateProjectHandler; import org.eclipse.che.api.project.server.handlers.ProjectHandlerRegistry; import org.eclipse.che.api.project.server.importer.ProjectImporter; import org.eclipse.che.api.project.server.importer.ProjectImporterRegistry; import org.eclipse.che.api.project.server.type.AttributeValue; import org.eclipse.che.api.project.server.type.Constant; import org.eclipse.che.api.project.server.type.ProjectTypeConstraintException; import org.eclipse.che.api.project.server.type.ProjectTypeDef; import org.eclipse.che.api.project.server.type.ProjectTypeRegistry; import org.eclipse.che.api.project.server.type.ReadonlyValueProvider; import org.eclipse.che.api.project.server.type.ValueProviderFactory; import org.eclipse.che.api.project.server.type.ValueStorageException; import org.eclipse.che.api.project.shared.dto.CopyOptions; import org.eclipse.che.api.project.shared.dto.ItemReference; import org.eclipse.che.api.project.shared.dto.MoveOptions; import org.eclipse.che.api.project.shared.dto.SourceEstimation; import org.eclipse.che.api.project.shared.dto.TreeElement; import org.eclipse.che.api.user.server.spi.UserDao; import org.eclipse.che.api.vfs.Path; import org.eclipse.che.api.vfs.VirtualFile; import org.eclipse.che.api.vfs.impl.file.DefaultFileWatcherNotificationHandler; import org.eclipse.che.api.vfs.impl.file.FileTreeWatcher; import org.eclipse.che.api.vfs.impl.file.FileWatcherNotificationHandler; import org.eclipse.che.api.vfs.impl.file.LocalVirtualFileSystemProvider; import org.eclipse.che.api.vfs.search.impl.FSLuceneSearcherProvider; import org.eclipse.che.api.vfs.watcher.FileWatcherManager; import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto; import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto; import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto; import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto; import org.eclipse.che.commons.lang.IoUtil; import org.eclipse.che.commons.lang.ws.rs.ExtMediaType; import org.eclipse.che.commons.subject.SubjectImpl; import org.eclipse.che.commons.test.mockito.answer.SelfReturningAnswer; import org.eclipse.che.dto.server.DtoFactory; import org.everrest.core.ApplicationContext; import org.everrest.core.ResourceBinder; import org.everrest.core.impl.ContainerResponse; import org.everrest.core.impl.EverrestConfiguration; import org.everrest.core.impl.EverrestProcessor; import org.everrest.core.impl.ProviderBinder; import org.everrest.core.impl.RequestDispatcher; import org.everrest.core.impl.RequestHandlerImpl; import org.everrest.core.impl.ResourceBinderImpl; import org.everrest.core.tools.ByteArrayContainerResponseWriter; import org.everrest.core.tools.DependencySupplierImpl; import org.everrest.core.tools.ResourceLauncher; import org.junit.Assert; import org.mockito.Mock; import org.mockito.testng.MockitoTestNGListener; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Listeners; import org.testng.annotations.Test; import javax.ws.rs.core.Application; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.nio.charset.Charset; import java.nio.file.PathMatcher; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import static java.lang.String.format; import static java.util.Collections.singletonList; import static javax.ws.rs.HttpMethod.DELETE; import static javax.ws.rs.HttpMethod.GET; import static javax.ws.rs.HttpMethod.POST; import static javax.ws.rs.HttpMethod.PUT; import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static javax.ws.rs.core.MediaType.TEXT_PLAIN; import static org.eclipse.che.commons.lang.ws.rs.ExtMediaType.APPLICATION_ZIP; import static org.everrest.core.ApplicationContext.anApplicationContext; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEqualsNoOrder; import static org.testng.Assert.assertNotNull; /** * @author andrew00x * @author Eugene Voevodin * @author Artem Zatsarynnyi * @author Dmitry Shnurenko */ @Listeners(value = {MockitoTestNGListener.class}) public class ProjectServiceTest { private static final String CONTENT_TYPE = "Content-Type"; private static final String vfsUser = "dev"; protected final static String FS_PATH = "target/fss"; protected final static String INDEX_PATH = "target/fss_index"; private static final String URL_ENCODED_QUOTES = "%22"; private static final String URL_ENCODED_SPACE = "%20"; private static final String URL_ENCODED_BACKSLASH = "%5C"; private static final String URL_ENCODED_ASTERISK = "%2A"; private static final String AND_OPERATOR = "AND"; private static final String NOT_OPERATOR = "NOT"; private static final String EXCLUDE_SEARCH_PATH = ".codenvy"; private ProjectManager pm; private ResourceLauncher launcher; private ProjectHandlerRegistry phRegistry; private ProjectServiceLinksInjector projectServiceLinksInjector; private org.eclipse.che.commons.env.EnvironmentContext env; private List<ProjectConfigDto> projects; @Mock private UserDao userDao; @Mock private WorkspaceDto usersWorkspaceMock; @Mock private WorkspaceConfigDto workspaceConfigMock; @Mock private HttpJsonRequestFactory httpJsonRequestFactory; @Mock private HttpJsonResponse httpJsonResponse; @Mock private FileWatcherManager fileWatcherManager; protected LocalVirtualFileSystemProvider vfsProvider; private ProjectImporterRegistry importerRegistry; protected ProjectRegistry projectRegistry; protected ProjectTypeRegistry ptRegistry; @BeforeMethod public void setUp() throws Exception { WorkspaceProjectsSyncer workspaceHolder = new WsAgentTestBase.TestWorkspaceHolder(); File root = new File(FS_PATH); if (root.exists()) { IoUtil.deleteRecursive(root); } root.mkdir(); File indexDir = new File(INDEX_PATH); if (indexDir.exists()) { IoUtil.deleteRecursive(indexDir); } indexDir.mkdir(); Set<PathMatcher> filters = new HashSet<>(); filters.add(path -> { for (java.nio.file.Path pathElement : path) { if (pathElement == null || EXCLUDE_SEARCH_PATH.equals(pathElement.toString())) { return true; } } return false; }); FSLuceneSearcherProvider sProvider = new FSLuceneSearcherProvider(indexDir, filters); vfsProvider = new LocalVirtualFileSystemProvider(root, sProvider); final EventService eventService = new EventService(); // PTs for test ProjectTypeDef chuck = new ProjectTypeDef("chuck_project_type", "chuck_project_type", true, false) { { addConstantDefinition("x", "attr description", new AttributeValue(Arrays.asList("a", "b"))); } }; Set<ProjectTypeDef> projectTypes = new HashSet<>(); final LocalProjectType myProjectType = new LocalProjectType("my_project_type", "my project type"); projectTypes.add(myProjectType); projectTypes.add(new LocalProjectType("module_type", "module type")); projectTypes.add(chuck); ptRegistry = new ProjectTypeRegistry(projectTypes); phRegistry = new ProjectHandlerRegistry(new HashSet<>()); importerRegistry = new ProjectImporterRegistry(Collections.<ProjectImporter>emptySet()); projectServiceLinksInjector = new ProjectServiceLinksInjector(); projectRegistry = new ProjectRegistry(workspaceHolder, vfsProvider, ptRegistry, phRegistry, eventService); projectRegistry.initProjects(); FileWatcherNotificationHandler fileWatcherNotificationHandler = new DefaultFileWatcherNotificationHandler(vfsProvider); FileTreeWatcher fileTreeWatcher = new FileTreeWatcher(root, new HashSet<>(), fileWatcherNotificationHandler); pm = new ProjectManager(vfsProvider, ptRegistry, projectRegistry, phRegistry, importerRegistry, fileWatcherNotificationHandler, fileTreeWatcher, workspaceHolder, fileWatcherManager); pm.initWatcher(); HttpJsonRequest httpJsonRequest = mock(HttpJsonRequest.class, new SelfReturningAnswer()); //List<ProjectConfigDto> modules = new ArrayList<>(); projects = new ArrayList<>(); addMockedProjectConfigDto(myProjectType, "my_project"); when(httpJsonRequestFactory.fromLink(any())).thenReturn(httpJsonRequest); when(httpJsonRequest.request()).thenReturn(httpJsonResponse); when(httpJsonResponse.asDto(WorkspaceDto.class)).thenReturn(usersWorkspaceMock); when(usersWorkspaceMock.getConfig()).thenReturn(workspaceConfigMock); when(workspaceConfigMock.getProjects()).thenReturn(projects); // verify(httpJsonRequestFactory).fromLink(eq(DtoFactory.newDto(Link.class) // .withHref(apiEndpoint + "/workspace/" + workspace + "/project") // .withMethod(PUT))); DependencySupplierImpl dependencies = new DependencySupplierImpl(); dependencies.addInstance(ProjectTypeRegistry.class, ptRegistry); dependencies.addInstance(UserDao.class, userDao); dependencies.addInstance(ProjectManager.class, pm); dependencies.addInstance(ProjectImporterRegistry.class, importerRegistry); dependencies.addInstance(ProjectHandlerRegistry.class, phRegistry); dependencies.addInstance(EventService.class, eventService); dependencies.addInstance(ProjectServiceLinksInjector.class, projectServiceLinksInjector); ResourceBinder resources = new ResourceBinderImpl(); ProviderBinder providers = ProviderBinder.getInstance(); EverrestProcessor processor = new EverrestProcessor(new EverrestConfiguration(), dependencies, new RequestHandlerImpl(new RequestDispatcher(resources), providers), null); launcher = new ResourceLauncher(processor); processor.addApplication(new Application() { @Override public Set<Class<?>> getClasses() { return java.util.Collections.<Class<?>>singleton(ProjectService.class); } @Override public Set<Object> getSingletons() { return new HashSet<>(Arrays.asList(new ApiExceptionMapper())); } }); ApplicationContext.setCurrent(anApplicationContext().withProviders(providers).build()); env = org.eclipse.che.commons.env.EnvironmentContext.getCurrent(); } @AfterMethod public void tearDown() throws Exception { pm.stop(); } private void addMockedProjectConfigDto(org.eclipse.che.api.project.server.type.ProjectTypeDef myProjectType, String projectName) throws ForbiddenException, ServerException, NotFoundException, ConflictException { final ProjectConfigDto testProjectConfigMock = mock(ProjectConfigDto.class); when(testProjectConfigMock.getPath()).thenReturn("/" + projectName); when(testProjectConfigMock.getName()).thenReturn(projectName); when(testProjectConfigMock.getDescription()).thenReturn("my test project"); when(testProjectConfigMock.getType()).thenReturn("my_project_type"); when(testProjectConfigMock.getSource()).thenReturn(DtoFactory.getInstance().createDto(SourceStorageDto.class)); // when(testProjectConfigMock.getModules()).thenReturn(modules); // when(testProjectConfigMock.findModule(anyString())).thenReturn(testProjectConfigMock); Map<String, List<String>> attr = new HashMap<>(); for (Attribute attribute : myProjectType.getAttributes()) { if (attribute instanceof Constant) { attr.put(attribute.getName(), attribute.getValue().getList()); } } when(testProjectConfigMock.getAttributes()).thenReturn(attr); projects.add(testProjectConfigMock); pm.createProject(testProjectConfigMock, null); } @Test @SuppressWarnings("unchecked") public void testGetProjects() throws Exception { List<RegisteredProject> p = pm.getProjects(); assertEquals(p.size(), 1); vfsProvider.getVirtualFileSystem().getRoot().createFolder("not_project"); // to refresh projectRegistry.initProjects(); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); List<ProjectConfigDto> result = (List<ProjectConfigDto>)response.getEntity(); assertNotNull(result); assertEquals(result.size(), 2); int good, bad; if (result.get(0).getName().equals("my_project")) { good = 0; bad = 1; } else { good = 1; bad = 0; } ProjectConfigDto projectDescriptor = result.get(good); assertEquals(projectDescriptor.getName(), "my_project"); assertEquals(projectDescriptor.getDescription(), "my test project"); assertEquals(projectDescriptor.getType(), "my_project_type"); ProjectConfigDto badProject = result.get(bad); assertEquals(badProject.getName(), "not_project"); assertNotNull(badProject.getProblems()); } @Test public void testGetProject() throws Exception { ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/my_project", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); ProjectConfigDto result = (ProjectConfigDto)response.getEntity(); assertNotNull(result); assertEquals(result.getDescription(), "my test project"); assertEquals(result.getType(), "my_project_type"); Map<String, List<String>> attributes = result.getAttributes(); assertNotNull(attributes); assertEquals(attributes.size(), 1); assertEquals(attributes.get("my_attribute"), singletonList("attribute value 1")); validateProjectLinks(result); } @Test public void testGetNotValidProject() throws Exception { //MountPoint mountPoint = pm.getProjectsRoot(workspace).getVirtualFile().getMountPoint(); vfsProvider.getVirtualFileSystem().getRoot().createFolder("not_project"); // to refresh projectRegistry.initProjects(); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/not_project", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); ProjectConfigDto badProject = (ProjectConfigDto)response.getEntity(); assertNotNull(badProject); assertEquals(badProject.getName(), "not_project"); assertNotNull(badProject.getProblems()); assertTrue(badProject.getProblems().size() > 0); assertEquals(11, badProject.getProblems().get(0).getCode()); validateProjectLinks(badProject); } @Test public void testGetProjectCheckUserPermissions() throws Exception { // Without roles Collections.<String>emptySet() should get default set of permissions env.setSubject(new SubjectImpl(vfsUser, vfsUser, "dummy_token", false)); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/my_project", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); ProjectConfigDto result = (ProjectConfigDto)response.getEntity(); assertNotNull(result); } @Test public void testGetProjectInvalidPath() throws Exception { ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/my_project_invalid", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 404); } @Test public void testCreateProject() throws Exception { final String projectName = "new_project"; final String projectType = "testCreateProject"; phRegistry.register(createProjectHandlerFor(projectName, projectType)); Map<String, List<String>> headers = new HashMap<>(); headers.put("Content-Type", singletonList(APPLICATION_JSON)); ProjectTypeDef pt = new ProjectTypeDef("testCreateProject", "my project type", true, false) { { addConstantDefinition("new_project_attribute", "attr description", "to be or not to be"); } }; ptRegistry.registerProjectType(pt); Map<String, List<String>> attributeValues = new LinkedHashMap<>(); attributeValues.put("new_project_attribute", singletonList("to be or not to be")); final ProjectConfigDto newProjectConfig = DtoFactory.getInstance().createDto(ProjectConfigDto.class) .withPath("/new_project") .withName(projectName) .withDescription("new project") .withType(projectType) .withAttributes(attributeValues) .withSource(DtoFactory.getInstance().createDto(SourceStorageDto.class)); projects.add(newProjectConfig); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project", "http://localhost:8080/api", headers, DtoFactory.getInstance().toJson(newProjectConfig).getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); ProjectConfigDto result = (ProjectConfigDto)response.getEntity(); assertNotNull(result); assertEquals(result.getName(), projectName); assertEquals(result.getPath(), "/new_project"); assertEquals(result.getDescription(), newProjectConfig.getDescription()); assertEquals(result.getType(), newProjectConfig.getType()); assertEquals(result.getType(), projectType); Map<String, List<String>> attributes = result.getAttributes(); assertNotNull(attributes); assertEquals(attributes.size(), 1); assertEquals(attributes.get("new_project_attribute"), singletonList("to be or not to be")); validateProjectLinks(result); RegisteredProject project = pm.getProject("new_project"); assertNotNull(project); //ProjectConfig config = project.getConfig(); assertEquals(project.getDescription(), newProjectConfig.getDescription()); assertEquals(project.getProjectType().getId(), newProjectConfig.getType()); String attributeVal = project.getAttributeEntries().get("new_project_attribute").getString(); assertNotNull(attributeVal); assertEquals(attributeVal, "to be or not to be"); assertNotNull(project.getBaseFolder().getChild("a")); assertNotNull(project.getBaseFolder().getChild("b")); assertNotNull(project.getBaseFolder().getChild("test.txt")); } @Test public void testCreateBatchProjects() throws Exception { //prepare first project final String projectName1 = "testProject1"; final String projectTypeId1 = "testProjectType1"; final String projectPath1 = "/testProject1"; createTestProjectType(projectTypeId1); phRegistry.register(createProjectHandlerFor(projectName1, projectTypeId1)); //prepare inner project final String innerProjectName = "innerProject"; final String innerProjectTypeId = "testProjectType2"; final String innerProjectPath = "/testProject1/innerProject"; createTestProjectType(innerProjectTypeId); phRegistry.register(createProjectHandlerFor(innerProjectName, innerProjectTypeId)); //prepare project to import final String importProjectName = "testImportProject"; final String importProjectTypeId = "testImportProjectType"; final String importProjectPath = "/testImportProject"; final String importType = "importType"; final String[] paths = {"a", "b", "test.txt"}; final List<String> children = new ArrayList<>(Arrays.asList(paths)); registerImporter(importType, prepareZipArchiveBasedOn(children)); createTestProjectType(importProjectTypeId); Map<String, List<String>> headers = new HashMap<>(); headers.put("Content-Type", singletonList(APPLICATION_JSON)); try (InputStream content = getClass().getResourceAsStream("batchNewProjectConfigs.json")) { ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/batch", "http://localhost:8080/api", headers, ByteStreams.toByteArray(content), null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); final List<ProjectConfigDto> result = (List<ProjectConfigDto>)response.getEntity(); assertNotNull(result); assertEquals(result.size(), 3); final ProjectConfigDto importProjectConfig = result.get(0); checkProjectIsCreated(importProjectName, importProjectPath, importProjectTypeId, importProjectConfig); final ProjectConfigDto config1 = result.get(1); checkProjectIsCreated(projectName1, projectPath1, projectTypeId1, config1); final ProjectConfigDto innerProjectConfig = result.get(2); checkProjectIsCreated(innerProjectName, innerProjectPath, innerProjectTypeId, innerProjectConfig); } } @Test public void testUpdateProject() throws Exception { Map<String, List<String>> headers = new HashMap<>(); headers.put("Content-Type", singletonList(APPLICATION_JSON)); ProjectTypeDef pt = new ProjectTypeDef("testUpdateProject", "my project type", true, false) { }; ptRegistry.registerProjectType(pt); pm.createProject(DtoFactory.getInstance().createDto(ProjectConfigDto.class).withDescription("created project").withType( "testUpdateProject").withPath("/testUpdateProject"), null); Map<String, List<String>> attributeValues = new LinkedHashMap<>(); attributeValues.put("my_attribute", singletonList("to be or not to be")); ProjectConfigDto descriptor = DtoFactory.getInstance().createDto(ProjectConfigDto.class) .withName("module1") .withType("testUpdateProject") .withDescription("updated project") .withAttributes(attributeValues); ContainerResponse response = launcher.service(PUT, "http://localhost:8080/api/project/testUpdateProject", "http://localhost:8080/api", headers, DtoFactory.getInstance().toJson(descriptor).getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); RegisteredProject project = pm.getProject("/testUpdateProject"); assertNotNull(project); //ProjectConfig config = project.getConfig(); assertEquals(project.getDescription(), "updated project"); assertEquals(project.getProjectType().getId(), "testUpdateProject"); } @Test public void testUpdateBadProject() throws Exception { //MountPoint mountPoint = pm.getProjectsRoot(workspace).getVirtualFile().getMountPoint(); //mountPoint.getRoot().createFolder("not_project"); pm.getProjectsRoot().createFolder("not_project"); projectRegistry.initProjects(); Map<String, List<String>> headers = new HashMap<>(); headers.put("Content-Type", singletonList(APPLICATION_JSON)); Map<String, List<String>> attributeValues = new LinkedHashMap<>(); attributeValues.put("my_attribute", singletonList("to be or not to be")); ProjectConfigDto descriptor = DtoFactory.getInstance().createDto(ProjectConfigDto.class) .withType("my_project_type") .withDescription("updated project") .withAttributes(attributeValues); final ProjectConfigDto newProjectConfig = DtoFactory.getInstance().createDto(ProjectConfigDto.class) .withPath("/not_project") .withName("not_project") .withDescription("updated project") .withType("my_project_type") .withAttributes(attributeValues) .withSource(DtoFactory.getInstance().createDto(SourceStorageDto.class)); projects.add(newProjectConfig); ContainerResponse response = launcher.service(PUT, "http://localhost:8080/api/project/not_project", "http://localhost:8080/api", headers, DtoFactory.getInstance().toJson(descriptor).getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); RegisteredProject project = pm.getProject("not_project"); assertNotNull(project); //ProjectConfig description = project.getConfig(); assertEquals(project.getDescription(), "updated project"); assertEquals(project.getProjectType().getId(), "my_project_type"); } @Test public void testUpdateProjectInvalidPath() throws Exception { Map<String, List<String>> headers = new HashMap<>(); headers.put("Content-Type", singletonList(APPLICATION_JSON)); Map<String, List<String>> attributeValues = new LinkedHashMap<>(); attributeValues.put("my_attribute", singletonList("to be or not to be")); ProjectConfigDto descriptor = DtoFactory.getInstance().createDto(ProjectConfigDto.class) .withType("my_project_type") .withDescription("updated project") .withAttributes(attributeValues); ContainerResponse response = launcher.service(PUT, "http://localhost:8080/api/project/my_project_invalid", "http://localhost:8080/api", headers, DtoFactory.getInstance().toJson(descriptor).getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 404); } @Test public void testEstimateProject() throws Exception { VirtualFile root = pm.getProjectsRoot().getVirtualFile(); //getVirtualFileSystemRegistry().getProvider("my_ws").getMountPoint(false).getRoot(); root.createFolder("testEstimateProjectGood").createFolder("check"); root.createFolder("testEstimateProjectBad"); String errMessage = "File /check not found"; final ValueProviderFactory vpf1 = projectFolder -> new ReadonlyValueProvider() { @Override public List<String> getValues(String attributeName) throws ValueStorageException { VirtualFileEntry file; try { file = projectFolder.getChild("check"); } catch (ServerException e) { throw new ValueStorageException(e.getMessage()); } if (file == null) { throw new ValueStorageException(errMessage); } return (List<String>)singletonList("checked"); } }; ProjectTypeDef pt = new ProjectTypeDef("testEstimateProjectPT", "my testEstimateProject type", true, false) { { addVariableDefinition("calculated_attribute", "attr description", true, vpf1); addVariableDefinition("my_property_1", "attr description", true); addVariableDefinition("my_property_2", "attr description", false); } }; ptRegistry.registerProjectType(pt); ContainerResponse response = launcher.service(GET, format("http://localhost:8080/api/project/estimate/%s?type=%s", "testEstimateProjectGood", "testEstimateProjectPT"), "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); //noinspection unchecked SourceEstimation result = (SourceEstimation)response.getEntity(); assertTrue(result.isMatched()); assertEquals(result.getAttributes().size(), 1); assertEquals(result.getAttributes().get("calculated_attribute").get(0), "checked"); // if project not matched response = launcher.service(GET, format("http://localhost:8080/api/project/estimate/%s?type=%s", "testEstimateProjectBad", "testEstimateProjectPT"), "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); //noinspection unchecked result = (SourceEstimation)response.getEntity(); assertFalse(result.isMatched()); assertEquals(result.getAttributes().size(), 0); } @Test public void testResolveSources() throws Exception { VirtualFile root = pm.getProjectsRoot().getVirtualFile(); root.createFolder("testEstimateProjectGood").createFolder("check"); root.createFolder("testEstimateProjectBad"); final ValueProviderFactory vpf1 = projectFolder -> new ReadonlyValueProvider() { @Override public List<String> getValues(String attributeName) throws ValueStorageException { VirtualFileEntry file; try { file = projectFolder.getChild("check"); } catch (ServerException e) { throw new ValueStorageException(e.getMessage()); } if (file == null) { throw new ValueStorageException("Check not found"); } return (List<String>)singletonList("checked"); } }; ProjectTypeDef pt = new ProjectTypeDef("testEstimateProjectPT", "my testEstimateProject type", true, false) { { addVariableDefinition("calculated_attribute", "attr description", true, vpf1); addVariableDefinition("my_property_1", "attr description", true); addVariableDefinition("my_property_2", "attr description", false); } }; ptRegistry.registerProjectType(pt); ContainerResponse response = launcher.service(GET, format("http://localhost:8080/api/project/resolve/%s", "testEstimateProjectGood"), "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); List<SourceEstimation> result = (List<SourceEstimation>)response.getEntity(); assertTrue(result.size() > 0); boolean m = false; for (SourceEstimation est : result) { if (est.getType().equals("testEstimateProjectPT")) { assertTrue(est.isMatched()); m = true; } } assertTrue(m); } @Test public void testImportProject() throws Exception { ByteArrayOutputStream bout = new ByteArrayOutputStream(); ZipOutputStream zipOut = new ZipOutputStream(bout); zipOut.putNextEntry(new ZipEntry("folder1/")); zipOut.putNextEntry(new ZipEntry("folder1/file1.txt")); zipOut.write("to be or not to be".getBytes(Charset.defaultCharset())); zipOut.close(); final InputStream zip = new ByteArrayInputStream(bout.toByteArray()); final String importType = "_123_"; registerImporter(importType, zip); final String myType = "chuck_project_type"; final ProjectConfigDto newProjectConfig = DtoFactory.getInstance().createDto(ProjectConfigDto.class) .withPath("/new_project") .withName("new_project") .withDescription("import test") .withType(myType); projects.add(newProjectConfig); Map<String, List<String>> headers = new HashMap<>(); headers.put("Content-Type", singletonList(APPLICATION_JSON)); String json = "{\n" + " \"location\": null,\n" + " \"type\": \"%s\"\n" + "}"; byte[] b = format(json, importType).getBytes(Charset.defaultCharset()); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/import/new_project", "http://localhost:8080/api", headers, b, null); assertEquals(response.getStatus(), 204); RegisteredProject newProject = pm.getProject("new_project"); assertNotNull(newProject); //assertNotNull(newProject.getConfig()); } private void registerImporter(String importType, InputStream zip) throws Exception { final ValueHolder<FolderEntry> folderHolder = new ValueHolder<>(); importerRegistry.register(new ProjectImporter() { @Override public String getId() { return importType; } @Override public boolean isInternal() { return false; } @Override public String getDescription() { return "Chuck importer"; } @Override public void importSources(FolderEntry baseFolder, SourceStorage storage) throws ConflictException, ServerException, ForbiddenException { importSources(baseFolder, storage, LineConsumerFactory.NULL); } @Override public void importSources(FolderEntry baseFolder, SourceStorage storage, LineConsumerFactory importOutputConsumerFactory) throws ConflictException, ServerException, ForbiddenException { // Don't really use location in this test. baseFolder.getVirtualFile().unzip(zip, true, 0); folderHolder.set(baseFolder); } @Override public ImporterCategory getCategory() { return ImporterCategory.ARCHIVE; } }); } @Test public void testCreateFile() throws Exception { String myContent = "to be or not to be"; ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/file/my_project?name=test.txt", "http://localhost:8080/api", null, myContent.getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); ItemReference fileItem = (ItemReference)response.getEntity(); assertEquals(fileItem.getType(), "file"); // assertEquals(fileItem.getMediaType(), TEXT_PLAIN); assertEquals(fileItem.getName(), "test.txt"); assertEquals(fileItem.getPath(), "/my_project/test.txt"); validateFileLinks(fileItem); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create("http://localhost:8080/api/project/file/my_project/test.txt")); VirtualFileEntry file = pm.getProject("my_project").getBaseFolder().getChild("test.txt"); Assert.assertTrue(file.isFile()); FileEntry _file = (FileEntry)file; //assertEquals(_file.getMediaType(), TEXT_PLAIN); assertEquals(new String(_file.contentAsBytes()), myContent); } @Test public void testGetFileContent() throws Exception { String myContent = "to be or not to be"; pm.getProject("my_project").getBaseFolder().createFile("test.txt", myContent.getBytes(Charset.defaultCharset())); ByteArrayContainerResponseWriter writer = new ByteArrayContainerResponseWriter(); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/file/my_project/test.txt", "http://localhost:8080/api", null, null, writer, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); assertEquals(response.getContentType().toString(), TEXT_PLAIN); assertEquals(new String(writer.getBody()), myContent); } @Test public void testUpdateFileContent() throws Exception { String myContent = "<test>hello</test>"; pm.getProject("my_project").getBaseFolder().createFile("test.xml", "to be or not to be".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(PUT, "http://localhost:8080/api/project/file/my_project/test.xml", "http://localhost:8080/api", null, myContent.getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); VirtualFileEntry file = pm.getProject("my_project").getBaseFolder().getChild("test.xml"); Assert.assertTrue(file.isFile()); FileEntry _file = (FileEntry)file; assertEquals(new String(_file.contentAsBytes()), myContent); } @Test public void testCreateFolder() throws Exception { ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/folder/my_project/test", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); ItemReference fileItem = (ItemReference)response.getEntity(); assertEquals(fileItem.getName(), "test"); assertEquals(fileItem.getPath(), "/my_project/test"); validateFolderLinks(fileItem); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create("http://localhost:8080/api/project/children/my_project/test")); VirtualFileEntry folder = pm.getProject("my_project").getBaseFolder().getChild("test"); Assert.assertTrue(folder.isFolder()); } // any folder created in the root of the workspace automatically becomes project @Test public void testCreateFolderInRoot() throws Exception { String folder = "my_folder"; ContainerResponse response = launcher.service(POST, format("http://localhost:8080/api/project/folder/%s", folder), "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); ItemReference fileItem = (ItemReference)response.getEntity(); assertEquals(fileItem.getType(), "project"); assertEquals(fileItem.getName(), folder); assertEquals(fileItem.getPath(), "/" + folder); validateFolderLinks(fileItem); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create(format("http://localhost:8080/api/project/children/%s", folder))); } @Test public void testCreatePath() throws Exception { ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/folder/my_project/a/b/c", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create("http://localhost:8080/api/project/children/my_project/a/b/c")); VirtualFileEntry folder = pm.getProject("my_project").getBaseFolder().getChild("a/b/c"); Assert.assertTrue(folder.isFolder()); } @Test public void testDeleteFile() throws Exception { pm.getProject("my_project").getBaseFolder().createFile("test.txt", "to be or not to be".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(DELETE, "http://localhost:8080/api/project/my_project/test.txt", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 204, "Error: " + response.getEntity()); Assert.assertNull(pm.getProject("my_project").getBaseFolder().getChild("test.txt")); } @Test public void testDeleteFolder() throws Exception { pm.getProject("my_project").getBaseFolder().createFolder("test"); ContainerResponse response = launcher.service(DELETE, "http://localhost:8080/api/project/my_project/test", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 204, "Error: " + response.getEntity()); Assert.assertNull(pm.getProject("my_project").getBaseFolder().getChild("test")); } @Test public void testDeletePath() throws Exception { pm.getProject("my_project").getBaseFolder().createFolder("a/b/c"); ContainerResponse response = launcher.service(DELETE, "http://localhost:8080/api/project/my_project/a/b/c", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 204, "Error: " + response.getEntity()); Assert.assertNull(pm.getProject("my_project").getBaseFolder().getChild("a/b/c")); } @Test public void testDeleteInvalidPath() throws Exception { ContainerResponse response = launcher.service(DELETE, "http://localhost:8080/api/project/my_project/a/b/c", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 204); assertNotNull(pm.getProject("my_project")); } @Test(expectedExceptions = NotFoundException.class) public void testDeleteProject() throws Exception { ContainerResponse response = launcher.service(DELETE, "http://localhost:8080/api/project/my_project", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 204, "Error: " + response.getEntity()); pm.getProject("my_project"); } @Test public void testDeleteProjectsConcurrently() throws Exception { int threadNumber = 5 * (Runtime.getRuntime().availableProcessors() + 1); ExecutorService executor = Executors.newFixedThreadPool(threadNumber); CountDownLatch countDownLatch = new CountDownLatch(threadNumber); List<Future<ContainerResponse>> futures = new LinkedList<>(); for (int i = 0; i < threadNumber; i++) { addMockedProjectConfigDto(ptRegistry.getProjectType("my_project_type"), "my_project_name" + i); } IntStream.range(0, threadNumber).forEach( i -> { futures.add(executor.submit(() -> { countDownLatch.countDown(); countDownLatch.await(); try { return launcher.service(DELETE, "http://localhost:8080/api/project/my_project_name" + i, "http://localhost:8080/api", null, null, null); } catch (Exception e) { throw new IllegalStateException(e); } })); } ); boolean isNotDone; do { isNotDone = false; for (Future<ContainerResponse> future : futures) { if (!future.isDone()) { isNotDone = true; } } } while (isNotDone); for (Future<ContainerResponse> future : futures) { assertEquals(future.get().getStatus(), 204, "Error: " + future.get().getEntity()); } executor.shutdown(); } @Test public void testCopyFile() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b/c"); ((FolderEntry)myProject.getBaseFolder().getChild("a/b")) .createFile("test.txt", "to be or not no be".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/copy/my_project/a/b/test.txt?to=/my_project/a/b/c", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create("http://localhost:8080/api/project/file/my_project/a/b/c/test.txt")); assertNotNull(myProject.getBaseFolder().getChild("a/b/c/test.txt")); // new assertNotNull(myProject.getBaseFolder().getChild("a/b/test.txt")); // old } @Test public void testCopyFileWithRename() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b/c"); ((FolderEntry)myProject.getBaseFolder().getChild("a/b")) .createFile("test.txt", "to be or not no be".getBytes(Charset.defaultCharset())); Map<String, List<String>> headers = new HashMap<>(); headers.put(CONTENT_TYPE, singletonList(APPLICATION_JSON)); CopyOptions descriptor = DtoFactory.getInstance().createDto(CopyOptions.class); descriptor.setName("copyOfTest.txt"); descriptor.setOverWrite(false); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/copy/my_project/a/b/test.txt?to=/my_project/a/b/c", "http://localhost:8080/api", headers, DtoFactory.getInstance().toJson(descriptor).getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create("http://localhost:8080/api/project/file/my_project/a/b/c/copyOfTest.txt")); assertNotNull(myProject.getBaseFolder().getChild("a/b/c/copyOfTest.txt")); // new assertNotNull(myProject.getBaseFolder().getChild("a/b/test.txt")); // old } @Test public void testCopyFileWithRenameAndOverwrite() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b/c"); // File names String originFileName = "test.txt"; String destinationFileName = "overwriteMe.txt"; // File contents String originContent = "to be or not no be"; String overwrittenContent = "that is the question"; ((FolderEntry)myProject.getBaseFolder().getChild("a/b")) .createFile(originFileName, originContent.getBytes(Charset.defaultCharset())); ((FolderEntry)myProject.getBaseFolder().getChild("a/b/c")).createFile(destinationFileName, overwrittenContent.getBytes(Charset.defaultCharset())); Map<String, List<String>> headers = new HashMap<>(); headers.put(CONTENT_TYPE, singletonList(APPLICATION_JSON)); CopyOptions descriptor = DtoFactory.getInstance().createDto(CopyOptions.class); descriptor.setName(destinationFileName); descriptor.setOverWrite(true); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/copy/my_project/a/b/" + originFileName + "?to=/my_project/a/b/c", "http://localhost:8080/api", headers, DtoFactory.getInstance().toJson(descriptor).getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create("http://localhost:8080/api/project/file/my_project/a/b/c/" + destinationFileName)); assertNotNull(myProject.getBaseFolder().getChild("a/b/c/" + destinationFileName)); // new assertNotNull(myProject.getBaseFolder().getChild("a/b/" + originFileName)); // old Scanner inputStreamScanner = null; String theFirstLineFromDestinationFile; try { inputStreamScanner = new Scanner( myProject.getBaseFolder().getChild("a/b/c/" + destinationFileName).getVirtualFile().getContent()); theFirstLineFromDestinationFile = inputStreamScanner.nextLine(); // destination should contain original file's content assertEquals(theFirstLineFromDestinationFile, originContent); } catch (ForbiddenException | ServerException e) { Assert.fail(e.getMessage()); } finally { if (inputStreamScanner != null) { inputStreamScanner.close(); } } } @Test public void testCopyFolder() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b/c"); ((FolderEntry)myProject.getBaseFolder().getChild("a/b")) .createFile("test.txt", "to be or not no be".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/copy/my_project/a/b?to=/my_project/a/b/c", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create("http://localhost:8080/api/project/children/my_project/a/b/c/b")); assertNotNull(myProject.getBaseFolder().getChild("a/b/test.txt")); assertNotNull(myProject.getBaseFolder().getChild("a/b/c/b/test.txt")); } @Test public void testCopyFolderWithRename() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b/c"); ((FolderEntry)myProject.getBaseFolder().getChild("a/b")) .createFile("test.txt", "to be or not no be".getBytes(Charset.defaultCharset())); // new name for folder final String renamedFolder = "renamedFolder"; Map<String, List<String>> headers = new HashMap<>(); headers.put(CONTENT_TYPE, singletonList(APPLICATION_JSON)); CopyOptions descriptor = DtoFactory.getInstance().createDto(CopyOptions.class); descriptor.setName(renamedFolder); descriptor.setOverWrite(false); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/copy/my_project/a/b?to=/my_project/a/b/c", "http://localhost:8080/api", headers, DtoFactory.getInstance().toJson(descriptor).getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create( format("http://localhost:8080/api/project/children/my_project/a/b/c/%s", renamedFolder))); assertNotNull(myProject.getBaseFolder().getChild("a/b/test.txt")); assertNotNull(myProject.getBaseFolder().getChild(format("a/b/c/%s/test.txt", renamedFolder))); } @Test public void testCopyFolderWithRenameAndOverwrite() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b/c"); // File names String originFileName = "test.txt"; String destinationFileName = "overwriteMe.txt"; // File contents String originContent = "to be or not no be"; String overwrittenContent = "that is the question"; // new name for folder final String renamedFolder = "renamedFolder"; ((FolderEntry)myProject.getBaseFolder().getChild("a/b")) .createFile(originFileName, originContent.getBytes(Charset.defaultCharset())); ((FolderEntry)myProject.getBaseFolder().getChild("a/b/c")) .createFile(destinationFileName, overwrittenContent.getBytes(Charset.defaultCharset())); Map<String, List<String>> headers = new HashMap<>(); headers.put(CONTENT_TYPE, singletonList(APPLICATION_JSON)); CopyOptions descriptor = DtoFactory.getInstance().createDto(CopyOptions.class); descriptor.setName(renamedFolder); descriptor.setOverWrite(true); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/copy/my_project/a/b?to=/my_project/a/b/c", "http://localhost:8080/api", headers, DtoFactory.getInstance().toJson(descriptor).getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create( format("http://localhost:8080/api/project/children/my_project/a/b/c/%s", renamedFolder))); assertNotNull(myProject.getBaseFolder().getChild("a/b/test.txt")); assertNotNull(myProject.getBaseFolder().getChild(format("a/b/c/%s/test.txt", renamedFolder))); assertEquals(myProject.getBaseFolder().getChild("a/b/test.txt").getName(), myProject.getBaseFolder().getChild(format("a/b/c/%s/%s", renamedFolder, originFileName)).getName()); } @Test public void testMoveFile() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b/c"); ((FolderEntry)myProject.getBaseFolder().getChild("a/b")) .createFile("test.txt", "to be or not no be".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/move/my_project/a/b/test.txt?to=/my_project/a/b/c", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create("http://localhost:8080/api/project/file/my_project/a/b/c/test.txt")); assertNotNull(myProject.getBaseFolder().getChild("a/b/c/test.txt")); // new Assert.assertNull(myProject.getBaseFolder().getChild("a/b/test.txt")); // old } @Test public void testMoveFileWithRename() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b/c"); ((FolderEntry)myProject.getBaseFolder().getChild("a/b")) .createFile("test.txt", "to be or not no be".getBytes(Charset.defaultCharset())); // name for file after move final String destinationName = "copyOfTestForMove.txt"; Map<String, List<String>> headers = new HashMap<>(); headers.put(CONTENT_TYPE, singletonList(APPLICATION_JSON)); MoveOptions descriptor = DtoFactory.getInstance().createDto(MoveOptions.class); descriptor.setName(destinationName); descriptor.setOverWrite(false); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/move/my_project/a/b/test.txt?to=/my_project/a/b/c", "http://localhost:8080/api", headers, DtoFactory.getInstance().toJson(descriptor).getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create( format("http://localhost:8080/api/project/file/my_project/a/b/c/%s", destinationName))); VirtualFileEntry theTargetFile = myProject.getBaseFolder().getChild(format("a/b/c/%s", destinationName)); assertNotNull(theTargetFile); // new } @Test public void testRenameFile() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b"); ((FolderEntry)myProject.getBaseFolder().getChild("a/b")) .createFile("test.txt", "to be or not no be".getBytes(Charset.defaultCharset())); // name for file after move final String destinationName = "copyOfTestForMove.txt"; Map<String, List<String>> headers = new HashMap<>(); headers.put(CONTENT_TYPE, singletonList(APPLICATION_JSON)); MoveOptions descriptor = DtoFactory.getInstance().createDto(MoveOptions.class); descriptor.setName(destinationName); descriptor.setOverWrite(false); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/move/my_project/a/b/test.txt", "http://localhost:8080/api", headers, DtoFactory.getInstance().toJson(descriptor).getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create( format("http://localhost:8080/api/project/file/my_project/a/b/%s", destinationName))); VirtualFileEntry theTargetFile = myProject.getBaseFolder().getChild(format("a/b/%s", destinationName)); assertNotNull(theTargetFile); // new } @Test public void testMoveFileWithRenameAndOverwrite() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b/c"); // File names String originFileName = "test.txt"; String destinationFileName = "overwriteMe.txt"; // File contents String originContent = "to be or not no be"; String overwrittenContent = "that is the question"; ((FolderEntry)myProject.getBaseFolder().getChild("a/b")) .createFile(originFileName, originContent.getBytes(Charset.defaultCharset())); ((FolderEntry)myProject.getBaseFolder().getChild("a/b/c")) .createFile(destinationFileName, overwrittenContent.getBytes(Charset.defaultCharset())); Map<String, List<String>> headers = new HashMap<>(); headers.put(CONTENT_TYPE, singletonList(APPLICATION_JSON)); MoveOptions descriptor = DtoFactory.getInstance().createDto(MoveOptions.class); descriptor.setName(destinationFileName); descriptor.setOverWrite(true); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/move/my_project/a/b/" + originFileName + "?to=/my_project/a/b/c", "http://localhost:8080/api", headers, DtoFactory.getInstance().toJson(descriptor).getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create("http://localhost:8080/api/project/file/my_project/a/b/c/" + destinationFileName)); assertNotNull(myProject.getBaseFolder().getChild("a/b/c/" + destinationFileName)); // new Scanner inputStreamScanner = null; String theFirstLineFromDestinationFile; try { inputStreamScanner = new Scanner( myProject.getBaseFolder().getChild("a/b/c/" + destinationFileName).getVirtualFile().getContent()); theFirstLineFromDestinationFile = inputStreamScanner.nextLine(); // destination should contain original file's content assertEquals(theFirstLineFromDestinationFile, originContent); } catch (ForbiddenException | ServerException e) { Assert.fail(e.getMessage()); } finally { if (inputStreamScanner != null) { inputStreamScanner.close(); } } } @Test public void testMoveFolder() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b/c"); ((FolderEntry)myProject.getBaseFolder().getChild("a/b/c")) .createFile("test.txt", "to be or not no be".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/move/my_project/a/b/c?to=/my_project/a", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create("http://localhost:8080/api/project/children/my_project/a/c")); assertNotNull(myProject.getBaseFolder().getChild("a/c/test.txt")); Assert.assertNull(myProject.getBaseFolder().getChild("a/b/c/test.txt")); Assert.assertNull(myProject.getBaseFolder().getChild("a/b/c")); } @Test public void testMoveFolderWithRename() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b/c"); ((FolderEntry)myProject.getBaseFolder().getChild("a/b")) .createFile("test.txt", "to be or not no be".getBytes(Charset.defaultCharset())); // new name for folder final String renamedFolder = "renamedFolder"; Map<String, List<String>> headers = new HashMap<>(); headers.put(CONTENT_TYPE, singletonList(APPLICATION_JSON)); MoveOptions descriptor = DtoFactory.getInstance().createDto(MoveOptions.class); descriptor.setName(renamedFolder); descriptor.setOverWrite(false); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/copy/my_project/a/b?to=/my_project/a/b/c", "http://localhost:8080/api", headers, DtoFactory.getInstance().toJson(descriptor).getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create( format("http://localhost:8080/api/project/children/my_project/a/b/c/%s", renamedFolder))); assertNotNull(myProject.getBaseFolder().getChild(format("a/b/c/%s/test.txt", renamedFolder))); } @Test public void testRenameFolder() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b"); ((FolderEntry)myProject.getBaseFolder().getChild("a/b")) .createFile("test.txt", "to be or not no be".getBytes(Charset.defaultCharset())); // new name for folder final String renamedFolder = "renamedFolder"; Map<String, List<String>> headers = new HashMap<>(); headers.put(CONTENT_TYPE, singletonList(APPLICATION_JSON)); MoveOptions descriptor = DtoFactory.getInstance().createDto(MoveOptions.class); descriptor.setName(renamedFolder); descriptor.setOverWrite(false); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/move/my_project/a/b", "http://localhost:8080/api", headers, DtoFactory.getInstance().toJson(descriptor).getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create( format("http://localhost:8080/api/project/children/my_project/a/%s", renamedFolder))); assertNotNull(myProject.getBaseFolder().getChild(format("a/%s/test.txt", renamedFolder))); } @Test public void testMoveFolderWithRenameAndOverwrite() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b/c"); // File names String originFileName = "test.txt"; String destinationFileName = "overwriteMe.txt"; // File contents String originContent = "to be or not no be"; String overwritenContent = "that is the question"; // new name for folder final String renamedFolder = "renamedFolder"; ((FolderEntry)myProject.getBaseFolder().getChild("a/b")) .createFile(originFileName, originContent.getBytes(Charset.defaultCharset())); ((FolderEntry)myProject.getBaseFolder().getChild("a/b/c")) .createFile(destinationFileName, overwritenContent.getBytes(Charset.defaultCharset())); Map<String, List<String>> headers = new HashMap<>(); headers.put(CONTENT_TYPE, singletonList(APPLICATION_JSON)); MoveOptions descriptor = DtoFactory.getInstance().createDto(MoveOptions.class); descriptor.setName(renamedFolder); descriptor.setOverWrite(true); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/copy/my_project/a/b?to=/my_project/a/b/c", "http://localhost:8080/api", headers, DtoFactory.getInstance().toJson(descriptor).getBytes(Charset.defaultCharset()), null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create( format("http://localhost:8080/api/project/children/my_project/a/b/c/%s", renamedFolder))); assertNotNull(myProject.getBaseFolder().getChild(format("a/b/c/%s/test.txt", renamedFolder))); } @Test public void testImportZip() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b"); ByteArrayOutputStream bout = new ByteArrayOutputStream(); ZipOutputStream zipOut = new ZipOutputStream(bout); zipOut.putNextEntry(new ZipEntry("folder1/")); zipOut.putNextEntry(new ZipEntry("folder1/file1.txt")); zipOut.write("to be or not to be".getBytes(Charset.defaultCharset())); zipOut.close(); byte[] zip = bout.toByteArray(); Map<String, List<String>> headers = new HashMap<>(); headers.put(CONTENT_TYPE, singletonList(ExtMediaType.APPLICATION_ZIP)); ContainerResponse response = launcher.service(POST, format("http://localhost:8080/api/project/import/my_project/a/b"), "http://localhost:8080/api", headers, zip, null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create("http://localhost:8080/api/project/children/my_project/a/b")); assertNotNull(myProject.getBaseFolder().getChild("a/b/folder1/file1.txt")); } @Test public void testImportZipWithoutSkipFirstLevel() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b"); ByteArrayOutputStream bout = new ByteArrayOutputStream(); ZipOutputStream zipOut = new ZipOutputStream(bout); zipOut.putNextEntry(new ZipEntry("folder1/")); zipOut.putNextEntry(new ZipEntry("folder1/folder2/")); zipOut.putNextEntry(new ZipEntry("folder1/folder2/file1.txt")); zipOut.write("to be or not to be".getBytes(Charset.defaultCharset())); zipOut.close(); byte[] zip = bout.toByteArray(); Map<String, List<String>> headers = new HashMap<>(); headers.put(CONTENT_TYPE, singletonList(ExtMediaType.APPLICATION_ZIP)); ContainerResponse response = launcher.service(POST, "http://localhost:8080/api/project/import/my_project/a/b?skipFirstLevel=false", "http://localhost:8080/api", headers, zip, null); assertEquals(response.getStatus(), 201, "Error: " + response.getEntity()); assertEquals(response.getHttpHeaders().getFirst("Location"), URI.create("http://localhost:8080/api/project/children/my_project/a/b")); assertNotNull(myProject.getBaseFolder().getChild("a/b/folder1/")); assertNotNull(myProject.getBaseFolder().getChild("a/b/folder1/folder2")); assertNotNull(myProject.getBaseFolder().getChild("a/b/folder1/folder2/file1.txt")); } @Test public void testExportZip() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b").createFile("test.txt", "hello".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/export/my_project", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); assertEquals(response.getContentType().toString(), ExtMediaType.APPLICATION_ZIP); } @Test @SuppressWarnings("unchecked") public void testGetChildren() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); FolderEntry a = myProject.getBaseFolder().createFolder("a"); a.createFolder("b"); a.createFile("test.txt", "test".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/children/my_project/a", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); List<ItemReference> result = (List<ItemReference>)response.getEntity(); assertEquals(result.size(), 2); Set<String> names = new LinkedHashSet<>(2); names.addAll(result.stream().map(ItemReference::getName).collect(Collectors.toList())); Assert.assertTrue(names.contains("b")); Assert.assertTrue(names.contains("test.txt")); } @Test @SuppressWarnings("unchecked") public void testGetItem() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); FolderEntry a = myProject.getBaseFolder().createFolder("a"); a.createFolder("b"); a.createFile("test.txt", "test".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/item/my_project/a/b", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); ItemReference result = (ItemReference)response.getEntity(); assertEquals(result.getName(), "b"); response = launcher.service(GET, "http://localhost:8080/api/project/item/my_project/a/test.txt", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); result = (ItemReference)response.getEntity(); assertEquals(result.getType(), "file"); //assertEquals(result.getMediaType(), TEXT_PLAIN); } @Test public void testGetItemWithoutParentProject() throws Exception { FolderEntry a = pm.getProjectsRoot().createFolder("a"); a.createFile("test.txt", "test".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/item/a/test.txt", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); ItemReference result = (ItemReference)response.getEntity(); assertEquals(result.getType(), "file"); //assertEquals(result.getMediaType(), TEXT_PLAIN); } @Test public void testGetMissingItem() throws Exception { ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/item/some_missing_project/a/b", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 404, "Error: " + response.getEntity()); } @Test public void testGetTree() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); FolderEntry a = myProject.getBaseFolder().createFolder("a"); a.createFolder("b/c"); a.createFolder("x/y"); a.createFile("test.txt", "test".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/tree/my_project/a", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); TreeElement tree = (TreeElement)response.getEntity(); ItemReference a_node = tree.getNode(); assertEquals(a_node.getName(), "a"); validateFolderLinks(a_node); List<TreeElement> children = tree.getChildren(); assertNotNull(children); assertEquals(children.size(), 2); Set<String> names = new LinkedHashSet<>(2); for (TreeElement subTree : children) { ItemReference _node = subTree.getNode(); validateFolderLinks(_node); names.add(_node.getName()); Assert.assertTrue(subTree.getChildren().isEmpty()); // default depth is 1 } Assert.assertTrue(names.contains("b")); Assert.assertTrue(names.contains("x")); } @Test public void testGetTreeWithDepth() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); FolderEntry a = myProject.getBaseFolder().createFolder("a"); a.createFolder("b/c"); a.createFolder("x/y"); a.createFile("test.txt", "test".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/tree/my_project/a?depth=2", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); TreeElement tree = (TreeElement)response.getEntity(); ItemReference a_node = tree.getNode(); assertEquals(a_node.getName(), "a"); List<TreeElement> children = tree.getChildren(); assertNotNull(children); Set<String> names = new LinkedHashSet<>(4); for (TreeElement subTree : children) { ItemReference _node = subTree.getNode(); validateFolderLinks(_node); String name = _node.getName(); names.add(name); for (TreeElement subSubTree : subTree.getChildren()) { ItemReference __node = subSubTree.getNode(); validateFolderLinks(__node); names.add(name + "/" + __node.getName()); } } Assert.assertTrue(names.contains("b")); Assert.assertTrue(names.contains("x")); Assert.assertTrue(names.contains("b/c")); Assert.assertTrue(names.contains("x/y")); } @Test public void testGetTreeWithDepthAndIncludeFiles() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); FolderEntry a = myProject.getBaseFolder().createFolder("a"); a.createFolder("b/c"); a.createFolder("x").createFile("test.txt", "test".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/tree/my_project/a?depth=100&includeFiles=true", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); TreeElement tree = (TreeElement)response.getEntity(); ItemReference a_node = tree.getNode(); assertEquals(a_node.getName(), "a"); List<TreeElement> children = tree.getChildren(); assertNotNull(children); Set<String> names = new LinkedHashSet<>(4); for (TreeElement subTree : children) { ItemReference _node = subTree.getNode(); validateFolderLinks(_node); String name = _node.getName(); names.add(name); for (TreeElement subSubTree : subTree.getChildren()) { ItemReference __node = subSubTree.getNode(); if (__node.getType().equals("folder")) { validateFolderLinks(__node); } else if (__node.getType().equals("file")) { validateFileLinks(__node); } names.add(name + "/" + __node.getName()); } } Assert.assertTrue(names.contains("b")); Assert.assertTrue(names.contains("x")); Assert.assertTrue(names.contains("b/c")); Assert.assertTrue(names.contains("x/test.txt")); } @Test public void testGetTreeWithDepthAndIncludeFilesNoFiles() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); FolderEntry a = myProject.getBaseFolder().createFolder("a"); a.createFolder("b/c"); a.createFolder("x"); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/tree/my_project/a?depth=100&includeFiles=true", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); TreeElement tree = (TreeElement)response.getEntity(); ItemReference a_node = tree.getNode(); assertEquals(a_node.getName(), "a"); List<TreeElement> children = tree.getChildren(); assertNotNull(children); Set<String> names = new LinkedHashSet<>(4); for (TreeElement subTree : children) { ItemReference _node = subTree.getNode(); validateFolderLinks(_node); String name = _node.getName(); names.add(name); for (TreeElement subSubTree : subTree.getChildren()) { ItemReference __node = subSubTree.getNode(); validateFolderLinks(__node); names.add(name + "/" + __node.getName()); } } Assert.assertTrue(names.contains("b")); Assert.assertTrue(names.contains("x")); Assert.assertTrue(names.contains("b/c")); Assert.assertFalse(names.contains("x/test.txt")); } @SuppressWarnings("unchecked") @Test public void testSearchByName() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b").createFile("test.txt", "hello".getBytes(Charset.defaultCharset())); myProject.getBaseFolder().createFolder("x/y").createFile("test.txt", "test".getBytes(Charset.defaultCharset())); myProject.getBaseFolder().createFolder("c").createFile("exclude", "test".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/search/my_project?name=test.txt", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); List<ItemReference> result = (List<ItemReference>)response.getEntity(); assertEquals(result.size(), 2); Set<String> paths = new LinkedHashSet<>(2); for (ItemReference itemReference : result) { paths.add(itemReference.getPath()); } Assert.assertTrue(paths.contains("/my_project/a/b/test.txt")); Assert.assertTrue(paths.contains("/my_project/x/y/test.txt")); } @SuppressWarnings("unchecked") @Test public void testSearchByText() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b").createFile("test.txt", "hello".getBytes(Charset.defaultCharset())); myProject.getBaseFolder().createFolder("x/y").createFile("__test.txt", "searchhit".getBytes(Charset.defaultCharset())); myProject.getBaseFolder().createFolder("c").createFile("_test", "searchhit".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/search/my_project?text=searchhit", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); List<ItemReference> result = (List<ItemReference>)response.getEntity(); assertEquals(result.size(), 2); Set<String> paths = new LinkedHashSet<>(1); paths.addAll(result.stream().map(ItemReference::getPath).collect(Collectors.toList())); Assert.assertTrue(paths.contains("/my_project/x/y/__test.txt")); } @SuppressWarnings("unchecked") @Test public void testSearchByTextWhenFileWasNotIndexed() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b").createFile("test.txt", "hello".getBytes(Charset.defaultCharset())); myProject.getBaseFolder().createFolder("x/y").createFile("__test.txt", "searchhit".getBytes(Charset.defaultCharset())); myProject.getBaseFolder().createFolder(EXCLUDE_SEARCH_PATH).createFile("_test", "searchhit".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/search/my_project?text=searchhit", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); List<ItemReference> result = (List<ItemReference>)response.getEntity(); assertEquals(result.size(), 1); Set<String> paths = new LinkedHashSet<>(1); paths.addAll(result.stream().map(ItemReference::getPath).collect(Collectors.toList())); Assert.assertTrue(paths.contains("/my_project/x/y/__test.txt")); Assert.assertFalse(paths.contains("/my_project/" + EXCLUDE_SEARCH_PATH + "/_test")); } @SuppressWarnings("unchecked") @Test public void testSearchParticularSequenceWords() throws Exception { String queryToSearch = "?text=" + URL_ENCODED_QUOTES + "To" + URL_ENCODED_SPACE + "be" + URL_ENCODED_SPACE + "or" + URL_ENCODED_SPACE + "not" + URL_ENCODED_SPACE + "to" + URL_ENCODED_SPACE + "be" + URL_ENCODED_QUOTES; RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("x/y") .createFile("containsSearchText.txt", "To be or not to be that is the question".getBytes( Charset.defaultCharset())); myProject.getBaseFolder().createFolder("a/b").createFile("test.txt", "Pay attention! To be or to be that is the question".getBytes( Charset.defaultCharset())); myProject.getBaseFolder().createFolder("c") .createFile("_test", "Pay attention! To be or to not be that is the question".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/search/my_project" + queryToSearch, "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); List<ItemReference> result = (List<ItemReference>)response.getEntity(); assertEquals(result.size(), 1); Set<String> paths = new LinkedHashSet<>(1); paths.addAll(result.stream().map(ItemReference::getPath).collect(Collectors.toList())); Assert.assertTrue(paths.contains("/my_project/x/y/containsSearchText.txt")); } @SuppressWarnings("unchecked") @Test public void testSearchParticularSequenceWordsWithAnyEnding() throws Exception { String queryToSearch = "?text=" + URL_ENCODED_QUOTES + "that" + URL_ENCODED_SPACE + "is" + URL_ENCODED_SPACE + "the" + URL_ENCODED_QUOTES + URL_ENCODED_SPACE + AND_OPERATOR + URL_ENCODED_SPACE + "question" + URL_ENCODED_ASTERISK; RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("x/y") .createFile("containsSearchText.txt", "To be or not to be that is the question".getBytes( Charset.defaultCharset())); myProject.getBaseFolder().createFolder("a/b") .createFile("containsSearchTextAlso.txt", "Pay attention! To be or not to be that is the questionS".getBytes(Charset.defaultCharset())); myProject.getBaseFolder().createFolder("c") .createFile("notContainsSearchText", "Pay attention! To be or to not be that is the questEon".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/search/my_project" + queryToSearch, "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); List<ItemReference> result = (List<ItemReference>)response.getEntity(); assertEquals(result.size(), 2); Set<String> paths = new LinkedHashSet<>(2); paths.addAll(result.stream().map(ItemReference::getPath).collect(Collectors.toList())); Assert.assertTrue(paths.contains("/my_project/x/y/containsSearchText.txt")); Assert.assertTrue(paths.contains("/my_project/a/b/containsSearchTextAlso.txt")); Assert.assertFalse(paths.contains("/my_project/c/notContainsSearchText.txt")); } @SuppressWarnings("unchecked") @Test public void testSearchWordWithAnyEnding() throws Exception { String queryToSearch = "?text=" + "question" + URL_ENCODED_ASTERISK; RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("x/y") .createFile("containsSearchText.txt", "To be or not to be that is the question".getBytes( Charset.defaultCharset())); myProject.getBaseFolder().createFolder("a/b") .createFile("containsSearchTextAlso.txt", "Pay attention! To be or not to be that is the questionS".getBytes(Charset.defaultCharset())); myProject.getBaseFolder().createFolder("c") .createFile("notContainsSearchText", "Pay attention! To be or to not be that is the questEon".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/search/my_project" + queryToSearch, "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); List<ItemReference> result = (List<ItemReference>)response.getEntity(); assertEquals(result.size(), 2); Set<String> paths = new LinkedHashSet<>(2); paths.addAll(result.stream().map(ItemReference::getPath).collect(Collectors.toList())); Assert.assertTrue(paths.contains("/my_project/x/y/containsSearchText.txt")); Assert.assertTrue(paths.contains("/my_project/a/b/containsSearchTextAlso.txt")); Assert.assertFalse(paths.contains("/my_project/c/notContainsSearchText.txt")); } @SuppressWarnings("unchecked") @Test public void testSearchTextWhenExcludeSomeText() throws Exception { String queryToSearch = "?text=" + "question" + URL_ENCODED_SPACE + NOT_OPERATOR + URL_ENCODED_SPACE + URL_ENCODED_QUOTES + "attention!" + URL_ENCODED_QUOTES; RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("x/y") .createFile("containsSearchText.txt", "To be or not to be that is the question".getBytes( Charset.defaultCharset())); myProject.getBaseFolder().createFolder("b") .createFile("notContainsSearchText", "Pay attention! To be or not to be that is the question".getBytes(Charset.defaultCharset())); myProject.getBaseFolder().createFolder("c").createFile("alsoNotContainsSearchText", "To be or to not be that is the ...".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/search/my_project" + queryToSearch, "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); List<ItemReference> result = (List<ItemReference>)response.getEntity(); assertEquals(result.size(), 1); Set<String> paths = new LinkedHashSet<>(1); paths.addAll(result.stream().map(ItemReference::getPath).collect(Collectors.toList())); Assert.assertTrue(paths.contains("/my_project/x/y/containsSearchText.txt")); Assert.assertFalse(paths.contains("/my_project/b/notContainsSearchText.txt")); Assert.assertFalse(paths.contains("/my_project/c/alsoContainsSearchText")); } @SuppressWarnings("unchecked") @Test public void testSearchTextWithEscapedCharachters() throws Exception { String queryToSearch = "?text=http" + URL_ENCODED_BACKSLASH + ':' + URL_ENCODED_BACKSLASH + '/' + URL_ENCODED_BACKSLASH + '/' + "localhost" + URL_ENCODED_BACKSLASH + ':' + "8080" + URL_ENCODED_BACKSLASH + '/' + "ide" + URL_ENCODED_BACKSLASH + '/' + "dev6" + URL_ENCODED_BACKSLASH + '?' + "action=createProject" + URL_ENCODED_BACKSLASH + ':' + "projectName=test"; RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("x/y") .createFile("test.txt", "http://localhost:8080/ide/dev6?action=createProject:projectName=test".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/search/my_project" + queryToSearch, "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); List<ItemReference> result = (List<ItemReference>)response.getEntity(); assertEquals(result.size(), 1); Set<String> paths = new LinkedHashSet<>(1); paths.addAll(result.stream().map(ItemReference::getPath).collect(Collectors.toList())); Assert.assertTrue(paths.contains("/my_project/x/y/test.txt")); } @SuppressWarnings("unchecked") @Test public void testSearchByNameAndText() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b").createFile("test.txt", "test".getBytes(Charset.defaultCharset())); myProject.getBaseFolder().createFolder("x/y").createFile("test.txt", "test".getBytes(Charset.defaultCharset())); myProject.getBaseFolder().createFolder("c").createFile("test", "test".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/search/my_project?text=test&name=test.txt", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); List<ItemReference> result = (List<ItemReference>)response.getEntity(); assertEquals(result.size(), 2); assertEqualsNoOrder(new Object[]{ result.get(0).getPath(), result.get(1).getPath() }, new Object[]{ "/my_project/a/b/test.txt", "/my_project/x/y/test.txt" }); } @SuppressWarnings("unchecked") @Test public void testSearchFromWSRoot() throws Exception { RegisteredProject myProject = pm.getProject("my_project"); myProject.getBaseFolder().createFolder("a/b").createFile("test", "test".getBytes(Charset.defaultCharset())); myProject.getBaseFolder().createFolder("x/y").createFile("test", "test".getBytes(Charset.defaultCharset())); myProject.getBaseFolder().createFolder("c").createFile("test.txt", "test".getBytes(Charset.defaultCharset())); ContainerResponse response = launcher.service(GET, "http://localhost:8080/api/project/search/?text=test&name=test.txt", "http://localhost:8080/api", null, null, null); assertEquals(response.getStatus(), 200, "Error: " + response.getEntity()); List<ItemReference> result = (List<ItemReference>)response.getEntity(); assertEquals(result.size(), 1); Assert.assertTrue(result.get(0).getPath().equals("/my_project/c/test.txt")); } private void validateFileLinks(ItemReference item) { Link link = item.getLink("delete"); assertNotNull(link); assertEquals(link.getMethod(), DELETE); assertEquals(link.getHref(), "http://localhost:8080/api/project" + item.getPath()); link = item.getLink("update content"); assertNotNull(link); assertEquals(link.getMethod(), PUT); assertEquals(link.getConsumes(), "*/*"); assertEquals(link.getHref(), "http://localhost:8080/api/project" + "/file" + item.getPath()); } private void validateFolderLinks(ItemReference item) { Link link = item.getLink("children"); assertNotNull(link); assertEquals(link.getMethod(), GET); assertEquals(link.getHref(), "http://localhost:8080/api/project/children" + item.getPath()); assertEquals(link.getProduces(), APPLICATION_JSON); link = item.getLink("tree"); assertNotNull(link); assertEquals(link.getMethod(), GET); assertEquals(link.getHref(), "http://localhost:8080/api/project/tree" + item.getPath()); assertEquals(link.getProduces(), APPLICATION_JSON); link = item.getLink("delete"); assertNotNull(link); assertEquals(link.getMethod(), DELETE); assertEquals(link.getHref(), "http://localhost:8080/api/project" + item.getPath()); } private void validateProjectLinks(ProjectConfigDto project) { List<Link> links = project.getLinks(); for (Link link : links) { switch (link.getHref()) { case "update project": assertNotNull(link); assertEquals(link.getMethod(), PUT); assertEquals(link.getHref(), "http://localhost:8080/api/project" + project.getPath()); assertEquals(link.getConsumes(), APPLICATION_JSON); assertEquals(link.getProduces(), APPLICATION_JSON); break; case "children": assertNotNull(link); assertEquals(link.getMethod(), GET); assertEquals(link.getHref(), "http://localhost:8080/api/project/children" + project.getPath()); assertEquals(link.getProduces(), APPLICATION_JSON); break; case "tree": assertNotNull(link); assertEquals(link.getMethod(), GET); assertEquals(link.getHref(), "http://localhost:8080/api/project/tree" + project.getPath()); assertEquals(link.getProduces(), APPLICATION_JSON); break; case "modules": assertNotNull(link); assertEquals(link.getMethod(), GET); assertEquals(link.getHref(), "http://localhost:8080/api/project/modules" + project.getPath()); assertEquals(link.getProduces(), APPLICATION_JSON); break; case "zipball sources": assertNotNull(link); assertEquals(link.getMethod(), GET); assertEquals(link.getHref(), "http://localhost:8080/api/project/export" + project.getPath()); assertEquals(link.getProduces(), APPLICATION_ZIP); break; case "delete": assertNotNull(link); assertEquals(link.getMethod(), DELETE); assertEquals(link.getHref(), "http://localhost:8080/api/project" + project.getPath()); break; } } } private InputStream prepareZipArchiveBasedOn(List<String> paths) throws IOException { ByteArrayOutputStream bout = new ByteArrayOutputStream(); ZipOutputStream zipOut = new ZipOutputStream(bout); for (String path : paths) { zipOut.putNextEntry(new ZipEntry(path)); } zipOut.close(); return new ByteArrayInputStream(bout.toByteArray()); } private void checkProjectIsCreated(String expectedName, String expectedPath, String expectedType, ProjectConfigDto actualConfig) throws ServerException, NotFoundException { final String projectDescription = "someDescription"; assertEquals(actualConfig.getName(), expectedName); assertEquals(actualConfig.getPath(), expectedPath); assertEquals(actualConfig.getDescription(), projectDescription); assertEquals(actualConfig.getType(), expectedType); final String expectedAttribute = "new_test_attribute"; final String expectedAttributeValue = "some_attribute_value"; final Map<String, List<String>> attributes = actualConfig.getAttributes(); assertNotNull(attributes); assertEquals(attributes.size(), 1); assertEquals(attributes.get(expectedAttribute), singletonList(expectedAttributeValue)); validateProjectLinks(actualConfig); RegisteredProject project = pm.getProject(expectedPath); assertNotNull(project); assertEquals(project.getDescription(), projectDescription); assertEquals(project.getProjectType().getId(), expectedType); String attributeVal = project.getAttributeEntries().get(expectedAttribute).getString(); assertNotNull(attributeVal); assertEquals(attributeVal, expectedAttributeValue); assertNotNull(project.getBaseFolder().getChild("a")); assertNotNull(project.getBaseFolder().getChild("b")); assertNotNull(project.getBaseFolder().getChild("test.txt")); } private void createTestProjectType(final String projectTypeId) throws ProjectTypeConstraintException { final ProjectTypeDef pt = new ProjectTypeDef(projectTypeId, "my project type", true, false) { { addConstantDefinition("new_test_attribute", "attr description", "some_attribute_value"); } }; ptRegistry.registerProjectType(pt); } private CreateProjectHandler createProjectHandlerFor(final String projectName, final String projectTypeId) { return new CreateProjectHandler() { @Override public void onCreateProject(Path projectPath, Map<String, AttributeValue> attributes, Map<String, String> options) throws ForbiddenException, ConflictException, ServerException { final String pathToProject = projectPath.toString(); final String pathToParent = pathToProject.substring(0, pathToProject.lastIndexOf("/")); final FolderEntry projectFolder = new FolderEntry( vfsProvider.getVirtualFileSystem().getRoot().getChild(Path.of(pathToParent)).createFolder(projectName)); projectFolder.createFolder("a"); projectFolder.createFolder("b"); projectFolder.createFile("test.txt", "test".getBytes(Charset.defaultCharset())); } @Override public String getProjectType() { return projectTypeId; } }; } private class LocalProjectType extends ProjectTypeDef { private LocalProjectType(String typeId, String typeName) { super(typeId, typeName, true, false); addConstantDefinition("my_attribute", "Constant", "attribute value 1"); } } }