diff options
Diffstat (limited to 'org.eclipse.jgit.lfs.test/tst/org')
8 files changed, 2287 insertions, 0 deletions
diff --git a/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/LfsConfigGitTest.java b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/LfsConfigGitTest.java new file mode 100644 index 0000000000..3ac41571a4 --- /dev/null +++ b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/LfsConfigGitTest.java @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2022, Matthias Fromme <mfromme@dspace.de> + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.lfs; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.ResetCommand.ResetType; +import org.eclipse.jgit.attributes.FilterCommand; +import org.eclipse.jgit.attributes.FilterCommandRegistry; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lfs.internal.LfsConnectionFactory; +import org.eclipse.jgit.lfs.lib.Constants; +import org.eclipse.jgit.lib.ConfigConstants; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.StoredConfig; +import org.eclipse.jgit.transport.http.HttpConnection; +import org.eclipse.jgit.util.HttpSupport; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * Test if the lfs config is used in the correct way during checkout. + * + * Two lfs-files are created, one that comes before .gitattributes and + * .lfsconfig in git order (".aaa.txt") and one that comes after ("zzz.txt"). + * + * During checkout/reset it is tested if the correct version of the lfs config + * is used. + * + * TODO: The current behavior seems a little bit strange/unintuitive. Some files + * are checked out before and some after the config files. This leads to the + * behavior, that during a single command the config changes. Since this seems + * to be the same way in native git, the behavior is accepted for now. + * + */ +public class LfsConfigGitTest extends RepositoryTestCase { + + private static final String SMUDGE_NAME = org.eclipse.jgit.lib.Constants.BUILTIN_FILTER_PREFIX + + Constants.ATTR_FILTER_DRIVER_PREFIX + + org.eclipse.jgit.lib.Constants.ATTR_FILTER_TYPE_SMUDGE; + + private static final String LFS_SERVER_URI1 = "https://lfs.server1/test/uri"; + + private static final String EXPECTED_SERVER_URL1 = LFS_SERVER_URI1 + + Protocol.OBJECTS_LFS_ENDPOINT; + + private static final String LFS_SERVER_URI2 = "https://lfs.server2/test/uri"; + + private static final String EXPECTED_SERVER_URL2 = LFS_SERVER_URI2 + + Protocol.OBJECTS_LFS_ENDPOINT; + + private static final String LFS_SERVER_URI3 = "https://lfs.server3/test/uri"; + + private static final String EXPECTED_SERVER_URL3 = LFS_SERVER_URI3 + + Protocol.OBJECTS_LFS_ENDPOINT; + + private static final String FAKE_LFS_POINTER1 = "version https://git-lfs.github.com/spec/v1\n" + + "oid sha256:6ce9fab52ee9a6c4c097def4e049c6acdeba44c99d26e83ba80adec1473c9b2d\n" + + "size 253952\n"; + + private static final String FAKE_LFS_POINTER2 = "version https://git-lfs.github.com/spec/v1\n" + + "oid sha256:a4b711cd989863ae2038758a62672138347abbbae4076a7ad3a545fda7d08f82\n" + + "size 67072\n"; + + private static List<String> checkoutURLs = new ArrayList<>(); + + static class SmudgeFilterMock extends FilterCommand { + public SmudgeFilterMock(Repository db, InputStream in, + OutputStream out) throws IOException { + super(in, out); + HttpConnection lfsServerConn = LfsConnectionFactory.getLfsConnection(db, + HttpSupport.METHOD_POST, Protocol.OPERATION_DOWNLOAD); + checkoutURLs.add(lfsServerConn.getURL().toString()); + } + + @Override + public int run() throws IOException { + // Stupid no impl + in.transferTo(out); + return -1; + } + } + + @BeforeClass + public static void installLfs() { + FilterCommandRegistry.register(SMUDGE_NAME, SmudgeFilterMock::new); + } + + @AfterClass + public static void removeLfs() { + FilterCommandRegistry.unregister(SMUDGE_NAME); + } + + private Git git; + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + git = new Git(db); + // commit something + writeTrashFile("Test.txt", "Hello world"); + git.add().addFilepattern("Test.txt").call(); + git.commit().setMessage("Initial commit").call(); + // prepare the config for LFS + StoredConfig config = git.getRepository().getConfig(); + config.setString("filter", "lfs", "smudge", SMUDGE_NAME); + config.setString(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF, "false"); + config.save(); + + fileBefore = null; + fileAfter = null; + configFile = null; + gitAttributesFile = null; + } + + File fileBefore; + + File fileAfter; + + File configFile; + + File gitAttributesFile; + + private void createLfsFiles(String lfsPointer) throws Exception { + //File to be checked out before lfs config + String fileNameBefore = ".aaa.txt"; + fileBefore = writeTrashFile(fileNameBefore, lfsPointer); + git.add().addFilepattern(fileNameBefore).call(); + + // File to be checked out after lfs config + String fileNameAfter = "zzz.txt"; + fileAfter = writeTrashFile(fileNameAfter, lfsPointer); + git.add().addFilepattern(fileNameAfter).call(); + + git.commit().setMessage("Commit LFS Pointer files").call(); + } + + + private String addLfsConfigFiles(String lfsServerUrl) throws Exception { + // Add config files to the repo + String lfsConfig1 = createLfsConfig(lfsServerUrl); + git.add().addFilepattern(Constants.DOT_LFS_CONFIG).call(); + // Modify gitattributes on second call, to force checkout too. + if (gitAttributesFile == null) { + gitAttributesFile = writeTrashFile(".gitattributes", + "*.txt filter=lfs"); + } else { + gitAttributesFile = writeTrashFile(".gitattributes", + "*.txt filter=lfs\n"); + } + + git.add().addFilepattern(".gitattributes").call(); + git.commit().setMessage("Commit config files").call(); + return lfsConfig1; + } + + private String createLfsConfig(String lfsServerUrl) throws IOException { + String lfsConfig1 = "[lfs]\n url = " + lfsServerUrl; + configFile = writeTrashFile(Constants.DOT_LFS_CONFIG, lfsConfig1); + return lfsConfig1; + } + + @Test + public void checkoutLfsObjects_reset() throws Exception { + createLfsFiles(FAKE_LFS_POINTER1); + String lfsConfig1 = addLfsConfigFiles(LFS_SERVER_URI1); + + // Delete files to force action on reset + assertTrue(configFile.delete()); + assertTrue(fileBefore.delete()); + assertTrue(fileAfter.delete()); + + assertTrue(gitAttributesFile.delete()); + + // create config file with different url + createLfsConfig(LFS_SERVER_URI3); + + checkoutURLs.clear(); + git.reset().setMode(ResetType.HARD).call(); + + checkFile(configFile, lfsConfig1); + checkFile(fileBefore, FAKE_LFS_POINTER1); + checkFile(fileAfter, FAKE_LFS_POINTER1); + + assertEquals(2, checkoutURLs.size()); + // TODO: Should may be EXPECTED_SERVR_URL1 + assertEquals(EXPECTED_SERVER_URL3, checkoutURLs.get(0)); + assertEquals(EXPECTED_SERVER_URL1, checkoutURLs.get(1)); + } + + @Test + public void checkoutLfsObjects_BranchSwitch() throws Exception { + // Create a new branch "URL1" and add config files + git.checkout().setCreateBranch(true).setName("URL1").call(); + + createLfsFiles(FAKE_LFS_POINTER1); + String lfsConfig1 = addLfsConfigFiles(LFS_SERVER_URI1); + + // Create a second new branch "URL2" and add config files + git.checkout().setCreateBranch(true).setName("URL2").call(); + + createLfsFiles(FAKE_LFS_POINTER2); + String lfsConfig2 = addLfsConfigFiles(LFS_SERVER_URI2); + + checkFile(configFile, lfsConfig2); + checkFile(fileBefore, FAKE_LFS_POINTER2); + checkFile(fileAfter, FAKE_LFS_POINTER2); + + checkoutURLs.clear(); + git.checkout().setName("URL1").call(); + + checkFile(configFile, lfsConfig1); + checkFile(fileBefore, FAKE_LFS_POINTER1); + checkFile(fileAfter, FAKE_LFS_POINTER1); + + assertEquals(2, checkoutURLs.size()); + // TODO: Should may be EXPECTED_SERVR_URL1 + assertEquals(EXPECTED_SERVER_URL2, checkoutURLs.get(0)); + assertEquals(EXPECTED_SERVER_URL1, checkoutURLs.get(1)); + + checkoutURLs.clear(); + git.checkout().setName("URL2").call(); + + checkFile(configFile, lfsConfig2); + checkFile(fileBefore, FAKE_LFS_POINTER2); + checkFile(fileAfter, FAKE_LFS_POINTER2); + + assertEquals(2, checkoutURLs.size()); + // TODO: Should may be EXPECTED_SERVR_URL2 + assertEquals(EXPECTED_SERVER_URL1, checkoutURLs.get(0)); + assertEquals(EXPECTED_SERVER_URL2, checkoutURLs.get(1)); + } + + @Test + public void checkoutLfsObjects_BranchSwitch_ModifiedLocal() + throws Exception { + + // Create a new branch "URL1" and add config files + git.checkout().setCreateBranch(true).setName("URL1").call(); + + createLfsFiles(FAKE_LFS_POINTER1); + addLfsConfigFiles(LFS_SERVER_URI1); + + // Create a second new branch "URL2" and add config files + git.checkout().setCreateBranch(true).setName("URL2").call(); + + createLfsFiles(FAKE_LFS_POINTER2); + addLfsConfigFiles(LFS_SERVER_URI1); + + // create config file with different url + assertTrue(configFile.delete()); + String lfsConfig3 = createLfsConfig(LFS_SERVER_URI3); + + checkFile(configFile, lfsConfig3); + checkFile(fileBefore, FAKE_LFS_POINTER2); + checkFile(fileAfter, FAKE_LFS_POINTER2); + + checkoutURLs.clear(); + git.checkout().setName("URL1").call(); + + checkFile(fileBefore, FAKE_LFS_POINTER1); + checkFile(fileAfter, FAKE_LFS_POINTER1); + checkFile(configFile, lfsConfig3); + + assertEquals(2, checkoutURLs.size()); + + assertEquals(EXPECTED_SERVER_URL3, checkoutURLs.get(0)); + assertEquals(EXPECTED_SERVER_URL3, checkoutURLs.get(1)); + + checkoutURLs.clear(); + git.checkout().setName("URL2").call(); + + checkFile(fileBefore, FAKE_LFS_POINTER2); + checkFile(fileAfter, FAKE_LFS_POINTER2); + checkFile(configFile, lfsConfig3); + + assertEquals(2, checkoutURLs.size()); + assertEquals(EXPECTED_SERVER_URL3, checkoutURLs.get(0)); + assertEquals(EXPECTED_SERVER_URL3, checkoutURLs.get(1)); + } +} diff --git a/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/LfsGitTest.java b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/LfsGitTest.java new file mode 100644 index 0000000000..3e83c8ef49 --- /dev/null +++ b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/LfsGitTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2021, 2022 Thomas Wolf <thomas.wolf@paranor.ch> and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.lfs; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.ResetCommand.ResetType; +import org.eclipse.jgit.attributes.FilterCommandRegistry; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lfs.lib.Constants; +import org.eclipse.jgit.lib.StoredConfig; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class LfsGitTest extends RepositoryTestCase { + + private static final String SMUDGE_NAME = org.eclipse.jgit.lib.Constants.BUILTIN_FILTER_PREFIX + + Constants.ATTR_FILTER_DRIVER_PREFIX + + org.eclipse.jgit.lib.Constants.ATTR_FILTER_TYPE_SMUDGE; + + private static final String CLEAN_NAME = org.eclipse.jgit.lib.Constants.BUILTIN_FILTER_PREFIX + + Constants.ATTR_FILTER_DRIVER_PREFIX + + org.eclipse.jgit.lib.Constants.ATTR_FILTER_TYPE_CLEAN; + + @BeforeClass + public static void installLfs() { + FilterCommandRegistry.register(SMUDGE_NAME, SmudgeFilter.FACTORY); + FilterCommandRegistry.register(CLEAN_NAME, CleanFilter.FACTORY); + } + + @AfterClass + public static void removeLfs() { + FilterCommandRegistry.unregister(SMUDGE_NAME); + FilterCommandRegistry.unregister(CLEAN_NAME); + } + + private Git git; + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + git = new Git(db); + // commit something + writeTrashFile("Test.txt", "Hello world"); + git.add().addFilepattern("Test.txt").call(); + git.commit().setMessage("Initial commit").call(); + // prepare the config for LFS + StoredConfig config = git.getRepository().getConfig(); + config.setString("filter", "lfs", "clean", CLEAN_NAME); + config.setString("filter", "lfs", "smudge", SMUDGE_NAME); + config.save(); + } + + @Test + public void testBranchSwitch() throws Exception { + git.branchCreate().setName("abranch").call(); + git.checkout().setName("abranch").call(); + File aFile = writeTrashFile("a.bin", "aaa"); + writeTrashFile(".gitattributes", "a.bin filter=lfs"); + git.add().addFilepattern(".").call(); + git.commit().setMessage("acommit").call(); + git.checkout().setName("master").call(); + git.branchCreate().setName("bbranch").call(); + git.checkout().setName("bbranch").call(); + File bFile = writeTrashFile("b.bin", "bbb"); + writeTrashFile(".gitattributes", "b.bin filter=lfs"); + git.add().addFilepattern(".").call(); + git.commit().setMessage("bcommit").call(); + git.checkout().setName("abranch").call(); + checkFile(aFile, "aaa"); + git.checkout().setName("bbranch").call(); + checkFile(bFile, "bbb"); + } + + @Test + public void checkoutNonLfsPointer() throws Exception { + String content = "size_t\nsome_function(void* ptr);\n"; + File smallFile = writeTrashFile("Test.txt", content); + StringBuilder largeContent = new StringBuilder( + LfsPointer.SIZE_THRESHOLD * 4); + while (largeContent.length() < LfsPointer.SIZE_THRESHOLD * 4) { + largeContent.append(content); + } + File largeFile = writeTrashFile("large.txt", largeContent.toString()); + fsTick(largeFile); + git.add().addFilepattern("Test.txt").addFilepattern("large.txt").call(); + git.commit().setMessage("Text files").call(); + writeTrashFile(".gitattributes", "*.txt filter=lfs"); + git.add().addFilepattern(".gitattributes").call(); + git.commit().setMessage("attributes").call(); + assertTrue(smallFile.delete()); + assertTrue(largeFile.delete()); + // This reset will run the two text files through the smudge filter + git.reset().setMode(ResetType.HARD).call(); + assertTrue(smallFile.exists()); + assertTrue(largeFile.exists()); + checkFile(smallFile, content); + checkFile(largeFile, largeContent.toString()); + // Modify the large file + largeContent.append(content); + writeTrashFile("large.txt", largeContent.toString()); + // This should convert largeFile to an LFS pointer + git.add().addFilepattern("large.txt").call(); + git.commit().setMessage("Large modified").call(); + String lfsPtr = "version https://git-lfs.github.com/spec/v1\n" + + "oid sha256:d041ab19bd7edd899b3c0450d0f61819f96672f0b22d26c9753abc62e1261614\n" + + "size 858\n"; + assertEquals("[.gitattributes, mode:100644, content:*.txt filter=lfs]" + + "[Test.txt, mode:100644, content:" + content + ']' + + "[large.txt, mode:100644, content:" + lfsPtr + ']', + indexState(CONTENT)); + // Verify the file has been saved + File savedFile = new File(db.getDirectory(), "lfs"); + savedFile = new File(savedFile, "objects"); + savedFile = new File(savedFile, "d0"); + savedFile = new File(savedFile, "41"); + savedFile = new File(savedFile, + "d041ab19bd7edd899b3c0450d0f61819f96672f0b22d26c9753abc62e1261614"); + String saved = new String(Files.readAllBytes(savedFile.toPath()), + StandardCharsets.UTF_8); + assertEquals(saved, largeContent.toString()); + + assertTrue(smallFile.delete()); + assertTrue(largeFile.delete()); + git.reset().setMode(ResetType.HARD).call(); + assertTrue(smallFile.exists()); + assertTrue(largeFile.exists()); + checkFile(smallFile, content); + checkFile(largeFile, largeContent.toString()); + assertEquals("[.gitattributes, mode:100644, content:*.txt filter=lfs]" + + "[Test.txt, mode:100644, content:" + content + ']' + + "[large.txt, mode:100644, content:" + lfsPtr + ']', + indexState(CONTENT)); + git.add().addFilepattern("Test.txt").call(); + git.commit().setMessage("Small committed again").call(); + String lfsPtrSmall = "version https://git-lfs.github.com/spec/v1\n" + + "oid sha256:9110463275fb0e2f0e9fdeaf84e598e62915666161145cf08927079119cc7814\n" + + "size 33\n"; + assertEquals("[.gitattributes, mode:100644, content:*.txt filter=lfs]" + + "[Test.txt, mode:100644, content:" + lfsPtrSmall + ']' + + "[large.txt, mode:100644, content:" + lfsPtr + ']', + indexState(CONTENT)); + + assertTrue(git.status().call().isClean()); + } +} diff --git a/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/internal/LfsConnectionFactoryTest.java b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/internal/LfsConnectionFactoryTest.java new file mode 100644 index 0000000000..ee8e893b3e --- /dev/null +++ b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/internal/LfsConnectionFactoryTest.java @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2022 Nail Samatov <sanail@yandex.ru> and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.lfs.internal; + +import static org.eclipse.jgit.lib.Constants.DEFAULT_REMOTE_NAME; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.RemoteAddCommand; +import org.eclipse.jgit.attributes.FilterCommandRegistry; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lfs.CleanFilter; +import org.eclipse.jgit.lfs.Protocol; +import org.eclipse.jgit.lfs.SmudgeFilter; +import org.eclipse.jgit.lfs.errors.LfsConfigInvalidException; +import org.eclipse.jgit.lfs.lib.Constants; +import org.eclipse.jgit.lib.ConfigConstants; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.StoredConfig; +import org.eclipse.jgit.transport.URIish; +import org.eclipse.jgit.transport.http.HttpConnection; +import org.eclipse.jgit.util.HttpSupport; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class LfsConnectionFactoryTest extends RepositoryTestCase { + + private static final String SMUDGE_NAME = org.eclipse.jgit.lib.Constants.BUILTIN_FILTER_PREFIX + + Constants.ATTR_FILTER_DRIVER_PREFIX + + org.eclipse.jgit.lib.Constants.ATTR_FILTER_TYPE_SMUDGE; + + private static final String CLEAN_NAME = org.eclipse.jgit.lib.Constants.BUILTIN_FILTER_PREFIX + + Constants.ATTR_FILTER_DRIVER_PREFIX + + org.eclipse.jgit.lib.Constants.ATTR_FILTER_TYPE_CLEAN; + + private final static String LFS_SERVER_URL1 = "https://lfs.server1/test/uri"; + + private final static String LFS_SERVER_URL2 = "https://lfs.server2/test/uri"; + + private final static String ORIGIN_URL = "https://git.server/test/uri"; + + private Git git; + + @BeforeClass + public static void installLfs() { + FilterCommandRegistry.register(SMUDGE_NAME, SmudgeFilter.FACTORY); + FilterCommandRegistry.register(CLEAN_NAME, CleanFilter.FACTORY); + } + + @AfterClass + public static void removeLfs() { + FilterCommandRegistry.unregister(SMUDGE_NAME); + FilterCommandRegistry.unregister(CLEAN_NAME); + } + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + git = new Git(db); + + // Just to have a non empty repo + writeTrashFile("Test.txt", "Hello world from the LFS Factory Test"); + git.add().addFilepattern("Test.txt").call(); + git.commit().setMessage("Initial commit").call(); + } + + @Test + public void lfsUrlFromRemoteUrlWithDotGit() throws Exception { + addRemoteUrl("https://localhost/repo.git"); + checkLfsUrl("https://localhost/repo.git/info/lfs"); + } + + @Test + public void lfsUrlFromRemoteUrlWithoutDotGit() throws Exception { + addRemoteUrl("https://localhost/repo"); + checkLfsUrl("https://localhost/repo.git/info/lfs"); + } + + @Test + public void lfsUrlFromLocalConfig() throws Exception { + addRemoteUrl("https://localhost/repo"); + + @SuppressWarnings("restriction") + StoredConfig cfg = db.getConfig(); + cfg.setString(ConfigConstants.CONFIG_SECTION_LFS, + null, + ConfigConstants.CONFIG_KEY_URL, + "https://localhost/repo/lfs"); + cfg.save(); + + checkLfsUrl("https://localhost/repo/lfs"); + } + + @Test + public void lfsUrlFromOriginConfig() throws Exception { + addRemoteUrl("https://localhost/repo"); + + @SuppressWarnings("restriction") + StoredConfig cfg = db.getConfig(); + cfg.setString(ConfigConstants.CONFIG_SECTION_LFS, + org.eclipse.jgit.lib.Constants.DEFAULT_REMOTE_NAME, + ConfigConstants.CONFIG_KEY_URL, + "https://localhost/repo/lfs"); + cfg.save(); + + checkLfsUrl("https://localhost/repo/lfs"); + } + + @Test + public void lfsUrlNotConfigured() throws Exception { + assertThrows(LfsConfigInvalidException.class, + () -> LfsConnectionFactory.getLfsConnection(db, + HttpSupport.METHOD_POST, Protocol.OPERATION_DOWNLOAD)); + } + + @Test + public void checkGetLfsConnection_lfsurl_lfsconfigFromWorkingDir() + throws Exception { + writeLfsConfig(); + checkLfsUrl(LFS_SERVER_URL1); + } + + @Test + public void checkGetLfsConnection_lfsurl_lfsconfigFromIndex() + throws Exception { + writeLfsConfig(); + git.add().addFilepattern(Constants.DOT_LFS_CONFIG).call(); + deleteTrashFile(Constants.DOT_LFS_CONFIG); + checkLfsUrl(LFS_SERVER_URL1); + } + + @Test + public void checkGetLfsConnection_lfsurl_lfsconfigFromHEAD() + throws Exception { + writeLfsConfig(); + git.add().addFilepattern(Constants.DOT_LFS_CONFIG).call(); + git.commit().setMessage("Commit LFS Config").call(); + + /* + * reading .lfsconfig from HEAD seems only testable using a bare repo, + * since otherwise working tree or index are used + */ + File directory = createTempDirectory("testBareRepo"); + try (Repository bareRepoDb = Git.cloneRepository() + .setDirectory(directory) + .setURI(db.getDirectory().toURI().toString()).setBare(true) + .call().getRepository()) { + + checkLfsUrl(LFS_SERVER_URL1); + } + } + + @Test + public void checkGetLfsConnection_remote_lfsconfigFromWorkingDir() + throws Exception { + addRemoteUrl(ORIGIN_URL); + writeLfsConfig(LFS_SERVER_URL1, "lfs", DEFAULT_REMOTE_NAME, "url"); + checkLfsUrl(LFS_SERVER_URL1); + } + + /** + * Test the config file precedence. + * + * Checking only with the local repository config is sufficient since from + * that point the "normal" precedence is used. + * + * @throws Exception + */ + @Test + public void checkGetLfsConnection_ConfigFilePrecedence_lfsconfigFromWorkingDir() + throws Exception { + writeLfsConfig(); + checkLfsUrl(LFS_SERVER_URL1); + + StoredConfig config = git.getRepository().getConfig(); + config.setString(ConfigConstants.CONFIG_SECTION_LFS, null, + ConfigConstants.CONFIG_KEY_URL, LFS_SERVER_URL2); + config.save(); + + checkLfsUrl(LFS_SERVER_URL2); + } + + @Test + public void checkGetLfsConnection_InvalidLfsConfig_WorkingDir() + throws Exception { + writeInvalidLfsConfig(); + LfsConfigInvalidException actualException = assertThrows( + LfsConfigInvalidException.class, () -> { + LfsConnectionFactory.getLfsConnection(db, HttpSupport.METHOD_POST, + Protocol.OPERATION_DOWNLOAD); + }); + assertTrue(getStackTrace(actualException) + .contains("Invalid line in config file")); + } + + @Test + public void checkGetLfsConnection_InvalidLfsConfig_Index() + throws Exception { + writeInvalidLfsConfig(); + git.add().addFilepattern(Constants.DOT_LFS_CONFIG).call(); + deleteTrashFile(Constants.DOT_LFS_CONFIG); + LfsConfigInvalidException actualException = assertThrows( + LfsConfigInvalidException.class, () -> { + LfsConnectionFactory.getLfsConnection(db, HttpSupport.METHOD_POST, + Protocol.OPERATION_DOWNLOAD); + }); + assertTrue(getStackTrace(actualException) + .contains("Invalid line in config file")); + } + + @Test + public void checkGetLfsConnection_InvalidLfsConfig_HEAD() throws Exception { + writeInvalidLfsConfig(); + git.add().addFilepattern(Constants.DOT_LFS_CONFIG).call(); + git.commit().setMessage("Commit LFS Config").call(); + + /* + * reading .lfsconfig from HEAD seems only testable using a bare repo, + * since otherwise working tree or index are used + */ + File directory = createTempDirectory("testBareRepo"); + try (Repository bareRepoDb = Git.cloneRepository() + .setDirectory(directory) + .setURI(db.getDirectory().toURI().toString()).setBare(true) + .call().getRepository()) { + LfsConfigInvalidException actualException = assertThrows( + LfsConfigInvalidException.class, + () -> { + LfsConnectionFactory.getLfsConnection(db, + HttpSupport.METHOD_POST, + Protocol.OPERATION_DOWNLOAD); + }); + assertTrue(getStackTrace(actualException) + .contains("Invalid line in config file")); + } + } + + private void addRemoteUrl(String remotUrl) throws Exception { + RemoteAddCommand add = git.remoteAdd(); + add.setUri(new URIish(remotUrl)); + add.setName(org.eclipse.jgit.lib.Constants.DEFAULT_REMOTE_NAME); + add.call(); + } + + /** + * Returns the stack trace of the provided exception as string + * + * @param actualException + * @return The exception stack trace as string + */ + private String getStackTrace(Exception actualException) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + actualException.printStackTrace(pw); + return sw.toString(); + } + + private void writeLfsConfig() throws IOException { + writeLfsConfig(LFS_SERVER_URL1, "lfs", "url"); + } + + private void writeLfsConfig(String lfsUrl, String section, String name) + throws IOException { + writeLfsConfig(lfsUrl, section, null, name); + } + + /* + * Write simple lfs config with single entry. Do not use FileBasedConfig to + * avoid introducing new dependency (for now). + */ + private void writeLfsConfig(String lfsUrl, String section, + String subsection, String name) throws IOException { + StringBuilder config = new StringBuilder(); + config.append("["); + config.append(section); + if (subsection != null) { + config.append(" \""); + config.append(subsection); + config.append("\""); + } + config.append("]\n"); + config.append(" "); + config.append(name); + config.append(" = "); + config.append(lfsUrl); + writeTrashFile(Constants.DOT_LFS_CONFIG, config.toString()); + } + + private void writeInvalidLfsConfig() throws IOException { + writeTrashFile(Constants.DOT_LFS_CONFIG, + "{lfs]\n url = " + LFS_SERVER_URL1); + } + + private void checkLfsUrl(String lfsUrl) throws IOException { + HttpConnection lfsServerConn; + lfsServerConn = LfsConnectionFactory.getLfsConnection(db, + HttpSupport.METHOD_POST, Protocol.OPERATION_DOWNLOAD); + + assertEquals(lfsUrl + Protocol.OBJECTS_LFS_ENDPOINT, + lfsServerConn.getURL().toString()); + } +} diff --git a/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/AbbreviatedLongObjectIdTest.java b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/AbbreviatedLongObjectIdTest.java new file mode 100644 index 0000000000..81c7f14e81 --- /dev/null +++ b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/AbbreviatedLongObjectIdTest.java @@ -0,0 +1,564 @@ +/* + * Copyright (C) 2015, Matthias Sohn <matthias.sohn@sap.com> and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.eclipse.jgit.lfs.lib; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.eclipse.jgit.lfs.test.LongObjectIdTestUtils; +import org.junit.Test; + +/* + * Ported to SHA-256 from org.eclipse.jgit.lib.AbbreviatedObjectIdTest + */ +public class AbbreviatedLongObjectIdTest { + @Test + public void testEmpty_FromByteArray() { + final AbbreviatedLongObjectId i; + i = AbbreviatedLongObjectId.fromString(new byte[] {}, 0, 0); + assertNotNull(i); + assertEquals(0, i.length()); + assertFalse(i.isComplete()); + assertEquals("", i.name()); + } + + @Test + public void testEmpty_FromString() { + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId + .fromString(""); + assertNotNull(i); + assertEquals(0, i.length()); + assertFalse(i.isComplete()); + assertEquals("", i.name()); + } + + @Test + public void testFull_FromByteArray() { + final String s = "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final byte[] b = org.eclipse.jgit.lib.Constants.encodeASCII(s); + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId.fromString(b, + 0, b.length); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertTrue(i.isComplete()); + assertEquals(s, i.name()); + + final LongObjectId f = i.toLongObjectId(); + assertNotNull(f); + assertEquals(LongObjectId.fromString(s), f); + assertEquals(f.hashCode(), i.hashCode()); + } + + @Test + public void testFull_FromString() { + final String s = "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertTrue(i.isComplete()); + assertEquals(s, i.name()); + + final LongObjectId f = i.toLongObjectId(); + assertNotNull(f); + assertEquals(LongObjectId.fromString(s), f); + assertEquals(f.hashCode(), i.hashCode()); + } + + @Test + public void test1_FromString() { + final String s = "2"; + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toLongObjectId()); + } + + @Test + public void test2_FromString() { + final String s = "27"; + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toLongObjectId()); + } + + @Test + public void test3_FromString() { + final String s = "27e"; + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toLongObjectId()); + } + + @Test + public void test4_FromString() { + final String s = "27e1"; + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toLongObjectId()); + } + + @Test + public void test5_FromString() { + final String s = "27e15"; + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toLongObjectId()); + } + + @Test + public void test6_FromString() { + final String s = "27e15b"; + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toLongObjectId()); + } + + @Test + public void test7_FromString() { + final String s = "27e15b7"; + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toLongObjectId()); + } + + @Test + public void test8_FromString() { + final String s = "27e15b72"; + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toLongObjectId()); + } + + @Test + public void test9_FromString() { + final String s = "27e15b729"; + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toLongObjectId()); + } + + @Test + public void test15_FromString() { + final String s = "27e15b72937fc8f"; + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toLongObjectId()); + } + + @Test + public void test16_FromString() { + final String s = "27e15b72937fc8f5"; + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toLongObjectId()); + } + + @Test + public void test17_FromString() { + final String s = "27e15b72937fc8f55"; + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toLongObjectId()); + } + + @Test + public void test33_FromString() { + final String s = "27e15b72937fc8f558da24ac3d50ec203"; + final AbbreviatedLongObjectId i = AbbreviatedLongObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toLongObjectId()); + } + + @Test + public void testEquals_Short() { + final String s = "27e15b72"; + final AbbreviatedLongObjectId a = AbbreviatedLongObjectId.fromString(s); + final AbbreviatedLongObjectId b = AbbreviatedLongObjectId.fromString(s); + assertNotSame(a, b); + assertTrue(a.hashCode() == b.hashCode()); + assertEquals(b, a); + assertEquals(a, b); + } + + @Test + public void testEquals_Full() { + final String s = "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final AbbreviatedLongObjectId a = AbbreviatedLongObjectId.fromString(s); + final AbbreviatedLongObjectId b = AbbreviatedLongObjectId.fromString(s); + assertNotSame(a, b); + assertTrue(a.hashCode() == b.hashCode()); + assertEquals(b, a); + assertEquals(a, b); + } + + @Test + public void testNotEquals_SameLength() { + final String sa = "27e15b72"; + final String sb = "27e15b7f"; + final AbbreviatedLongObjectId a = AbbreviatedLongObjectId + .fromString(sa); + final AbbreviatedLongObjectId b = AbbreviatedLongObjectId + .fromString(sb); + assertFalse(a.equals(b)); + assertFalse(b.equals(a)); + } + + @Test + public void testNotEquals_DiffLength() { + final String sa = "27e15b72abcd"; + final String sb = "27e15b72"; + final AbbreviatedLongObjectId a = AbbreviatedLongObjectId + .fromString(sa); + final AbbreviatedLongObjectId b = AbbreviatedLongObjectId + .fromString(sb); + assertFalse(a.equals(b)); + assertFalse(b.equals(a)); + } + + @Test + public void testPrefixCompare_Full() { + final String s1 = "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final AbbreviatedLongObjectId a = AbbreviatedLongObjectId + .fromString(s1); + final LongObjectId i1 = LongObjectId.fromString(s1); + assertEquals(0, a.prefixCompare(i1)); + assertTrue(i1.startsWith(a)); + + final String s2 = "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b11"; + final LongObjectId i2 = LongObjectId.fromString(s2); + assertTrue(a.prefixCompare(i2) < 0); + assertFalse(i2.startsWith(a)); + + final String s3 = "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b0f"; + final LongObjectId i3 = LongObjectId.fromString(s3); + assertTrue(a.prefixCompare(i3) > 0); + assertFalse(i3.startsWith(a)); + } + + @Test + public void testPrefixCompare_1() { + final String sa = "2"; + final AbbreviatedLongObjectId a = AbbreviatedLongObjectId + .fromString(sa); + + final String s1 = "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final LongObjectId i1 = LongObjectId.fromString(s1); + assertEquals(0, a.prefixCompare(i1)); + assertTrue(i1.startsWith(a)); + + final String s2 = "37e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final LongObjectId i2 = LongObjectId.fromString(s2); + assertTrue(a.prefixCompare(i2) < 0); + assertFalse(i2.startsWith(a)); + + final String s3 = "17e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final LongObjectId i3 = LongObjectId.fromString(s3); + assertTrue(a.prefixCompare(i3) > 0); + assertFalse(i3.startsWith(a)); + } + + @Test + public void testPrefixCompare_15() { + final String sa = "27e15b72937fc8f"; + final AbbreviatedLongObjectId a = AbbreviatedLongObjectId + .fromString(sa); + + final String s1 = "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final LongObjectId i1 = LongObjectId.fromString(s1); + assertEquals(0, a.prefixCompare(i1)); + assertTrue(i1.startsWith(a)); + + final String s2 = "27e15b72937fc90558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final LongObjectId i2 = LongObjectId.fromString(s2); + assertTrue(a.prefixCompare(i2) < 0); + assertFalse(i2.startsWith(a)); + + final String s3 = "27e15b72937fc8e558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final LongObjectId i3 = LongObjectId.fromString(s3); + assertTrue(a.prefixCompare(i3) > 0); + assertFalse(i3.startsWith(a)); + } + + @Test + public void testPrefixCompare_16() { + final String sa = "27e15b72937fc8f5"; + final AbbreviatedLongObjectId a = AbbreviatedLongObjectId + .fromString(sa); + + final String s1 = "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final LongObjectId i1 = LongObjectId.fromString(s1); + assertEquals(0, a.prefixCompare(i1)); + assertTrue(i1.startsWith(a)); + + final String s2 = "27e15b72937fc8f658da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final LongObjectId i2 = LongObjectId.fromString(s2); + assertTrue(a.prefixCompare(i2) < 0); + assertFalse(i2.startsWith(a)); + + final String s3 = "27e15b72937fc8f458da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final LongObjectId i3 = LongObjectId.fromString(s3); + assertTrue(a.prefixCompare(i3) > 0); + assertFalse(i3.startsWith(a)); + } + + @Test + public void testPrefixCompare_17() { + final String sa = "27e15b72937fc8f55"; + final AbbreviatedLongObjectId a = AbbreviatedLongObjectId + .fromString(sa); + + final String s1 = "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final LongObjectId i1 = LongObjectId.fromString(s1); + assertEquals(0, a.prefixCompare(i1)); + assertTrue(i1.startsWith(a)); + + final String s2 = "27e15b72937fc8f568da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final LongObjectId i2 = LongObjectId.fromString(s2); + assertTrue(a.prefixCompare(i2) < 0); + assertFalse(i2.startsWith(a)); + + final String s3 = "27e15b72937fc8f548da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final LongObjectId i3 = LongObjectId.fromString(s3); + assertTrue(a.prefixCompare(i3) > 0); + assertFalse(i3.startsWith(a)); + } + + @Test + public void testPrefixCompare_33() { + final String sa = "27e15b72937fc8f558da24ac3d50ec203"; + final AbbreviatedLongObjectId a = AbbreviatedLongObjectId + .fromString(sa); + + final String s1 = "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + final LongObjectId i1 = LongObjectId.fromString(s1); + assertEquals(0, a.prefixCompare(i1)); + assertTrue(i1.startsWith(a)); + + final String s2 = "27e15b72937fc8f558da24ac3d50ec20402a4cf21e33b87ae8e4ce90e89c4b10"; + final LongObjectId i2 = LongObjectId.fromString(s2); + assertTrue(a.prefixCompare(i2) < 0); + assertFalse(i2.startsWith(a)); + + final String s3 = "27e15b72937fc8f558da24ac3d50ec20202a4cf21e33b87ae8e4ce90e89c4b10"; + final LongObjectId i3 = LongObjectId.fromString(s3); + assertTrue(a.prefixCompare(i3) > 0); + assertFalse(i3.startsWith(a)); + } + + @Test + public void testIsId() { + // These are all too short. + assertFalse(AbbreviatedLongObjectId.isId("")); + assertFalse(AbbreviatedLongObjectId.isId("a")); + + // These are too long. + assertFalse(AbbreviatedLongObjectId.isId(LongObjectId + .fromString( + "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10") + .name() + "0")); + assertFalse(AbbreviatedLongObjectId.isId(LongObjectId + .fromString( + "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10") + .name() + "c0ffee")); + + // These contain non-hex characters. + assertFalse(AbbreviatedLongObjectId.isId("01notahexstring")); + + // These should all work. + assertTrue(AbbreviatedLongObjectId.isId("ab")); + assertTrue(AbbreviatedLongObjectId.isId("abc")); + assertTrue(AbbreviatedLongObjectId.isId("abcd")); + assertTrue(AbbreviatedLongObjectId.isId("abcd0")); + assertTrue(AbbreviatedLongObjectId.isId("abcd09")); + assertTrue(AbbreviatedLongObjectId.isId(LongObjectId + .fromString( + "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10") + .name())); + } + + @Test + public void testAbbreviate() { + AnyLongObjectId id = LongObjectIdTestUtils.hash("test"); + assertEquals( + "abbreviated id should match the id it was abbreviated from", 0, + id.abbreviate(10).prefixCompare(id)); + } + + @Test + public void testFromStringByteWrongLength() { + byte[] buf = new byte[65]; + try { + AbbreviatedLongObjectId.fromString(buf, 0, 65); + fail("expected IllegalArgumentException for too long AbbreviatedLongObjectId"); + } catch (IllegalArgumentException e) { + // expected + } + } + + @Test + public void testFromStringWrongLength() { + AnyLongObjectId id = LongObjectIdTestUtils.hash("test"); + try { + AbbreviatedLongObjectId.fromString(id.name() + "c0ffee"); + fail("expected IllegalArgumentException for too long AbbreviatedLongObjectId"); + } catch (IllegalArgumentException e) { + // expected + } + } + + @Test + public void testFromLongObjectId() { + AnyLongObjectId id = LongObjectIdTestUtils.hash("test"); + assertEquals(0, + AbbreviatedLongObjectId.fromLongObjectId(id).prefixCompare(id)); + } + + @Test + public void testPrefixCompareByte() { + AnyLongObjectId id = LongObjectId.fromString( + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"); + byte[] buf = new byte[32]; + id.copyRawTo(buf, 0); + + AbbreviatedLongObjectId a = id.abbreviate(62); + assertEquals(0, a.prefixCompare(buf, 0)); + + a = LongObjectId + .fromString( + "0023456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef") + .abbreviate(16); + assertEquals(-1, a.prefixCompare(buf, 0)); + a = LongObjectId + .fromString( + "0123456789abcdef0023456789abcdef0123456789abcdef0123456789abcdef") + .abbreviate(32); + assertEquals(-1, a.prefixCompare(buf, 0)); + a = LongObjectId + .fromString( + "0123456789abcdef0123456789abcdef0023456789abcdef0123456789abcdef") + .abbreviate(48); + assertEquals(-1, a.prefixCompare(buf, 0)); + a = LongObjectId + .fromString( + "0123456789abcdef0123456789abcdef0123456789abcdef0023456789abcdef") + .abbreviate(64); + assertEquals(-1, a.prefixCompare(buf, 0)); + + a = LongObjectId + .fromString( + "1123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef") + .abbreviate(16); + assertEquals(1, a.prefixCompare(buf, 0)); + a = LongObjectId + .fromString( + "0123456789abcdef1123456789abcdef0123456789abcdef0123456789abcdef") + .abbreviate(32); + assertEquals(1, a.prefixCompare(buf, 0)); + a = LongObjectId + .fromString( + "0123456789abcdef0123456789abcdef1123456789abcdef0123456789abcdef") + .abbreviate(48); + assertEquals(1, a.prefixCompare(buf, 0)); + a = LongObjectId + .fromString( + "0123456789abcdef0123456789abcdef0123456789abcdef1123456789abcdef") + .abbreviate(64); + assertEquals(1, a.prefixCompare(buf, 0)); + } + + @Test + public void testPrefixCompareLong() { + AnyLongObjectId id = new LongObjectId(1L, 2L, 3L, 4L); + long[] buf = new long[4]; + id.copyRawTo(buf, 0); + + AbbreviatedLongObjectId a = id.abbreviate(62); + assertEquals(0, a.prefixCompare(buf, 0)); + + a = new LongObjectId(0L, 2L, 3L, 4L).abbreviate(16); + assertEquals(-1, a.prefixCompare(buf, 0)); + a = new LongObjectId(1L, 1L, 3L, 4L).abbreviate(32); + assertEquals(-1, a.prefixCompare(buf, 0)); + a = new LongObjectId(1L, 2L, 2L, 4L).abbreviate(48); + assertEquals(-1, a.prefixCompare(buf, 0)); + a = new LongObjectId(1L, 2L, 3L, 3L).abbreviate(64); + assertEquals(-1, a.prefixCompare(buf, 0)); + + a = new LongObjectId(2L, 2L, 3L, 4L).abbreviate(16); + assertEquals(1, a.prefixCompare(buf, 0)); + a = new LongObjectId(1L, 3L, 3L, 4L).abbreviate(32); + assertEquals(1, a.prefixCompare(buf, 0)); + a = new LongObjectId(1L, 2L, 4L, 4L).abbreviate(48); + assertEquals(1, a.prefixCompare(buf, 0)); + a = new LongObjectId(1L, 2L, 3L, 5L).abbreviate(64); + assertEquals(1, a.prefixCompare(buf, 0)); + } + + @Test + public void testGetFirstByte() { + AnyLongObjectId id = LongObjectId.fromString( + "f423456789abcdef0123456789abcdef0123456789abcdef1123456789abcdef"); + AbbreviatedLongObjectId a = id.abbreviate(10); + assertEquals(0xf4, a.getFirstByte()); + assertEquals(id.getFirstByte(), a.getFirstByte()); + } + + @SuppressWarnings("unlikely-arg-type") + @Test + public void testNotEquals() { + AbbreviatedLongObjectId a = new LongObjectId(1L, 2L, 3L, 4L) + .abbreviate(10); + assertFalse(a.equals("different")); + } +} diff --git a/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LFSPointerTest.java b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LFSPointerTest.java new file mode 100644 index 0000000000..da78b28d90 --- /dev/null +++ b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LFSPointerTest.java @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2016, Christian Halstrick <christian.halstrick@sap.com> and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.eclipse.jgit.lfs.lib; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import org.eclipse.jgit.lfs.LfsPointer; +import org.junit.Test; + +/* + * Test LfsPointer file abstraction + */ +public class LFSPointerTest { + + private static final String TEST_SHA256 = "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10"; + + @Test + public void testEncoding() throws IOException { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer ptr = new LfsPointer(id, 4); + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + ptr.encode(baos); + assertEquals( + "version https://git-lfs.github.com/spec/v1\noid sha256:" + + TEST_SHA256 + "\nsize 4\n", + baos.toString(UTF_8.name())); + } + } + + @Test + public void testReadValidLfsPointer() throws Exception { + String ptr = "version https://git-lfs.github.com/spec/v1\n" + + "oid sha256:" + TEST_SHA256 + '\n' + + "size 4\n"; + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + try (ByteArrayInputStream in = new ByteArrayInputStream( + ptr.getBytes(UTF_8))) { + assertEquals(lfs, LfsPointer.parseLfsPointer(in)); + } + } + + @Test + public void testReadValidLfsPointerUnordered() throws Exception { + // This is actually not allowed per the spec, but JGit accepts it + // anyway. + String ptr = "version https://git-lfs.github.com/spec/v1\n" + + "size 4\n" + + "oid sha256:" + TEST_SHA256 + '\n'; + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + try (ByteArrayInputStream in = new ByteArrayInputStream( + ptr.getBytes(UTF_8))) { + assertEquals(lfs, LfsPointer.parseLfsPointer(in)); + } + } + + @Test + public void testReadValidLfsPointerVersionNotFirst() throws Exception { + // This is actually not allowed per the spec, but JGit accepts it + // anyway. + String ptr = "oid sha256:" + TEST_SHA256 + '\n' + + "size 4\n" + + "version https://git-lfs.github.com/spec/v1\n"; + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + try (ByteArrayInputStream in = new ByteArrayInputStream( + ptr.getBytes(UTF_8))) { + assertEquals(lfs, LfsPointer.parseLfsPointer(in)); + } + } + + @Test + public void testReadInvalidLfsPointer() throws Exception { + String cSource = "size_t someFunction(void *ptr); // Fake C source\n"; + try (ByteArrayInputStream in = new ByteArrayInputStream( + cSource.getBytes(UTF_8))) { + assertNull("Is not a LFS pointer", LfsPointer.parseLfsPointer(in)); + } + } + + @Test + public void testReadInvalidLfsPointer2() throws Exception { + String cSource = "size_t\nsomeFunction(void *ptr);\n// Fake C source\n"; + try (ByteArrayInputStream in = new ByteArrayInputStream( + cSource.getBytes(UTF_8))) { + assertNull("Is not a LFS pointer", LfsPointer.parseLfsPointer(in)); + } + } + + @Test + public void testReadInValidLfsPointerVersionWrong() throws Exception { + String ptr = "version https://git-lfs.example.org/spec/v1\n" + + "oid sha256:" + TEST_SHA256 + '\n' + + "size 4\n"; + try (ByteArrayInputStream in = new ByteArrayInputStream( + ptr.getBytes(UTF_8))) { + assertNull("Is not a LFS pointer", LfsPointer.parseLfsPointer(in)); + } + } + + @Test + public void testReadInValidLfsPointerVersionTwice() throws Exception { + String ptr = "version https://git-lfs.github.com/spec/v1\n" + + "version https://git-lfs.github.com/spec/v1\n" + + "oid sha256:" + TEST_SHA256 + '\n' + + "size 4\n"; + try (ByteArrayInputStream in = new ByteArrayInputStream( + ptr.getBytes(UTF_8))) { + assertNull("Is not a LFS pointer", LfsPointer.parseLfsPointer(in)); + } + } + + @Test + public void testReadInValidLfsPointerVersionTwice2() throws Exception { + String ptr = "version https://git-lfs.github.com/spec/v1\n" + + "oid sha256:" + TEST_SHA256 + '\n' + + "version https://git-lfs.github.com/spec/v1\n" + + "size 4\n"; + try (ByteArrayInputStream in = new ByteArrayInputStream( + ptr.getBytes(UTF_8))) { + assertNull("Is not a LFS pointer", LfsPointer.parseLfsPointer(in)); + } + } + + @Test + public void testReadInValidLfsPointerOidTwice() throws Exception { + String ptr = "version https://git-lfs.github.com/spec/v1\n" + + "oid sha256:" + TEST_SHA256 + '\n' + + "oid sha256:" + TEST_SHA256 + '\n' + + "size 4\n"; + try (ByteArrayInputStream in = new ByteArrayInputStream( + ptr.getBytes(UTF_8))) { + assertNull("Is not a LFS pointer", LfsPointer.parseLfsPointer(in)); + } + } + + @Test + public void testReadInValidLfsPointerSizeTwice() throws Exception { + String ptr = "version https://git-lfs.github.com/spec/v1\n" + + "size 4\n" + + "size 4\n" + + "oid sha256:" + TEST_SHA256 + '\n'; + try (ByteArrayInputStream in = new ByteArrayInputStream( + ptr.getBytes(UTF_8))) { + assertNull("Is not a LFS pointer", LfsPointer.parseLfsPointer(in)); + } + } + + @Test + public void testRoundtrip() throws Exception { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer ptr = new LfsPointer(id, 4); + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + ptr.encode(baos); + try (ByteArrayInputStream in = new ByteArrayInputStream( + baos.toByteArray())) { + assertEquals(ptr, LfsPointer.parseLfsPointer(in)); + } + } + } + + @Test + public void testEquals() throws Exception { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + AnyLongObjectId id2 = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs2 = new LfsPointer(id2, 4); + assertTrue(lfs.equals(lfs2)); + assertTrue(lfs2.equals(lfs)); + } + + @Test + public void testEqualsNull() throws Exception { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + assertFalse(lfs.equals(null)); + } + + @Test + public void testEqualsSame() throws Exception { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + assertTrue(lfs.equals(lfs)); + } + + @Test + public void testEqualsOther() throws Exception { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + assertFalse(lfs.equals(new Object())); + } + + @Test + public void testNotEqualsOid() throws Exception { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + AnyLongObjectId id2 = LongObjectId + .fromString(TEST_SHA256.replace('7', '5')); + LfsPointer lfs2 = new LfsPointer(id2, 4); + assertFalse(lfs.equals(lfs2)); + assertFalse(lfs2.equals(lfs)); + } + + @Test + public void testNotEqualsSize() throws Exception { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + AnyLongObjectId id2 = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs2 = new LfsPointer(id2, 5); + assertFalse(lfs.equals(lfs2)); + assertFalse(lfs2.equals(lfs)); + } + + @Test + public void testCompareToEquals() throws Exception { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + AnyLongObjectId id2 = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs2 = new LfsPointer(id2, 4); + assertEquals(0, lfs.compareTo(lfs2)); + assertEquals(0, lfs2.compareTo(lfs)); + } + + @Test + @SuppressWarnings("SelfComparison") + public void testCompareToSame() throws Exception { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + assertEquals(0, lfs.compareTo(lfs)); + } + + @Test + public void testCompareToNotEqualsOid() throws Exception { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + AnyLongObjectId id2 = LongObjectId + .fromString(TEST_SHA256.replace('7', '5')); + LfsPointer lfs2 = new LfsPointer(id2, 4); + assertNotEquals(0, lfs.compareTo(lfs2)); + assertNotEquals(0, lfs2.compareTo(lfs)); + } + + @Test + public void testCompareToNotEqualsSize() throws Exception { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + AnyLongObjectId id2 = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs2 = new LfsPointer(id2, 5); + assertNotEquals(0, lfs.compareTo(lfs2)); + assertNotEquals(0, lfs2.compareTo(lfs)); + } + + @Test + public void testCompareToNull() throws Exception { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + assertThrows(NullPointerException.class, () -> lfs.compareTo(null)); + } + + @Test + public void testHashcodeEquals() throws Exception { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + AnyLongObjectId id2 = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs2 = new LfsPointer(id2, 4); + assertEquals(lfs.hashCode(), lfs2.hashCode()); + } + + @Test + public void testHashcodeSame() throws Exception { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + assertEquals(lfs.hashCode(), lfs.hashCode()); + } + + @Test + public void testHashcodeNotEquals() throws Exception { + AnyLongObjectId id = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs = new LfsPointer(id, 4); + AnyLongObjectId id2 = LongObjectId.fromString(TEST_SHA256); + LfsPointer lfs2 = new LfsPointer(id2, 5); + assertNotEquals(lfs.hashCode(), lfs2.hashCode()); + } +} diff --git a/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LfsPointerFilterTest.java b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LfsPointerFilterTest.java new file mode 100644 index 0000000000..081a4a50a4 --- /dev/null +++ b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LfsPointerFilterTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2015, Dariusz Luksza <dariusz@luksza.org> and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.eclipse.jgit.lfs.lib; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription; +import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository; +import org.eclipse.jgit.junit.TestRepository; +import org.eclipse.jgit.revwalk.ObjectWalk; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevTree; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.junit.Test; + +public class LfsPointerFilterTest { + + private static final int SIZE = 12345; + + private static final String OID = "4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393"; + + private static final String[] NOT_VALID_LFS_FILES = { "", // empty file + // simulate java file + "package org.eclipse.jgit;", + // invalid LFS pointer, no oid and version + "version https://hawser.github.com/spec/v1\n", + // invalid LFS pointer, no version + "version https://hawser.github.com/spec/v1\n" + + "oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393\n", + // invalid LFS pointer, no id + "version https://hawser.github.com/spec/v1\n" + "size 12345\n", + // invalid LFS pointer, wrong order of oid and size + "version https://hawser.github.com/spec/v1\n" + "size 12345\n" + + "oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393\n" }; + + private static final String[] LFS_VERSION_DOMAINS = { + "hawser", "git-lfs" + }; + + private static final String[] VALID_LFS_FILES = { + // valid LFS pointer + "version https://%s.github.com/spec/v1\n" + + "oid sha256:" + OID + "\n" + + "size " + SIZE + "\n", + // valid LFS pointer with "custom" key + "version https://%s.github.com/spec/v1\n" + + "custom key with value\n" + + "oid sha256:" + OID + "\n" + + "size " + SIZE + "\n", + // valid LFS pointer with key with "." + "version https://%s.github.com/spec/v1\n" + + "oid sha256:" + OID + "\n" + + "r.key key with .\n" + + "size " + SIZE + "\n", + // valid LFS pointer with key with "-" + "version https://%s.github.com/spec/v1\n" + + "oid sha256:" + OID + "\n" + + "size " + SIZE + "\n" + + "valid-name another valid key\n" }; + + @Test + public void testRegularFilesInRepositoryRoot() throws Exception { + for (String file : NOT_VALID_LFS_FILES) { + assertLfs("file.bin", file).withRecursive(false).shouldBe(false); + } + } + + @Test + public void testNestedRegularFiles() throws Exception { + for (String file : NOT_VALID_LFS_FILES) { + assertLfs("a/file.bin", file).withRecursive(true).shouldBe(false); + } + } + + @Test + public void testValidPointersInRepositoryRoot() throws Exception { + for (String domain : LFS_VERSION_DOMAINS) { + for (String file : VALID_LFS_FILES) { + assertLfs("file.bin", String.format(file, domain)) + .withRecursive(true).shouldBe(true) + .check(); + } + } + } + + @Test + public void testValidNestedPointers() throws Exception { + for (String domain : LFS_VERSION_DOMAINS) { + for (String file : VALID_LFS_FILES) { + assertLfs("a/file.bin", String.format(file, domain)) + .withRecursive(true).shouldBe(true).check(); + } + } + } + + @Test + public void testValidNestedPointersWithoutRecurrence() throws Exception { + for (String domain : LFS_VERSION_DOMAINS) { + for (String file : VALID_LFS_FILES) { + assertLfs("file.bin", String.format(file, domain)) + .withRecursive(false).shouldBe(true).check(); + assertLfs("a/file.bin", String.format(file, domain)) + .withRecursive(false).shouldBe(false).check(); + } + } + } + + private static LfsTreeWalk assertLfs(String path, String content) { + return new LfsTreeWalk(path, content); + } + + private static class LfsTreeWalk { + private final String path; + + private final String content; + + private boolean state; + + private boolean recursive; + + private TestRepository<InMemoryRepository> tr; + + LfsTreeWalk(String path, String content) { + this.path = path; + this.content = content; + } + + LfsTreeWalk withRecursive(boolean shouldBeRecursive) { + this.recursive = shouldBeRecursive; + return this; + } + + LfsTreeWalk shouldBe(boolean shouldBeValid) { + this.state = shouldBeValid; + return this; + } + + void check() throws Exception { + tr = new TestRepository<>(new InMemoryRepository( + new DfsRepositoryDescription("test"))); + RevCommit commit = tr.branch("master").commit().add(path, content) + .message("initial commit").create(); + RevTree tree = parseCommit(commit); + LfsPointerFilter filter = new LfsPointerFilter(); + try (TreeWalk treeWalk = new TreeWalk(tr.getRepository())) { + treeWalk.addTree(tree); + treeWalk.setRecursive(recursive); + treeWalk.setFilter(filter); + + if (state) { + assertTrue(treeWalk.next()); + assertEquals(path, treeWalk.getPathString()); + assertNotNull(filter.getPointer()); + assertEquals(SIZE, filter.getPointer().getSize()); + assertEquals(OID, filter.getPointer().getOid().name()); + } else { + assertFalse(treeWalk.next()); + assertNull(filter.getPointer()); + } + } + } + + private RevTree parseCommit(RevCommit commit) throws Exception { + try (ObjectWalk ow = new ObjectWalk(tr.getRepository())) { + return ow.parseCommit(commit).getTree(); + } + } + } +} diff --git a/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LongObjectIdTest.java b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LongObjectIdTest.java new file mode 100644 index 0000000000..a71d42367d --- /dev/null +++ b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LongObjectIdTest.java @@ -0,0 +1,398 @@ +/* + * Copyright (C) 2015, Matthias Sohn <matthias.sohn@sap.com> and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.eclipse.jgit.lfs.lib; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Locale; + +import org.eclipse.jgit.junit.JGitTestUtil; +import org.eclipse.jgit.lfs.errors.InvalidLongObjectIdException; +import org.eclipse.jgit.lfs.test.LongObjectIdTestUtils; +import org.eclipse.jgit.util.FileUtils; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +/* + * Ported to SHA-256 from org.eclipse.jgit.lib.ObjectIdTest + */ +public class LongObjectIdTest { + private static Path tmp; + + @BeforeClass + public static void setup() throws IOException { + tmp = Files.createTempDirectory("jgit_test_"); + } + + @AfterClass + public static void tearDown() throws IOException { + FileUtils.delete(tmp.toFile(), FileUtils.RECURSIVE | FileUtils.RETRY); + } + + @Test + public void test001_toString() { + final String x = "8367b0edc81df80e6b42eb1b71f783111224e058cb3da37894d065d2deb7ab0a"; + final LongObjectId oid = LongObjectId.fromString(x); + assertEquals(x, oid.name()); + } + + @Test + public void test002_toString() { + final String x = "140ce71d628cceb78e3709940ba52a651a0c4a9c1400f2e15e998a1a43887edf"; + final LongObjectId oid = LongObjectId.fromString(x); + assertEquals(x, oid.name()); + } + + @Test + public void test003_equals() { + final String x = "8367b0edc81df80e6b42eb1b71f783111224e058cb3da37894d065d2deb7ab0a"; + final LongObjectId a = LongObjectId.fromString(x); + final LongObjectId b = LongObjectId.fromString(x); + assertEquals(a.hashCode(), b.hashCode()); + assertEquals("a and b should be equal", b, a); + } + + @Test + public void test004_isId() { + assertTrue("valid id", LongObjectId.isId( + "8367b0edc81df80e6b42eb1b71f783111224e058cb3da37894d065d2deb7ab0a")); + } + + @Test + public void test005_notIsId() { + assertFalse("bob is not an id", LongObjectId.isId("bob")); + } + + @Test + public void test006_notIsId() { + assertFalse("63 digits is not an id", LongObjectId.isId( + "8367b0edc81df80e6b42eb1b71f783111224e058cb3da37894d065d2deb7ab0")); + } + + @Test + public void test007_isId() { + assertTrue("uppercase is accepted", LongObjectId.isId( + "8367b0edc81df80e6b42eb1b71f783111224e058cb3da37894d065d2dEb7ab0A")); + } + + @Test + public void test008_notIsId() { + assertFalse("g is not a valid hex digit", LongObjectId.isId( + "g367b0edc81df80e6b42eb1b71f783111224e058cb3da37894d065d2deb7ab0a")); + } + + @Test + public void test009_toString() { + final String x = "140ce71d628cceb78e3709940ba52a651a0c4a9c1400f2e15e998a1a43887edf"; + final LongObjectId oid = LongObjectId.fromString(x); + assertEquals(x, LongObjectId.toString(oid)); + } + + @Test + public void test010_toString() { + final String x = "0000000000000000000000000000000000000000000000000000000000000000"; + assertEquals(x, LongObjectId.toString(null)); + } + + @Test + public void test011_toString() { + final String x = "0123456789ABCDEFabcdef01234567890123456789ABCDEFabcdef0123456789"; + final LongObjectId oid = LongObjectId.fromString(x); + assertEquals(x.toLowerCase(Locale.ROOT), oid.name()); + } + + @Test + public void testGetByte() { + byte[] raw = new byte[32]; + for (int i = 0; i < 32; i++) + raw[i] = (byte) (0xa0 + i); + LongObjectId id = LongObjectId.fromRaw(raw); + + assertEquals(raw[0] & 0xff, id.getFirstByte()); + assertEquals(raw[0] & 0xff, id.getByte(0)); + assertEquals(raw[1] & 0xff, id.getByte(1)); + assertEquals(raw[1] & 0xff, id.getSecondByte()); + + for (int i = 2; i < 32; i++) { + assertEquals("index " + i, raw[i] & 0xff, id.getByte(i)); + } + try { + id.getByte(32); + fail("LongObjectId has 32 byte only"); + } catch (ArrayIndexOutOfBoundsException e) { + // expected + } + } + + @Test + public void testSetByte() { + byte[] exp = new byte[32]; + for (int i = 0; i < 32; i++) { + exp[i] = (byte) (0xa0 + i); + } + + MutableLongObjectId id = new MutableLongObjectId(); + id.fromRaw(exp); + assertEquals(LongObjectId.fromRaw(exp).name(), id.name()); + + id.setByte(0, 0x10); + assertEquals(0x10, id.getByte(0)); + exp[0] = 0x10; + assertEquals(LongObjectId.fromRaw(exp).name(), id.name()); + + for (int p = 1; p < 32; p++) { + id.setByte(p, 0x10 + p); + assertEquals(0x10 + p, id.getByte(p)); + exp[p] = (byte) (0x10 + p); + assertEquals(LongObjectId.fromRaw(exp).name(), id.name()); + } + + for (int p = 0; p < 32; p++) { + id.setByte(p, 0x80 + p); + assertEquals(0x80 + p, id.getByte(p)); + exp[p] = (byte) (0x80 + p); + assertEquals(LongObjectId.fromRaw(exp).name(), id.name()); + } + } + + @Test + public void testZeroId() { + AnyLongObjectId zero = new LongObjectId(0L, 0L, 0L, 0L); + assertEquals(zero, LongObjectId.zeroId()); + assertEquals( + "0000000000000000000000000000000000000000000000000000000000000000", + LongObjectId.zeroId().name()); + } + + @Test + public void testEquals() { + AnyLongObjectId id1 = LongObjectIdTestUtils.hash("test"); + assertTrue("id should equal itself", id1.equals(id1)); + AnyLongObjectId id2 = new LongObjectId(id1); + assertEquals("objects should be equals", id1, id2); + + id2 = LongObjectIdTestUtils.hash("other"); + assertNotEquals("objects should be not equal", id1, id2); + } + + @Test + public void testCopyRawBytes() { + AnyLongObjectId id1 = LongObjectIdTestUtils.hash("test"); + AnyLongObjectId id2 = new LongObjectId(id1); + + byte[] buf = new byte[64]; + id1.copyRawTo(buf, 0); + id2.copyRawTo(buf, 32); + assertTrue("objects should be equals", + LongObjectId.equals(buf, 0, buf, 32)); + } + + @Test + public void testCopyRawLongs() { + long[] a = new long[4]; + a[0] = 1L; + a[1] = 2L; + a[2] = 3L; + a[3] = 4L; + AnyLongObjectId id1 = new LongObjectId(a[0], a[1], a[2], a[3]); + AnyLongObjectId id2 = LongObjectId.fromRaw(a); + assertEquals("objects should be equals", id1, id2); + } + + @Test + public void testCopyFromStringInvalid() { + AnyLongObjectId id1 = LongObjectIdTestUtils.hash("test"); + try { + LongObjectId.fromString(id1.name() + "01234"); + fail("expected InvalidLongObjectIdException"); + } catch (InvalidLongObjectIdException e) { + assertEquals("Invalid id: " + id1.name() + "01234", + e.getMessage()); + } + } + + @Test + public void testCopyFromStringByte() { + AnyLongObjectId id1 = LongObjectIdTestUtils.hash("test"); + byte[] buf = new byte[64]; + Charset cs = US_ASCII; + cs.encode(id1.name()).get(buf); + AnyLongObjectId id2 = LongObjectId.fromString(buf, 0); + assertEquals("objects should be equals", id1, id2); + } + + @Test + public void testHashFile() throws IOException { + AnyLongObjectId id1 = LongObjectIdTestUtils.hash("test"); + Path f = tmp.resolve("test"); + JGitTestUtil.write(f.toFile(), "test"); + AnyLongObjectId id2 = LongObjectIdTestUtils.hash(f); + assertEquals("objects should be equals", id1, id2); + } + + @Test + public void testCompareTo() { + AnyLongObjectId id1 = LongObjectId.fromString( + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"); + assertEquals(0, id1.compareTo(LongObjectId.fromString( + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"))); + AnyLongObjectId self = id1; + assertEquals(0, id1.compareTo(self)); + + assertEquals(-1, id1.compareTo(LongObjectId.fromString( + "1123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"))); + assertEquals(-1, id1.compareTo(LongObjectId.fromString( + "0123456789abcdef1123456789abcdef0123456789abcdef0123456789abcdef"))); + assertEquals(-1, id1.compareTo(LongObjectId.fromString( + "0123456789abcdef0123456789abcdef1123456789abcdef0123456789abcdef"))); + assertEquals(-1, id1.compareTo(LongObjectId.fromString( + "0123456789abcdef0123456789abcdef0123456789abcdef1123456789abcdef"))); + + assertEquals(1, id1.compareTo(LongObjectId.fromString( + "0023456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"))); + assertEquals(1, id1.compareTo(LongObjectId.fromString( + "0123456789abcdef0023456789abcdef0123456789abcdef0123456789abcdef"))); + assertEquals(1, id1.compareTo(LongObjectId.fromString( + "0123456789abcdef0123456789abcdef0023456789abcdef0123456789abcdef"))); + assertEquals(1, id1.compareTo(LongObjectId.fromString( + "0123456789abcdef0123456789abcdef0123456789abcdef0023456789abcdef"))); + } + + @Test + public void testCompareToByte() { + AnyLongObjectId id1 = LongObjectId.fromString( + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"); + byte[] buf = new byte[32]; + id1.copyRawTo(buf, 0); + assertEquals(0, id1.compareTo(buf, 0)); + + LongObjectId + .fromString( + "1123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef") + .copyRawTo(buf, 0); + assertEquals(-1, id1.compareTo(buf, 0)); + + LongObjectId + .fromString( + "0023456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef") + .copyRawTo(buf, 0); + assertEquals(1, id1.compareTo(buf, 0)); + } + + @Test + public void testCompareToLong() { + AnyLongObjectId id1 = new LongObjectId(1L, 2L, 3L, 4L); + long[] buf = new long[4]; + id1.copyRawTo(buf, 0); + assertEquals(0, id1.compareTo(buf, 0)); + + new LongObjectId(2L, 2L, 3L, 4L).copyRawTo(buf, 0); + assertEquals(-1, id1.compareTo(buf, 0)); + + new LongObjectId(0L, 2L, 3L, 4L).copyRawTo(buf, 0); + assertEquals(1, id1.compareTo(buf, 0)); + } + + @Test + public void testCopyToByte() { + AnyLongObjectId id1 = LongObjectIdTestUtils.hash("test"); + byte[] buf = new byte[64]; + id1.copyTo(buf, 0); + assertEquals(id1, LongObjectId.fromString(buf, 0)); + } + + @Test + public void testCopyRawToByteBuffer() { + AnyLongObjectId id1 = LongObjectIdTestUtils.hash("test"); + ByteBuffer buf = ByteBuffer.allocate(32); + id1.copyRawTo(buf); + assertEquals(id1, LongObjectId.fromRaw(buf.array(), 0)); + } + + @Test + public void testCopyToByteBuffer() { + AnyLongObjectId id1 = LongObjectIdTestUtils.hash("test"); + ByteBuffer buf = ByteBuffer.allocate(64); + id1.copyTo(buf); + assertEquals(id1, LongObjectId.fromString(buf.array(), 0)); + } + + @Test + public void testCopyRawToOutputStream() throws IOException { + AnyLongObjectId id1 = LongObjectIdTestUtils.hash("test"); + ByteArrayOutputStream os = new ByteArrayOutputStream(32); + id1.copyRawTo(os); + assertEquals(id1, LongObjectId.fromRaw(os.toByteArray(), 0)); + } + + @Test + public void testCopyToOutputStream() throws IOException { + AnyLongObjectId id1 = LongObjectIdTestUtils.hash("test"); + ByteArrayOutputStream os = new ByteArrayOutputStream(64); + id1.copyTo(os); + assertEquals(id1, LongObjectId.fromString(os.toByteArray(), 0)); + } + + @Test + public void testCopyToWriter() throws IOException { + AnyLongObjectId id1 = LongObjectIdTestUtils.hash("test"); + ByteArrayOutputStream os = new ByteArrayOutputStream(64); + try (OutputStreamWriter w = new OutputStreamWriter(os, + UTF_8)) { + id1.copyTo(w); + } + assertEquals(id1, LongObjectId.fromString(os.toByteArray(), 0)); + } + + @Test + public void testCopyToWriterWithBuf() throws IOException { + AnyLongObjectId id1 = LongObjectIdTestUtils.hash("test"); + ByteArrayOutputStream os = new ByteArrayOutputStream(64); + try (OutputStreamWriter w = new OutputStreamWriter(os, + UTF_8)) { + char[] buf = new char[64]; + id1.copyTo(buf, w); + } + assertEquals(id1, LongObjectId.fromString(os.toByteArray(), 0)); + } + + @Test + public void testCopyToStringBuilder() { + AnyLongObjectId id1 = LongObjectIdTestUtils.hash("test"); + StringBuilder sb = new StringBuilder(); + char[] buf = new char[64]; + id1.copyTo(buf, sb); + assertEquals(id1, LongObjectId.fromString(sb.toString())); + } + + @Test + public void testCopy() { + AnyLongObjectId id1 = LongObjectIdTestUtils.hash("test"); + assertEquals(id1.copy(), id1); + MutableLongObjectId id2 = new MutableLongObjectId(); + id2.fromObjectId(id1); + assertEquals(id1, id2.copy()); + } +} diff --git a/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/MutableLongObjectIdTest.java b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/MutableLongObjectIdTest.java new file mode 100644 index 0000000000..8c19cd714f --- /dev/null +++ b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/MutableLongObjectIdTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2015, Matthias Sohn <matthias.sohn@sap.com> and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.lfs.lib; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +/* + * Ported to SHA-256 from org.eclipse.jgit.lib.MutableObjectIdTest + */ +public class MutableLongObjectIdTest { + + @Test + public void testFromRawLong() { + MutableLongObjectId m = new MutableLongObjectId(); + m.fromRaw(new long[] { 1L, 2L, 3L, 4L }); + assertEquals(new LongObjectId(1L, 2L, 3L, 4L), m); + } + + @Test + public void testFromString() { + AnyLongObjectId id = new LongObjectId(1L, 2L, 3L, 4L); + MutableLongObjectId m = new MutableLongObjectId(); + m.fromString(id.name()); + assertEquals(id, m); + } + + @Test + public void testFromStringByte() { + AnyLongObjectId id = new LongObjectId(1L, 2L, 3L, 4L); + MutableLongObjectId m = new MutableLongObjectId(); + byte[] buf = new byte[64]; + id.copyTo(buf, 0); + m.fromString(buf, 0); + assertEquals(id, m); + } + + @Test + public void testCopy() { + MutableLongObjectId m = new MutableLongObjectId(); + m.fromRaw(new long[] { 1L, 2L, 3L, 4L }); + assertEquals(m, new MutableLongObjectId(m)); + } + + @Test + public void testToObjectId() { + MutableLongObjectId m = new MutableLongObjectId(); + m.fromRaw(new long[] { 1L, 2L, 3L, 4L }); + assertEquals(m, m.toObjectId()); + } +} |