blob: 4e4b056a9af5f9e416549934bd726be25b36dc18 [file] [log] [blame]
package com.gitblit.tests;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import com.gitblit.Keys;
import com.gitblit.manager.FilestoreManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.models.FilestoreModel.Status;
import com.gitblit.servlet.FilestoreServlet;
import com.gitblit.utils.FileUtils;
public class FilestoreServletTest extends GitblitUnitTest {
private static final AtomicBoolean started = new AtomicBoolean(false);
private static final String SHA256_EG = "9a712c5d4037503a2d5ee1d07ad191eb99d051e84cbb020c171a5ae19bbe3cbd";
private static final String repoName = "helloworld.git";
private static final String repoLfs = "/r/" + repoName + "/info/lfs/objects/";
@BeforeClass
public static void startGitblit() throws Exception {
started.set(GitBlitSuite.startGitblit());
}
@AfterClass
public static void stopGitblit() throws Exception {
if (started.get()) {
GitBlitSuite.stopGitblit();
}
}
@Test
public void testRegexGroups() throws Exception {
Pattern p = Pattern.compile(FilestoreServlet.REGEX_PATH);
String basicUrl = "https://localhost:8080/r/test.git/info/lfs/objects/";
String batchUrl = basicUrl + "batch";
String oidUrl = basicUrl + SHA256_EG;
Matcher m = p.matcher(batchUrl);
assertTrue(m.find());
assertEquals("https://localhost:8080", m.group(FilestoreServlet.REGEX_GROUP_BASE_URI));
assertEquals("r", m.group(FilestoreServlet.REGEX_GROUP_PREFIX));
assertEquals("test.git", m.group(FilestoreServlet.REGEX_GROUP_REPOSITORY));
assertEquals("batch", m.group(FilestoreServlet.REGEX_GROUP_ENDPOINT));
m = p.matcher(oidUrl);
assertTrue(m.find());
assertEquals("https://localhost:8080", m.group(FilestoreServlet.REGEX_GROUP_BASE_URI));
assertEquals("r", m.group(FilestoreServlet.REGEX_GROUP_PREFIX));
assertEquals("test.git", m.group(FilestoreServlet.REGEX_GROUP_REPOSITORY));
assertEquals(SHA256_EG, m.group(FilestoreServlet.REGEX_GROUP_ENDPOINT));
}
@Test
public void testRegexGroupsNestedRepo() throws Exception {
Pattern p = Pattern.compile(FilestoreServlet.REGEX_PATH);
String basicUrl = "https://localhost:8080/r/nested/test.git/info/lfs/objects/";
String batchUrl = basicUrl + "batch";
String oidUrl = basicUrl + SHA256_EG;
Matcher m = p.matcher(batchUrl);
assertTrue(m.find());
assertEquals("https://localhost:8080", m.group(FilestoreServlet.REGEX_GROUP_BASE_URI));
assertEquals("r", m.group(FilestoreServlet.REGEX_GROUP_PREFIX));
assertEquals("nested/test.git", m.group(FilestoreServlet.REGEX_GROUP_REPOSITORY));
assertEquals("batch", m.group(FilestoreServlet.REGEX_GROUP_ENDPOINT));
m = p.matcher(oidUrl);
assertTrue(m.find());
assertEquals("https://localhost:8080", m.group(FilestoreServlet.REGEX_GROUP_BASE_URI));
assertEquals("r", m.group(FilestoreServlet.REGEX_GROUP_PREFIX));
assertEquals("nested/test.git", m.group(FilestoreServlet.REGEX_GROUP_REPOSITORY));
assertEquals(SHA256_EG, m.group(FilestoreServlet.REGEX_GROUP_ENDPOINT));
}
@Test
public void testDownload() throws Exception {
FileUtils.delete(filestore().getStorageFolder());
filestore().clearFilestoreCache();
RepositoryModel r = gitblit().getRepositoryModel(repoName);
UserModel u = new UserModel("admin");
u.canAdmin = true;
//No upload limit
settings().overrideSetting(Keys.filestore.maxUploadSize, FilestoreManager.UNDEFINED_SIZE);
final BlobInfo blob = new BlobInfo(512*FileUtils.KB);
//Emulate a pre-existing Git-LFS repository by using using internal pre-tested methods
assertEquals(Status.Available, filestore().uploadBlob(blob.hash, blob.length, u, r, new ByteArrayInputStream(blob.blob)));
final String downloadURL = GitBlitSuite.url + repoLfs + blob.hash;
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(downloadURL);
// add request header
request.addHeader(HttpHeaders.ACCEPT, FilestoreServlet.GIT_LFS_META_MIME);
HttpResponse response = client.execute(request);
assertEquals(200, response.getStatusLine().getStatusCode());
String content = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
String expectedContent = String.format("{%s:%s,%s:%d,%s:{%s:{%s:%s}}}",
"\"oid\"", "\"" + blob.hash + "\"",
"\"size\"", blob.length,
"\"actions\"",
"\"download\"",
"\"href\"", "\"" + downloadURL + "\"");
assertEquals(expectedContent, content);
//Now try the binary download
request.removeHeaders(HttpHeaders.ACCEPT);
response = client.execute(request);
assertEquals(200, response.getStatusLine().getStatusCode());
byte[] dlData = IOUtils.toByteArray(response.getEntity().getContent());
assertArrayEquals(blob.blob, dlData);
}
@Test
public void testDownloadMultiple() throws Exception {
FileUtils.delete(filestore().getStorageFolder());
filestore().clearFilestoreCache();
RepositoryModel r = gitblit().getRepositoryModel(repoName);
UserModel u = new UserModel("admin");
u.canAdmin = true;
//No upload limit
settings().overrideSetting(Keys.filestore.maxUploadSize, FilestoreManager.UNDEFINED_SIZE);
final BlobInfo blob = new BlobInfo(512*FileUtils.KB);
//Emulate a pre-existing Git-LFS repository by using using internal pre-tested methods
assertEquals(Status.Available, filestore().uploadBlob(blob.hash, blob.length, u, r, new ByteArrayInputStream(blob.blob)));
final String batchURL = GitBlitSuite.url + repoLfs + "batch";
final String downloadURL = GitBlitSuite.url + repoLfs + blob.hash;
HttpClient client = HttpClientBuilder.create().build();
HttpPost request = new HttpPost(batchURL);
// add request header
request.addHeader(HttpHeaders.ACCEPT, FilestoreServlet.GIT_LFS_META_MIME);
request.addHeader(HttpHeaders.CONTENT_ENCODING, FilestoreServlet.GIT_LFS_META_MIME);
String content = String.format("{%s:%s,%s:[{%s:%s,%s:%d},{%s:%s,%s:%d}]}",
"\"operation\"", "\"download\"",
"\"objects\"",
"\"oid\"", "\"" + blob.hash + "\"",
"\"size\"", blob.length,
"\"oid\"", "\"" + SHA256_EG + "\"",
"\"size\"", 0);
HttpEntity entity = new ByteArrayEntity(content.getBytes("UTF-8"));
request.setEntity(entity);
HttpResponse response = client.execute(request);
String responseMessage = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
assertEquals(200, response.getStatusLine().getStatusCode());
String expectedContent = String.format("{%s:[{%s:%s,%s:%d,%s:{%s:{%s:%s}}},{%s:%s,%s:%d,%s:{%s:%s,%s:%d}}]}",
"\"objects\"",
"\"oid\"", "\"" + blob.hash + "\"",
"\"size\"", blob.length,
"\"actions\"",
"\"download\"",
"\"href\"", "\"" + downloadURL + "\"",
"\"oid\"", "\"" + SHA256_EG + "\"",
"\"size\"", 0,
"\"error\"",
"\"message\"", "\"Object not available\"",
"\"code\"", 404
);
assertEquals(expectedContent, responseMessage);
}
@Test
public void testDownloadUnavailable() throws Exception {
FileUtils.delete(filestore().getStorageFolder());
filestore().clearFilestoreCache();
//No upload limit
settings().overrideSetting(Keys.filestore.maxUploadSize, FilestoreManager.UNDEFINED_SIZE);
final BlobInfo blob = new BlobInfo(512*FileUtils.KB);
final String downloadURL = GitBlitSuite.url + repoLfs + blob.hash;
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(downloadURL);
// add request header
request.addHeader(HttpHeaders.ACCEPT, FilestoreServlet.GIT_LFS_META_MIME);
HttpResponse response = client.execute(request);
assertEquals(404, response.getStatusLine().getStatusCode());
String content = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
String expectedError = String.format("{%s:%s,%s:%d}",
"\"message\"", "\"Object not available\"",
"\"code\"", 404);
assertEquals(expectedError, content);
}
@Test
public void testUpload() throws Exception {
FileUtils.delete(filestore().getStorageFolder());
filestore().clearFilestoreCache();
RepositoryModel r = gitblit().getRepositoryModel(repoName);
UserModel u = new UserModel("admin");
u.canAdmin = true;
//No upload limit
settings().overrideSetting(Keys.filestore.maxUploadSize, FilestoreManager.UNDEFINED_SIZE);
final BlobInfo blob = new BlobInfo(512*FileUtils.KB);
final String expectedUploadURL = GitBlitSuite.url + repoLfs + blob.hash;
final String initialUploadURL = GitBlitSuite.url + repoLfs + "batch";
HttpClient client = HttpClientBuilder.create().build();
HttpPost request = new HttpPost(initialUploadURL);
// add request header
request.addHeader(HttpHeaders.ACCEPT, FilestoreServlet.GIT_LFS_META_MIME);
request.addHeader(HttpHeaders.CONTENT_ENCODING, FilestoreServlet.GIT_LFS_META_MIME);
String content = String.format("{%s:%s,%s:[{%s:%s,%s:%d}]}",
"\"operation\"", "\"upload\"",
"\"objects\"",
"\"oid\"", "\"" + blob.hash + "\"",
"\"size\"", blob.length);
HttpEntity entity = new ByteArrayEntity(content.getBytes("UTF-8"));
request.setEntity(entity);
HttpResponse response = client.execute(request);
String responseMessage = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
assertEquals(200, response.getStatusLine().getStatusCode());
String expectedContent = String.format("{%s:[{%s:%s,%s:%d,%s:{%s:{%s:%s}}}]}",
"\"objects\"",
"\"oid\"", "\"" + blob.hash + "\"",
"\"size\"", blob.length,
"\"actions\"",
"\"upload\"",
"\"href\"", "\"" + expectedUploadURL + "\"");
assertEquals(expectedContent, responseMessage);
//Now try to upload the binary download
HttpPut putRequest = new HttpPut(expectedUploadURL);
putRequest.setEntity(new ByteArrayEntity(blob.blob));
response = client.execute(putRequest);
responseMessage = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
assertEquals(200, response.getStatusLine().getStatusCode());
//Confirm behind the scenes that it is available
ByteArrayOutputStream savedBlob = new ByteArrayOutputStream();
assertEquals(Status.Available, filestore().downloadBlob(blob.hash, u, r, savedBlob));
assertArrayEquals(blob.blob, savedBlob.toByteArray());
}
@Test
public void testMalformedUpload() throws Exception {
FileUtils.delete(filestore().getStorageFolder());
filestore().clearFilestoreCache();
//No upload limit
settings().overrideSetting(Keys.filestore.maxUploadSize, FilestoreManager.UNDEFINED_SIZE);
final BlobInfo blob = new BlobInfo(512*FileUtils.KB);
final String initialUploadURL = GitBlitSuite.url + repoLfs + "batch";
HttpClient client = HttpClientBuilder.create().build();
HttpPost request = new HttpPost(initialUploadURL);
// add request header
request.addHeader(HttpHeaders.ACCEPT, FilestoreServlet.GIT_LFS_META_MIME);
request.addHeader(HttpHeaders.CONTENT_ENCODING, FilestoreServlet.GIT_LFS_META_MIME);
//Malformed JSON, comma instead of colon and unquoted strings
String content = String.format("{%s:%s,%s:[{%s:%s,%s,%d}]}",
"operation", "upload",
"objects",
"oid", blob.hash,
"size", blob.length);
HttpEntity entity = new ByteArrayEntity(content.getBytes("UTF-8"));
request.setEntity(entity);
HttpResponse response = client.execute(request);
String responseMessage = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
assertEquals(400, response.getStatusLine().getStatusCode());
String expectedError = String.format("{%s:%s,%s:%d}",
"\"message\"", "\"Malformed Git-LFS request\"",
"\"code\"", 400);
assertEquals(expectedError, responseMessage);
}
}