/******************************************************************************* * Copyright (c) 2012, 2014 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.servlets.git; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; 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.IOUtilities; import org.eclipse.orion.server.core.ProtocolConstants; import org.eclipse.orion.server.core.resources.UniversalUniqueIdentifier; import org.eclipse.orion.server.git.GitConstants; import org.json.JSONException; import org.json.JSONObject; import org.junit.Ignore; import org.junit.Test; import org.xml.sax.SAXException; import com.meterware.httpunit.PostMethodWebRequest; import com.meterware.httpunit.WebRequest; import com.meterware.httpunit.WebResponse; public class GitApplyPatchTest extends GitTest { private static final String EOL = "\r\n"; //$NON-NLS-1$ @Test public void testApplyPatch_addFile() throws Exception { // clone: create createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME); String workspaceId = workspaceIdFromLocation(workspaceLocation); JSONObject project = createProjectOrLink(workspaceLocation, getMethodName().concat("Project"), null); IPath clonePath = getClonePath(workspaceId, project); clone(clonePath); // get project metadata WebRequest request = getGetRequest(project.getString(ProtocolConstants.KEY_CONTENT_LOCATION)); WebResponse response = webConversation.getResponse(request); assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode()); project = new JSONObject(response.getText()); JSONObject gitSection = project.optJSONObject(GitConstants.KEY_GIT); assertNotNull(gitSection); gitSection = project.getJSONObject(GitConstants.KEY_GIT); String gitDiffUri = gitSection.getString(GitConstants.KEY_DIFF); StringBuilder sb = new StringBuilder(); sb.append("diff --git a/new.txt b/new.txt").append("\n"); sb.append("new file mode 100644").append("\n"); sb.append("index 0000000..8013df8 100644").append("\n"); sb.append("--- /dev/null").append("\n"); sb.append("+++ b/new.txt").append("\n"); sb.append("@@ -0,0 +1 @@").append("\n"); sb.append("+newborn").append("\n"); sb.append("\\ No newline at end of file").append("\n"); JSONObject patchResult = patch(gitDiffUri, sb.toString()); assertEquals("200", patchResult.getString("HttpCode")); JSONObject newTxt = getChild(project, "new.txt"); assertEquals("newborn", getFileContent(newTxt)); String gitStatusUri = gitSection.getString(GitConstants.KEY_STATUS); assertStatus(new StatusResult().setUntrackedNames("new.txt"), gitStatusUri); } @Test public void testApplyPatch_deleteFile() throws Exception { // clone: create createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME); String workspaceId = workspaceIdFromLocation(workspaceLocation); JSONObject project = createProjectOrLink(workspaceLocation, getMethodName().concat("Project"), null); IPath clonePath = getClonePath(workspaceId, project); clone(clonePath); // get project metadata WebRequest request = getGetRequest(project.getString(ProtocolConstants.KEY_CONTENT_LOCATION)); WebResponse response = webConversation.getResponse(request); assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode()); project = new JSONObject(response.getText()); JSONObject gitSection = project.optJSONObject(GitConstants.KEY_GIT); assertNotNull(gitSection); gitSection = project.getJSONObject(GitConstants.KEY_GIT); String gitDiffUri = gitSection.getString(GitConstants.KEY_DIFF); StringBuilder sb = new StringBuilder(); sb.append("diff --git a/test.txt b/test.txt").append("\n"); sb.append("deleted file mode 100644").append("\n"); sb.append("index 8013df8..0000000 100644").append("\n"); sb.append("--- a/test.txt").append("\n"); sb.append("+++ /dev/null").append("\n"); sb.append("@@ -1 +0,0 @@").append("\n"); sb.append("-test").append("\n"); JSONObject patchResult = patch(gitDiffUri, sb.toString()); assertEquals("200", patchResult.getString("HttpCode")); String gitStatusUri = gitSection.getString(GitConstants.KEY_STATUS); assertStatus(new StatusResult().setMissingNames("test.txt"), gitStatusUri); } @Test public void testApplyPatch_modifyFile() throws Exception { // clone: create createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME); String workspaceId = workspaceIdFromLocation(workspaceLocation); JSONObject project = createProjectOrLink(workspaceLocation, getMethodName().concat("Project"), null); IPath clonePath = getClonePath(workspaceId, project); clone(clonePath); // get project metadata WebRequest request = getGetRequest(project.getString(ProtocolConstants.KEY_CONTENT_LOCATION)); WebResponse response = webConversation.getResponse(request); assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode()); project = new JSONObject(response.getText()); JSONObject gitSection = project.optJSONObject(GitConstants.KEY_GIT); assertNotNull(gitSection); gitSection = project.getJSONObject(GitConstants.KEY_GIT); String gitDiffUri = gitSection.getString(GitConstants.KEY_DIFF); StringBuilder sb = new StringBuilder(); sb.append("diff --git a/test.txt b/test.txt").append("\n"); sb.append("index 30d74d2..8013df8 100644").append("\n"); sb.append("--- a/test.txt").append("\n"); sb.append("+++ b/test.txt").append("\n"); sb.append("@@ -1 +1 @@").append("\n"); sb.append("-test").append("\n"); sb.append("\\ No newline at end of file").append("\n"); sb.append("+patched").append("\n"); sb.append("\\ No newline at end of file").append("\n"); JSONObject patchResult = patch(gitDiffUri, sb.toString()); assertEquals("200", patchResult.getString("HttpCode")); JSONObject testTxt = getChild(project, "test.txt"); assertEquals("patched", getFileContent(testTxt)); String gitStatusUri = gitSection.getString(GitConstants.KEY_STATUS); assertStatus(new StatusResult().setModifiedNames("test.txt").setModifiedContents("patched"), gitStatusUri); } // TODO @Ignore("not reported as a format error") @Test public void testApplyPatch_modifyFileFormatError() throws Exception { // clone: create createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME); JSONObject project = createProjectOrLink(workspaceLocation, getMethodName().concat("Project"), null); IPath clonePath = new Path("file").append(project.getString(ProtocolConstants.KEY_ID)).makeAbsolute(); clone(clonePath); // get project metadata WebRequest request = getGetRequest(project.getString(ProtocolConstants.KEY_CONTENT_LOCATION)); WebResponse response = webConversation.getResponse(request); assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode()); project = new JSONObject(response.getText()); JSONObject gitSection = project.optJSONObject(GitConstants.KEY_GIT); assertNotNull(gitSection); gitSection = project.getJSONObject(GitConstants.KEY_GIT); String gitDiffUri = gitSection.getString(GitConstants.KEY_DIFF); StringBuilder sb = new StringBuilder(); sb.append("diff --git a/test.txt b/test.txt").append("\n"); sb.append("malformed patch").append("\n"); JSONObject patchResult = patch(gitDiffUri, sb.toString()); assertEquals("400", patchResult.getString("HttpCode")); // nothing has changed JSONObject testTxt = getChild(project, "test.txt"); assertEquals("test", getFileContent(testTxt)); String gitStatusUri = gitSection.getString(GitConstants.KEY_STATUS); assertStatus(StatusResult.CLEAN, gitStatusUri); } @Test public void testApplyPatch_modifyFileApplyError() throws Exception { // clone: create createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME); String workspaceId = workspaceIdFromLocation(workspaceLocation); JSONObject project = createProjectOrLink(workspaceLocation, getMethodName().concat("Project"), null); IPath clonePath = getClonePath(workspaceId, project); clone(clonePath); // get project metadata WebRequest request = getGetRequest(project.getString(ProtocolConstants.KEY_CONTENT_LOCATION)); WebResponse response = webConversation.getResponse(request); assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode()); project = new JSONObject(response.getText()); JSONObject gitSection = project.optJSONObject(GitConstants.KEY_GIT); assertNotNull(gitSection); gitSection = project.getJSONObject(GitConstants.KEY_GIT); String gitDiffUri = gitSection.getString(GitConstants.KEY_DIFF); StringBuilder sb = new StringBuilder(); sb.append("diff --git a/test.txt b/test.txt").append("\n"); sb.append("index 30d74d2..8013df8 100644").append("\n"); sb.append("--- a/test.txt").append("\n"); sb.append("+++ b/test.txt").append("\n"); sb.append("@@ -1 +1 @@").append("\n"); sb.append("-xxx").append("\n"); sb.append("\\ No newline at end of file").append("\n"); sb.append("+patched").append("\n"); sb.append("\\ No newline at end of file").append("\n"); JSONObject patchResult = patch(gitDiffUri, sb.toString()); assertEquals("400", patchResult.getString("HttpCode")); // nothing has changed JSONObject testTxt = getChild(project, "test.txt"); assertEquals("test", getFileContent(testTxt)); String gitStatusUri = gitSection.getString(GitConstants.KEY_STATUS); assertStatus(StatusResult.CLEAN, gitStatusUri); } private JSONObject patch(final String gitDiffUri, String patch) throws IOException, SAXException, JSONException { WebRequest request = getPostGitDiffRequest(gitDiffUri, patch); WebResponse response = webConversation.getResponse(request); return new JSONObject(response.getText()); } private static WebRequest getPostGitDiffRequest(String location, String patch) throws UnsupportedEncodingException { String requestURI = toAbsoluteURI(location); String boundary = new UniversalUniqueIdentifier().toBase64String(); StringBuilder sb = new StringBuilder(); sb.append("--" + boundary + EOL); sb.append("Content-Disposition: form-data; name=\"radio\"" + EOL); sb.append(EOL); sb.append("fileRadio" + EOL); sb.append("--" + boundary + EOL); sb.append("Content-Disposition: form-data; name=\"uploadedfile\"; filename=\"\"" + EOL); sb.append(ProtocolConstants.HEADER_CONTENT_TYPE + ": plain/text" + EOL + EOL); //$NON-NLS-1$ sb.append(patch); // see GitDiffHandlerV1.readPatch(ServletInputStream, String) sb.append(EOL + "--" + boundary + "--" + EOL); patch = sb.toString(); WebRequest request = new PostMethodWebRequest(requestURI, IOUtilities.toInputStream(patch), "UTF-8"); request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1"); request.setHeaderField(ProtocolConstants.HEADER_CONTENT_TYPE, "multipart/related; boundary=" + boundary); //$NON-NLS-1$ setAuthentication(request); return request; } }