/******************************************************************************* * Copyright (c) 2016 IBM Corporation and others. * 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.orion.server.tests.metastore; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URI; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.orion.internal.server.core.metastore.SimpleMetaStore; import org.eclipse.orion.server.core.OrionConfiguration; import org.eclipse.orion.server.core.ProtocolConstants; import org.eclipse.orion.server.core.metastore.WorkspaceInfo; import org.eclipse.orion.server.tests.servlets.files.FileSystemTest; import org.eclipse.orion.server.tests.servlets.internal.DeleteMethodWebRequest; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.xml.sax.SAXException; import com.meterware.httpunit.GetMethodWebRequest; import com.meterware.httpunit.WebConversation; import com.meterware.httpunit.WebRequest; import com.meterware.httpunit.WebResponse; /** * Tests to ensure that the project list in a workspace in a SimpleMetaStore can be successfully deleted concurrently * from separate threads. See Bug 474557 */ public class SimpleMetaStoreWorkspaceProjectListConcurrencyTests extends FileSystemTest { private int USERS_NUMBER = 4; private class WorkspaceObject { private int PROJECTS_NUMBER = 40; private URI workspaceLocation; public void setWorkspaceLocation(URI workspaceLocation) { this.workspaceLocation = workspaceLocation; } private List<WebConversation> webConversationList = new ArrayList<WebConversation>(); private String password; public String getPassword() { return password; } public String getLogin() { return login; } private String login; public WorkspaceObject(String login, String password) { this.login = login; this.password = password; for (int i = 0; i < PROJECTS_NUMBER; i++) { WebConversation webConversation = new WebConversation(); webConversation.setExceptionsThrownOnErrorStatus(false); webConversationList.add(webConversation); } } public List<WebConversation> getWebConversationList() { return webConversationList; } public String getWorkspaceName() { return workspaceLocation.getPath().split("/")[2]; } public URI getWorkspaceLocation() { return workspaceLocation; } } private List<WorkspaceObject> workspaceObjectList = new ArrayList<WorkspaceObject>(); @BeforeClass public static void setupWorkspace() { initializeWorkspaceLocation(); } @Before public void setUp() throws CoreException, IOException, SAXException { String userLogin = testUserLogin; for (int i = 0; i < USERS_NUMBER; i++) { WorkspaceObject workspaceObject = new WorkspaceObject(userLogin + "_" + i, testUserPassword); webConversation = workspaceObject.getWebConversationList().get(0); testUserLogin = workspaceObject.getLogin(); testUserPassword = workspaceObject.getPassword(); setUpAuthorization(); createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME); workspaceObject.setWorkspaceLocation(workspaceLocation); workspaceObjectList.add(workspaceObject); } } private Thread createThreadForDeletion(final String name, final WebConversation webConversation, final WebRequest request) { Runnable runnable = new Runnable() { public void run() { try { WebResponse response = webConversation.getResponse(request); assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode()); } catch (IOException e) { fail(e.getLocalizedMessage()); } catch (SAXException e) { fail(e.getLocalizedMessage()); } } }; Thread thread = new Thread(runnable, "SimpleMetaStoreWorkspaceProjectListConcurrencyTests-" + name); return thread; } @Test public void testSimpleMetaStoreDeleteProjectConcurrency() throws IOException, SAXException, JSONException, CoreException { List<Thread> threads = new ArrayList<Thread>(); for (int j = 0; j < workspaceObjectList.size(); j++) { List<WebConversation> webConversationList = workspaceObjectList.get(j).getWebConversationList(); ArrayList<WebRequest> webRequestList = new ArrayList<WebRequest>(); URI workspaceLocation1 = workspaceObjectList.get(j).getWorkspaceLocation(); testUserLogin = workspaceObjectList.get(j).getLogin(); testUserPassword = workspaceObjectList.get(j).getPassword(); for (int i = 0; i < webConversationList.size(); i++) { // create a project String projectName = "TestProject" + i; WebRequest request = getCreateProjectRequest(workspaceLocation1, projectName, null); WebResponse response = webConversationList.get(i).getResponse(request); assertEquals(HttpURLConnection.HTTP_CREATED, response.getResponseCode()); String projectLocation = response.getHeaderField(ProtocolConstants.HEADER_LOCATION); // update the global variables for the test IPath workspacePath = new Path(workspaceLocation1.getPath()); String workspaceId = new Path(workspaceLocation1.getPath()).segment(workspacePath.segmentCount() - 1); testProjectBaseLocation = "/" + workspaceId + '/' + projectName; JSONObject project = new JSONObject(response.getText()); testProjectLocalFileLocation = "/" + project.optString(ProtocolConstants.KEY_ID, null); String contentLocation = project.optString(ProtocolConstants.KEY_CONTENT_LOCATION); // IFileStore projectStore = EFS.getStore(makeLocalPathAbsolute("")); // add a file in the project String fileName = "file.txt"; request = getPostFilesRequest(contentLocation, getNewFileJSON(fileName).toString(), fileName); response = webConversationList.get(i).getResponse(request); assertEquals(HttpURLConnection.HTTP_CREATED, response.getResponseCode()); assertEquals("Response should contain file metadata in JSON, but was " + response.getText(), "application/json", response.getContentType()); JSONObject responseObject = new JSONObject(response.getText()); assertNotNull("No file information in response", responseObject); checkFileMetadata(responseObject, fileName, null, null, null, null, null, null, null, projectName); WebRequest request1 = new DeleteMethodWebRequest(toAbsoluteURI(projectLocation)); request1.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1"); setAuthentication(request1); webRequestList.add(request1); } WorkspaceInfo workspaceLocal = OrionConfiguration.getMetaStore().readWorkspace(workspaceObjectList.get(j).getWorkspaceName()); List<String> projectListFinal = workspaceLocal.getProjectNames(); // Assertion for check a number of projects before deletion. assertEquals(webConversationList.size(), projectListFinal.size()); for (int i = 0; i < webConversationList.size(); i++) { threads.add(createThreadForDeletion(workspaceObjectList.get(j).getWorkspaceName() + " TestProject" + i, webConversationList.get(i), webRequestList.get(i))); } } for (int i = 0; i < threads.size(); i++) { threads.get(i).start(); } for (int i = 0; i < threads.size(); i++) { try { threads.get(i).join(); } catch (InterruptedException e) { // just continue } } for (int i = 0; i < workspaceObjectList.size(); i++) { WebRequest request = new GetMethodWebRequest(addSchemeHostPort(workspaceObjectList.get(i).getWorkspaceLocation()).toString()); setAuthentication(request); WebResponse response = webConversation.getResponse(request); JSONObject workspace = new JSONObject(response.getText()); assertNotNull(workspace); JSONArray projects = workspace.getJSONArray(ProtocolConstants.KEY_PROJECTS); assertEquals(0, projects.length()); response = webConversation.getResponse(request); assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode()); WorkspaceInfo workspaceLocal = OrionConfiguration.getMetaStore().readWorkspace(workspaceObjectList.get(i).getWorkspaceName()); List<String> projectListFinal = workspaceLocal.getProjectNames(); assertEquals(0, projectListFinal.size()); } } }