diff options
Diffstat (limited to 'org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/pgm/ToolTestCase.java')
-rw-r--r-- | org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/pgm/ToolTestCase.java | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/pgm/ToolTestCase.java b/org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/pgm/ToolTestCase.java new file mode 100644 index 0000000000..55db1a12d9 --- /dev/null +++ b/org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/pgm/ToolTestCase.java @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2022, Simeon Andreev <simeon.danailov.andreev@gmail.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.pgm; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.diff.DiffEntry; +import org.eclipse.jgit.lib.CLIRepositoryTestCase; +import org.eclipse.jgit.pgm.opt.CmdLineParser; +import org.eclipse.jgit.pgm.opt.SubcommandHandler; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.treewalk.FileTreeIterator; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.util.SystemReader; +import org.junit.Assume; +import org.junit.Before; +import org.kohsuke.args4j.Argument; +import org.kohsuke.args4j.CmdLineException; + +/** + * Base test case for the {@code difftool} and {@code mergetool} commands. + */ +public abstract class ToolTestCase extends CLIRepositoryTestCase { + + public static class GitCliJGitWrapperParser { + @Argument(index = 0, metaVar = "metaVar_command", required = true, handler = SubcommandHandler.class) + TextBuiltin subcommand; + + @Argument(index = 1, metaVar = "metaVar_arg") + List<String> arguments = new ArrayList<>(); + } + + protected static final String TOOL_NAME = "some_tool"; + + private static final String TEST_BRANCH_NAME = "test_branch"; + + private Git git; + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + git = new Git(db); + git.commit().setMessage("initial commit").call(); + git.branchCreate().setName(TEST_BRANCH_NAME).call(); + } + + protected String[] runAndCaptureUsingInitRaw(String... args) + throws Exception { + InputStream inputStream = null; // no input stream + return runAndCaptureUsingInitRaw(inputStream, args); + } + + protected String[] runAndCaptureUsingInitRaw( + List<String> expectedErrorOutput, String... args) throws Exception { + InputStream inputStream = null; // no input stream + return runAndCaptureUsingInitRaw(inputStream, expectedErrorOutput, + args); + } + + protected String[] runAndCaptureUsingInitRaw(InputStream inputStream, + String... args) throws Exception { + List<String> expectedErrorOutput = Collections.emptyList(); + return runAndCaptureUsingInitRaw(inputStream, expectedErrorOutput, + args); + } + + protected String[] runAndCaptureUsingInitRaw(InputStream inputStream, + List<String> expectedErrorOutput, String... args) + throws CmdLineException, Exception, IOException { + CLIGitCommand.Result result = new CLIGitCommand.Result(); + + GitCliJGitWrapperParser bean = new GitCliJGitWrapperParser(); + CmdLineParser clp = new CmdLineParser(bean); + clp.parseArgument(args); + + TextBuiltin cmd = bean.subcommand; + cmd.initRaw(db, null, inputStream, result.out, result.err); + cmd.execute(bean.arguments.toArray(new String[bean.arguments.size()])); + if (cmd.getOutputWriter() != null) { + cmd.getOutputWriter().flush(); + } + if (cmd.getErrorWriter() != null) { + cmd.getErrorWriter().flush(); + } + + List<String> errLines = result.errLines().stream() + .filter(l -> !l.isBlank()) // we care only about error messages + .collect(Collectors.toList()); + assertEquals("Expected no standard error output from tool", + expectedErrorOutput.toString(), errLines.toString()); + + return result.outLines().toArray(new String[0]); + } + + protected String[] createMergeConflict() throws Exception { + // create files on initial branch + git.checkout().setName(TEST_BRANCH_NAME).call(); + writeTrashFile("dir1/a", "Hello world a"); + writeTrashFile("dir2/b", "Hello world b"); + git.add().addFilepattern(".").call(); + git.commit().setMessage("files a & b added").call(); + // create another branch and change files + git.branchCreate().setName("branch_1").call(); + git.checkout().setName("branch_1").call(); + writeTrashFile("dir1/a", "Hello world a 1"); + writeTrashFile("dir2/b", "Hello world b 1"); + git.add().addFilepattern(".").call(); + RevCommit commit1 = git.commit() + .setMessage("files a & b modified commit 1").call(); + // checkout initial branch + git.checkout().setName(TEST_BRANCH_NAME).call(); + // create another branch and change files + git.branchCreate().setName("branch_2").call(); + git.checkout().setName("branch_2").call(); + writeTrashFile("dir1/a", "Hello world a 2"); + writeTrashFile("dir2/b", "Hello world b 2"); + git.add().addFilepattern(".").call(); + git.commit().setMessage("files a & b modified commit 2").call(); + // cherry-pick conflicting changes + git.cherryPick().include(commit1).call(); + String[] conflictingFilenames = { "dir1/a", "dir2/b" }; + return conflictingFilenames; + } + + protected String[] createDeletedConflict() throws Exception { + // create files on initial branch + git.checkout().setName(TEST_BRANCH_NAME).call(); + writeTrashFile("dir1/a", "Hello world a"); + writeTrashFile("dir2/b", "Hello world b"); + git.add().addFilepattern(".").call(); + git.commit().setMessage("files a & b added").call(); + // create another branch and change files + git.branchCreate().setName("branch_1").call(); + git.checkout().setName("branch_1").call(); + writeTrashFile("dir1/a", "Hello world a 1"); + writeTrashFile("dir2/b", "Hello world b 1"); + git.add().addFilepattern(".").call(); + RevCommit commit1 = git.commit() + .setMessage("files a & b modified commit 1").call(); + // checkout initial branch + git.checkout().setName(TEST_BRANCH_NAME).call(); + // create another branch and change files + git.branchCreate().setName("branch_2").call(); + git.checkout().setName("branch_2").call(); + git.rm().addFilepattern("dir1/a").call(); + git.rm().addFilepattern("dir2/b").call(); + git.commit().setMessage("files a & b deleted commit 2").call(); + // cherry-pick conflicting changes + git.cherryPick().include(commit1).call(); + String[] conflictingFilenames = { "dir1/a", "dir2/b" }; + return conflictingFilenames; + } + + protected String[] createUnstagedChanges() throws Exception { + writeTrashFile("dir1/a", "Hello world a"); + writeTrashFile("dir2/b", "Hello world b"); + git.add().addFilepattern(".").call(); + git.commit().setMessage("files a & b").call(); + writeTrashFile("dir1/a", "New Hello world a"); + writeTrashFile("dir2/b", "New Hello world b"); + String[] conflictingFilenames = { "dir1/a", "dir2/b" }; + return conflictingFilenames; + } + + protected String[] createStagedChanges() throws Exception { + String[] conflictingFilenames = createUnstagedChanges(); + git.add().addFilepattern(".").call(); + return conflictingFilenames; + } + + protected List<DiffEntry> getRepositoryChanges(RevCommit commit) + throws Exception { + TreeWalk tw = new TreeWalk(db); + tw.addTree(commit.getTree()); + FileTreeIterator modifiedTree = new FileTreeIterator(db); + tw.addTree(modifiedTree); + List<DiffEntry> changes = DiffEntry.scan(tw); + return changes; + } + + protected Path getFullPath(String repositoryFilename) { + Path dotGitPath = db.getDirectory().toPath(); + Path repositoryRoot = dotGitPath.getParent(); + Path repositoryFilePath = repositoryRoot.resolve(repositoryFilename); + return repositoryFilePath; + } + + protected static InputStream createInputStream(String[] inputLines) { + return createInputStream(Arrays.asList(inputLines)); + } + + protected static InputStream createInputStream(List<String> inputLines) { + String input = String.join(System.lineSeparator(), inputLines); + InputStream inputStream = new ByteArrayInputStream(input.getBytes(UTF_8)); + return inputStream; + } + + protected static void assertArrayOfLinesEquals(String failMessage, + String[] expected, String[] actual) { + assertEquals(failMessage, toString(expected), toString(actual)); + } + + protected static void assertArrayOfMatchingLines(String failMessage, + Pattern[] expected, String[] actual) { + assertEquals(failMessage + System.lineSeparator() + + "Expected and actual lines count don't match. Expected: " + + Arrays.asList(expected) + ", actual: " + + Arrays.asList(actual), expected.length, actual.length); + int n = expected.length; + for (int i = 0; i < n; ++i) { + Pattern expectedPattern = expected[i]; + String actualLine = actual[i]; + Matcher matcher = expectedPattern.matcher(actualLine); + boolean matches = matcher.matches(); + assertTrue(failMessage + System.lineSeparator() + "Line " + i + " '" + + actualLine + "' doesn't match expected pattern: " + + expectedPattern + System.lineSeparator() + "Expected: " + + Arrays.asList(expected) + ", actual: " + + Arrays.asList(actual), + matches); + } + } + + protected static void assumeLinuxPlatform() { + Assume.assumeTrue("This test can run only in Linux tests", + SystemReader.getInstance().isLinux()); + } +} |