1
2
3
4
5
6
7
8
9
10 package org.eclipse.jgit.pgm;
11
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertTrue;
14
15 import java.io.ByteArrayInputStream;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.nio.file.Path;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collections;
22 import java.util.List;
23 import java.util.regex.Matcher;
24 import java.util.regex.Pattern;
25 import java.util.stream.Collectors;
26
27 import org.eclipse.jgit.api.Git;
28 import org.eclipse.jgit.diff.DiffEntry;
29 import org.eclipse.jgit.lib.CLIRepositoryTestCase;
30 import org.eclipse.jgit.pgm.opt.CmdLineParser;
31 import org.eclipse.jgit.pgm.opt.SubcommandHandler;
32 import org.eclipse.jgit.revwalk.RevCommit;
33 import org.eclipse.jgit.treewalk.FileTreeIterator;
34 import org.eclipse.jgit.treewalk.TreeWalk;
35 import org.junit.Before;
36 import org.kohsuke.args4j.Argument;
37 import org.kohsuke.args4j.CmdLineException;
38
39
40
41
42 public abstract class ToolTestCase extends CLIRepositoryTestCase {
43
44 public static class GitCliJGitWrapperParser {
45 @Argument(index = 0, metaVar = "metaVar_command", required = true, handler = SubcommandHandler.class)
46 TextBuiltin subcommand;
47
48 @Argument(index = 1, metaVar = "metaVar_arg")
49 List<String> arguments = new ArrayList<>();
50 }
51
52 protected static final String TOOL_NAME = "some_tool";
53
54 private static final String TEST_BRANCH_NAME = "test_branch";
55
56 private Git git;
57
58 @Override
59 @Before
60 public void setUp() throws Exception {
61 super.setUp();
62 git = new Git(db);
63 git.commit().setMessage("initial commit").call();
64 git.branchCreate().setName(TEST_BRANCH_NAME).call();
65 }
66
67 protected String[] runAndCaptureUsingInitRaw(String... args)
68 throws Exception {
69 InputStream inputStream = null;
70 return runAndCaptureUsingInitRaw(inputStream, args);
71 }
72
73 protected String[] runAndCaptureUsingInitRaw(
74 List<String> expectedErrorOutput, String... args) throws Exception {
75 InputStream inputStream = null;
76 return runAndCaptureUsingInitRaw(inputStream, expectedErrorOutput,
77 args);
78 }
79
80 protected String[] runAndCaptureUsingInitRaw(InputStream inputStream,
81 String... args) throws Exception {
82 List<String> expectedErrorOutput = Collections.emptyList();
83 return runAndCaptureUsingInitRaw(inputStream, expectedErrorOutput,
84 args);
85 }
86
87 protected String[] runAndCaptureUsingInitRaw(InputStream inputStream,
88 List<String> expectedErrorOutput, String... args)
89 throws CmdLineException, Exception, IOException {
90 CLIGitCommand.Result result = new CLIGitCommand.Result();
91
92 GitCliJGitWrapperParser bean = new GitCliJGitWrapperParser();
93 CmdLineParser clp = new CmdLineParser(bean);
94 clp.parseArgument(args);
95
96 TextBuiltin cmd = bean.subcommand;
97 cmd.initRaw(db, null, inputStream, result.out, result.err);
98 cmd.execute(bean.arguments.toArray(new String[bean.arguments.size()]));
99 if (cmd.getOutputWriter() != null) {
100 cmd.getOutputWriter().flush();
101 }
102 if (cmd.getErrorWriter() != null) {
103 cmd.getErrorWriter().flush();
104 }
105
106 List<String> errLines = result.errLines().stream()
107 .filter(l -> !l.isBlank())
108 .collect(Collectors.toList());
109 assertEquals("Expected no standard error output from tool",
110 expectedErrorOutput.toString(), errLines.toString());
111
112 return result.outLines().toArray(new String[0]);
113 }
114
115 protected String[] createMergeConflict() throws Exception {
116
117 git.checkout().setName(TEST_BRANCH_NAME).call();
118 writeTrashFile("dir1/a", "Hello world a");
119 writeTrashFile("dir2/b", "Hello world b");
120 git.add().addFilepattern(".").call();
121 git.commit().setMessage("files a & b added").call();
122
123 git.branchCreate().setName("branch_1").call();
124 git.checkout().setName("branch_1").call();
125 writeTrashFile("dir1/a", "Hello world a 1");
126 writeTrashFile("dir2/b", "Hello world b 1");
127 git.add().addFilepattern(".").call();
128 RevCommit commit1 = git.commit()
129 .setMessage("files a & b modified commit 1").call();
130
131 git.checkout().setName(TEST_BRANCH_NAME).call();
132
133 git.branchCreate().setName("branch_2").call();
134 git.checkout().setName("branch_2").call();
135 writeTrashFile("dir1/a", "Hello world a 2");
136 writeTrashFile("dir2/b", "Hello world b 2");
137 git.add().addFilepattern(".").call();
138 git.commit().setMessage("files a & b modified commit 2").call();
139
140 git.cherryPick().include(commit1).call();
141 String[] conflictingFilenames = { "dir1/a", "dir2/b" };
142 return conflictingFilenames;
143 }
144
145 protected String[] createDeletedConflict() throws Exception {
146
147 git.checkout().setName(TEST_BRANCH_NAME).call();
148 writeTrashFile("dir1/a", "Hello world a");
149 writeTrashFile("dir2/b", "Hello world b");
150 git.add().addFilepattern(".").call();
151 git.commit().setMessage("files a & b added").call();
152
153 git.branchCreate().setName("branch_1").call();
154 git.checkout().setName("branch_1").call();
155 writeTrashFile("dir1/a", "Hello world a 1");
156 writeTrashFile("dir2/b", "Hello world b 1");
157 git.add().addFilepattern(".").call();
158 RevCommit commit1 = git.commit()
159 .setMessage("files a & b modified commit 1").call();
160
161 git.checkout().setName(TEST_BRANCH_NAME).call();
162
163 git.branchCreate().setName("branch_2").call();
164 git.checkout().setName("branch_2").call();
165 git.rm().addFilepattern("dir1/a").call();
166 git.rm().addFilepattern("dir2/b").call();
167 git.commit().setMessage("files a & b deleted commit 2").call();
168
169 git.cherryPick().include(commit1).call();
170 String[] conflictingFilenames = { "dir1/a", "dir2/b" };
171 return conflictingFilenames;
172 }
173
174 protected String[] createUnstagedChanges() throws Exception {
175 writeTrashFile("dir1/a", "Hello world a");
176 writeTrashFile("dir2/b", "Hello world b");
177 git.add().addFilepattern(".").call();
178 git.commit().setMessage("files a & b").call();
179 writeTrashFile("dir1/a", "New Hello world a");
180 writeTrashFile("dir2/b", "New Hello world b");
181 String[] conflictingFilenames = { "dir1/a", "dir2/b" };
182 return conflictingFilenames;
183 }
184
185 protected String[] createStagedChanges() throws Exception {
186 String[] conflictingFilenames = createUnstagedChanges();
187 git.add().addFilepattern(".").call();
188 return conflictingFilenames;
189 }
190
191 protected List<DiffEntry> getRepositoryChanges(RevCommit commit)
192 throws Exception {
193 TreeWalk tw = new TreeWalk(db);
194 tw.addTree(commit.getTree());
195 FileTreeIterator modifiedTree = new FileTreeIterator(db);
196 tw.addTree(modifiedTree);
197 List<DiffEntry> changes = DiffEntry.scan(tw);
198 return changes;
199 }
200
201 protected Path getFullPath(String repositoryFilename) {
202 Path dotGitPath = db.getDirectory().toPath();
203 Path repositoryRoot = dotGitPath.getParent();
204 Path repositoryFilePath = repositoryRoot.resolve(repositoryFilename);
205 return repositoryFilePath;
206 }
207
208 protected static InputStream createInputStream(String[] inputLines) {
209 return createInputStream(Arrays.asList(inputLines));
210 }
211
212 protected static InputStream createInputStream(List<String> inputLines) {
213 String input = String.join(System.lineSeparator(), inputLines);
214 InputStream inputStream = new ByteArrayInputStream(input.getBytes());
215 return inputStream;
216 }
217
218 protected static void assertArrayOfLinesEquals(String failMessage,
219 String[] expected, String[] actual) {
220 assertEquals(failMessage, toString(expected), toString(actual));
221 }
222
223 protected static void assertArrayOfMatchingLines(String failMessage,
224 Pattern[] expected, String[] actual) {
225 assertEquals(failMessage + System.lineSeparator()
226 + "Expected and actual lines count don't match. Expected: "
227 + Arrays.asList(expected) + ", actual: "
228 + Arrays.asList(actual), expected.length, actual.length);
229 int n = expected.length;
230 for (int i = 0; i < n; ++i) {
231 Pattern expectedPattern = expected[i];
232 String actualLine = actual[i];
233 Matcher matcher = expectedPattern.matcher(actualLine);
234 boolean matches = matcher.matches();
235 assertTrue(failMessage + System.lineSeparator() + "Line " + i + " '"
236 + actualLine + "' doesn't match expected pattern: "
237 + expectedPattern + System.lineSeparator() + "Expected: "
238 + Arrays.asList(expected) + ", actual: "
239 + Arrays.asList(actual),
240 matches);
241 }
242 }
243 }