/*******************************************************************************
* Copyright (c) 2011, 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 static org.junit.Assert.assertNotSame;
import java.io.IOException;
import java.net.HttpURLConnection;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.orion.internal.server.core.metastore.SimpleMetaStore;
import org.eclipse.orion.server.core.ProtocolConstants;
import org.eclipse.orion.server.git.GitConstants;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Test;
import org.xml.sax.SAXException;
import com.meterware.httpunit.GetMethodWebRequest;
import com.meterware.httpunit.WebRequest;
import com.meterware.httpunit.WebResponse;
/**
* Tests for servlet implementation of Git blame.
*/
public class GitBlameTest extends GitTest {
@Test
public void testBlameNoCommits() throws IOException, SAXException, JSONException, CoreException {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
IPath[] clonePaths = createTestProjects(workspaceLocation);
for (IPath clonePath : clonePaths) {
//clone a repo
JSONObject clone = clone(clonePath);
String cloneContentLocation = clone.getString(ProtocolConstants.KEY_CONTENT_LOCATION);
//get project/folder metadata
WebRequest request = getGetRequest(cloneContentLocation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject folder = new JSONObject(response.getText());
// get blameUri
JSONObject gitSection = folder.getJSONObject(GitConstants.KEY_GIT);
String gitBlameUri = gitSection.getString(GitConstants.KEY_BLAME);
// blame request
request = getGetGitBlameRequest(gitBlameUri);
response = webConversation.getResource(request);
assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, response.getResponseCode());
// test
JSONObject blameObject = new JSONObject(response.getText());
assertEquals(blameObject.get("Severity"), "Error");
assertEquals(blameObject.get("HttpCode"), 400);
assertEquals(blameObject.get("Code"), 0);
}
}
@Test
public void testBlameOneCommit() throws IOException, SAXException, JSONException, CoreException {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
IPath[] clonePaths = createTestProjects(workspaceLocation);
for (IPath clonePath : clonePaths) {
//clone a repo
JSONObject clone = clone(clonePath);
String cloneContentLocation = clone.getString(ProtocolConstants.KEY_CONTENT_LOCATION);
//get project/folder metadata
WebRequest request = getGetRequest(cloneContentLocation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject folder = new JSONObject(response.getText());
JSONObject gitSection = folder.getJSONObject(GitConstants.KEY_GIT);
String gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD);
//create and modify file
JSONObject testTxt = getChild(folder, "test.txt");
modifyFile(testTxt, "line one \n line two \n line 3 \n line 4");
//commit
addFile(testTxt);
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri, "initial commit", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// get blame Uri
JSONObject testTxtGitSection = testTxt.getJSONObject(GitConstants.KEY_GIT);
String blameUri = testTxtGitSection.getString(GitConstants.KEY_BLAME);
// blame request
request = getGetGitBlameRequest(blameUri);
response = webConversation.getResource(request);
// get BlameInfo
JSONObject blameObject = new JSONObject(response.getText());
//Test
assertEquals(blameObject.getString(ProtocolConstants.KEY_TYPE), "Blame");
JSONArray blame = blameObject.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertNotNull(blameObject.get(ProtocolConstants.KEY_CHILDREN));
assertEquals(blame.length(), 1);
blameObject = blame.getJSONObject(0);
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_EMAIL));
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_NAME));
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_IMAGE));
assertNotNull(blameObject.get(GitConstants.KEY_COMMITTER_EMAIL));
assertNotNull(blameObject.get(GitConstants.KEY_COMMITTER_NAME));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT_MESSAGE));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT_TIME));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT));
assertNotNull(blameObject.get(ProtocolConstants.KEY_NAME));
JSONArray children = blameObject.getJSONArray(ProtocolConstants.KEY_CHILDREN);
JSONObject child = children.getJSONObject(0);
assertEquals(children.length(), 1);
assertEquals(child.get(GitConstants.KEY_START_RANGE), 1);
assertEquals(child.get(GitConstants.KEY_END_RANGE), 4);
}
}
@Test
public void testBlameMultiCommit() throws IOException, SAXException, JSONException, CoreException {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
IPath[] clonePaths = createTestProjects(workspaceLocation);
for (IPath clonePath : clonePaths) {
//clone a repo
JSONObject clone = clone(clonePath);
String cloneContentLocation = clone.getString(ProtocolConstants.KEY_CONTENT_LOCATION);
//get project/folder metadata
WebRequest request = getGetRequest(cloneContentLocation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject folder = new JSONObject(response.getText());
JSONObject gitSection = folder.getJSONObject(GitConstants.KEY_GIT);
String gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD);
//create file test.txtx
JSONObject testTxt = getChild(folder, "test.txt");
modifyFile(testTxt, "line one \n line two \n line 3 \n line 4");
//commit the file
addFile(testTxt);
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri, "initial commit", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// get the blame uri for this file
JSONObject testTxtGitSection = testTxt.getJSONObject(GitConstants.KEY_GIT);
String blameUri = testTxtGitSection.getString(GitConstants.KEY_BLAME);
// blame the file
request = getGetGitBlameRequest(blameUri);
response = webConversation.getResource(request);
// testing
JSONObject blameObject = new JSONObject(response.getText());
// non blame info tests
JSONArray blame = blameObject.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertNotNull(blameObject.get(ProtocolConstants.KEY_CHILDREN));
assertEquals(blame.length(), 1);
blameObject = blame.getJSONObject(0);
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_EMAIL));
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_NAME));
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_IMAGE));
assertNotNull(blameObject.get(GitConstants.KEY_COMMITTER_EMAIL));
assertNotNull(blameObject.get(GitConstants.KEY_COMMITTER_NAME));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT_MESSAGE));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT_TIME));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT));
assertNotNull(blameObject.get(ProtocolConstants.KEY_NAME));
JSONArray children = blameObject.getJSONArray(ProtocolConstants.KEY_CHILDREN);
JSONObject child = children.getJSONObject(0);
assertEquals(children.length(), 1);
assertEquals(child.get(GitConstants.KEY_START_RANGE), 1);
assertEquals(child.get(GitConstants.KEY_END_RANGE), 4);
//save commit info to test
String commitLocation1 = blameObject.getString(GitConstants.KEY_COMMIT);
int commitTime1 = blameObject.getInt(GitConstants.KEY_COMMIT_TIME);
String commitId1 = blameObject.getString(ProtocolConstants.KEY_NAME);
// modify the file
modifyFile(testTxt, "LINE ONE \n LINE TWO \n LINE THREE \n LINE FOUR \n LINE FIVE");
addFile(testTxt);
//commit the new changes
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri, "initial commit", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// get blame uri
testTxtGitSection = testTxt.getJSONObject(GitConstants.KEY_GIT);
blameUri = testTxtGitSection.getString(GitConstants.KEY_BLAME);
// blame file
request = getGetGitBlameRequest(blameUri);
response = webConversation.getResource(request);
// test
blameObject = new JSONObject(response.getText());
// non blame info tests
assertEquals(blameObject.length(), 4);
assertEquals(blameObject.getString(ProtocolConstants.KEY_TYPE), "Blame");
assertEquals(blameObject.getString(ProtocolConstants.KEY_LOCATION), blameUri);
blame = blameObject.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertNotNull(blameObject.get(ProtocolConstants.KEY_CHILDREN));
// test first commit
assertEquals(blame.length(), 1);
blameObject = blame.getJSONObject(0);
//test second commit
blameObject = blame.getJSONObject(0);
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_EMAIL));
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_NAME));
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_IMAGE));
assertNotNull(blameObject.get(GitConstants.KEY_COMMITTER_EMAIL));
assertNotNull(blameObject.get(GitConstants.KEY_COMMITTER_NAME));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT_MESSAGE));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT_TIME));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT));
assertNotNull(blameObject.get(ProtocolConstants.KEY_NAME));
children = blameObject.getJSONArray(ProtocolConstants.KEY_CHILDREN);
child = children.getJSONObject(0);
assertEquals(children.length(), 1);
assertEquals(child.get(GitConstants.KEY_START_RANGE), 1);
assertEquals(child.get(GitConstants.KEY_END_RANGE), 5);
String commitLocation2 = blameObject.getString(GitConstants.KEY_COMMIT);
int commitTime2 = blameObject.getInt(GitConstants.KEY_COMMIT_TIME);
String commitId2 = blameObject.getString(ProtocolConstants.KEY_NAME);
// test that there are not duplicates of the same commit
assertNotSame(commitId1, commitId2);
assertNotSame(commitLocation1, commitLocation2);
assertNotSame(commitTime1, commitTime2);
}
}
@Test
public void testBlameMultiFile() throws IOException, SAXException, JSONException, CoreException {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
IPath[] clonePaths = createTestProjects(workspaceLocation);
for (IPath clonePath : clonePaths) {
//clone a repo
JSONObject clone = clone(clonePath);
String cloneContentLocation = clone.getString(ProtocolConstants.KEY_CONTENT_LOCATION);
//get project/folder metadata
WebRequest request = getGetRequest(cloneContentLocation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject folder = new JSONObject(response.getText());
JSONObject gitSection = folder.getJSONObject(GitConstants.KEY_GIT);
String gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD);
/*
* Commit 1
*/
// create the original file and modify it
JSONObject testTxt = getChild(folder, "test.txt");
modifyFile(testTxt, "line one \n line two \n line 3 \n line 4");
//commit file
addFile(testTxt);
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri, "initial commit", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// get blameURI
JSONObject testTxtGitSection = testTxt.getJSONObject(GitConstants.KEY_GIT);
String blameUri = testTxtGitSection.getString(GitConstants.KEY_BLAME);
// make blame request
request = getGetGitBlameRequest(blameUri);
response = webConversation.getResource(request);
// test
JSONObject blameObject = new JSONObject(response.getText());
assertEquals(blameObject.getString(ProtocolConstants.KEY_TYPE), "Blame");
assertEquals(blameObject.getString(ProtocolConstants.KEY_LOCATION), blameUri);
//test blameInfo
JSONArray blame = blameObject.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertNotNull(blameObject.get(ProtocolConstants.KEY_CHILDREN));
assertEquals(blame.length(), 1);
blameObject = blame.getJSONObject(0);
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_EMAIL));
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_NAME));
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_IMAGE));
assertNotNull(blameObject.get(GitConstants.KEY_COMMITTER_EMAIL));
assertNotNull(blameObject.get(GitConstants.KEY_COMMITTER_NAME));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT_MESSAGE));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT_TIME));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT));
assertNotNull(blameObject.get(ProtocolConstants.KEY_NAME));
JSONArray children = blameObject.getJSONArray(ProtocolConstants.KEY_CHILDREN);
JSONObject child = children.getJSONObject(0);
assertEquals(children.length(), 1);
assertEquals(child.get(GitConstants.KEY_START_RANGE), 1);
assertEquals(child.get(GitConstants.KEY_END_RANGE), 4);
/*
* commit 2 - different file
*/
// create a second file in a different folder
JSONObject newfolder = getChild(folder, "folder");
JSONObject folderTxt = getChild(newfolder, "folder.txt");
modifyFile(folderTxt, "commit me");
// commit the new file
addFile(folderTxt);
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri, "initial commit on testFile2.txt", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// make blame request
request = getGetGitBlameRequest(blameUri);
response = webConversation.getResource(request);
/*
* These tests should produce the same results as the above tests
* They should be not affected by the recent commit
*/
blameObject = new JSONObject(response.getText());
assertEquals(blameObject.getString(ProtocolConstants.KEY_TYPE), "Blame");
assertEquals(blameObject.getString(ProtocolConstants.KEY_LOCATION), blameUri);
//test blameInfo
blame = blameObject.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertNotNull(blameObject.get(ProtocolConstants.KEY_CHILDREN));
assertEquals(blame.length(), 1);
blameObject = blame.getJSONObject(0);
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_EMAIL));
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_NAME));
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_IMAGE));
assertNotNull(blameObject.get(GitConstants.KEY_COMMITTER_EMAIL));
assertNotNull(blameObject.get(GitConstants.KEY_COMMITTER_NAME));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT_MESSAGE));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT_TIME));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT));
assertNotNull(blameObject.get(ProtocolConstants.KEY_NAME));
children = blameObject.getJSONArray(ProtocolConstants.KEY_CHILDREN);
child = children.getJSONObject(0);
assertEquals(children.length(), 1);
assertEquals(child.get(GitConstants.KEY_START_RANGE), 1);
assertEquals(child.get(GitConstants.KEY_END_RANGE), 4);
/*
* commit 3 - original file
*/
// modify original file
modifyFile(testTxt, "LINE ONE \n LINE TWO \n LINE THREE \n LINE FOUR \n LINE FIVE");
//commit the changes
addFile(testTxt);
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri, "modified testFile.txt", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
blameUri = testTxtGitSection.getString(GitConstants.KEY_BLAME);
// do blame computation
request = getGetGitBlameRequest(blameUri);
response = webConversation.getResource(request);
blameObject = new JSONObject(response.getText());
assertEquals(blameObject.getString(ProtocolConstants.KEY_TYPE), "Blame");
assertEquals(blameObject.getString(ProtocolConstants.KEY_LOCATION), blameUri);
// test
blame = blameObject.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertNotNull(blameObject.get(ProtocolConstants.KEY_CHILDREN));
assertEquals(blame.length(), 1);
blameObject = blame.getJSONObject(0);
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_EMAIL));
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_NAME));
assertNotNull(blameObject.get(GitConstants.KEY_AUTHOR_IMAGE));
assertNotNull(blameObject.get(GitConstants.KEY_COMMITTER_EMAIL));
assertNotNull(blameObject.get(GitConstants.KEY_COMMITTER_NAME));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT_MESSAGE));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT_TIME));
assertNotNull(blameObject.get(GitConstants.KEY_COMMIT));
assertNotNull(blameObject.get(ProtocolConstants.KEY_NAME));
children = blameObject.getJSONArray(ProtocolConstants.KEY_CHILDREN);
child = children.getJSONObject(0);
assertEquals(children.length(), 1);
assertEquals(child.get(GitConstants.KEY_START_RANGE), 1);
assertEquals(child.get(GitConstants.KEY_END_RANGE), 5);
}
}
@Test
public void testFolderBlame() throws IOException, SAXException, JSONException, CoreException {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
IPath[] clonePaths = createTestProjects(workspaceLocation);
for (IPath clonePath : clonePaths) {
//clone a repo
JSONObject clone = clone(clonePath);
String cloneContentLocation = clone.getString(ProtocolConstants.KEY_CONTENT_LOCATION);
//get project/folder metadata
WebRequest request = getGetRequest(cloneContentLocation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject folder = new JSONObject(response.getText());
JSONObject gitSection = folder.getJSONObject(GitConstants.KEY_GIT);
String gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD);
JSONObject newfolder = getChild(folder, "folder");
//modifyFile(newfolder, "commit me");
// commit the new file
addFile(newfolder);
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri, "initial commit on testFile2.txt", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject newfolderGitSection = newfolder.getJSONObject(GitConstants.KEY_GIT);
String blameUri = newfolderGitSection.getString(GitConstants.KEY_BLAME);
// blame request
request = getGetGitBlameRequest(blameUri);
response = webConversation.getResource(request);
// get BlameInfo
JSONObject blameObject = new JSONObject(response.getText());
//Test
assertEquals(blameObject.get("Severity"), "Error");
assertEquals(blameObject.get("HttpCode"), 400);
assertEquals(blameObject.get("Code"), 0);
}
}
protected static WebRequest getGetGitBlameRequest(String location) {
String requestURI = toAbsoluteURI(location);
WebRequest request = new GetMethodWebRequest(requestURI);
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return request;
}
}