| 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); |
| } |
| |
| } |