1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package com.aragost.javahg.test;
27
28 import java.io.BufferedReader;
29 import java.io.File;
30 import java.io.FileInputStream;
31 import java.io.IOException;
32 import java.io.InputStreamReader;
33 import java.nio.charset.Charset;
34 import java.util.Collection;
35 import java.util.logging.Level;
36 import java.util.logging.Logger;
37
38 import org.junit.After;
39 import org.junit.Assert;
40 import org.junit.Assume;
41 import org.junit.runner.RunWith;
42
43 import com.aragost.javahg.BaseRepository;
44 import com.aragost.javahg.Changeset;
45 import com.aragost.javahg.HgVersion;
46 import com.aragost.javahg.Repository;
47 import com.aragost.javahg.RepositoryConfiguration;
48 import com.aragost.javahg.RepositoryConfiguration.CachePolicy;
49 import com.aragost.javahg.commands.AddCommand;
50 import com.aragost.javahg.commands.CommitCommand;
51 import com.aragost.javahg.commands.UpdateCommand;
52 import com.aragost.javahg.commands.VersionCommand;
53 import com.aragost.javahg.internals.AbstractCommand;
54 import com.aragost.javahg.internals.GenericCommand;
55 import com.aragost.javahg.internals.HgInputStream;
56 import com.aragost.javahg.internals.RuntimeIOException;
57 import com.aragost.javahg.internals.Server;
58 import com.aragost.javahg.internals.Utils;
59 import com.google.common.collect.ObjectArrays;
60 import com.google.common.io.Files;
61
62
63
64
65 @RunWith(org.junit.runners.BlockJUnit4ClassRunner.class)
66 public abstract class AbstractTestCase {
67
68
69
70
71
72 private static final Logger JUL_ROOT_LOGGER = Logger.getLogger("");
73
74 private static int count = 0;
75
76 private BaseRepository testRepository;
77
78 private BaseRepository testRepository2;
79
80 protected static final RepositoryConfiguration REPO_CONF;
81
82 static {
83 REPO_CONF = makeRepoConf();
84
85 JUL_ROOT_LOGGER.setLevel(Level.WARNING);
86
87 File dir = Files.createTempDir();
88 BaseRepository repo = Repository.create(REPO_CONF, dir);
89 HgVersion version = VersionCommand.on(repo).execute();
90 repo.close();
91 try {
92 deleteTempDir(dir);
93 } catch (IOException e) {
94 System.err.println("JavaHg: Failed to remove temp dir: " + dir.getAbsolutePath());
95 }
96
97 System.err.println("JavaHg test using Mercurial version: " + version + ", binary: " + REPO_CONF.getHgBin());
98 }
99
100 public File createMercurialRepository() {
101 File dir = Files.createTempDir();
102 Server server = new Server(RepositoryConfiguration.DEFAULT.getHgBin(),
103 RepositoryConfiguration.DEFAULT.getEncoding());
104 server.initMecurialRepository(dir);
105 return dir;
106 }
107
108 protected static RepositoryConfiguration makeRepoConf() {
109 RepositoryConfiguration conf = new RepositoryConfiguration();
110 conf.setCachePolicy(CachePolicy.WEAK);
111 conf.addExtension(JavaHgTestExtension.class);
112
113 return conf;
114 }
115
116 public Charset utf8() {
117 return Charset.forName("UTF-8");
118 }
119
120 public BaseRepository getTestRepository() {
121 if (this.testRepository == null) {
122 File dir = Files.createTempDir();
123 this.testRepository = Repository.create(REPO_CONF, dir);
124 }
125 return this.testRepository;
126 }
127
128 public BaseRepository getTestRepository2() {
129 if (this.testRepository2 == null) {
130 File dir = Files.createTempDir();
131 this.testRepository2 = Repository.create(REPO_CONF, dir);
132 }
133 return this.testRepository2;
134 }
135
136
137
138
139
140
141
142
143 public void writeFile(String name, String content) throws IOException {
144 writeFile(getTestRepository(), name, content);
145 }
146
147 public void writeFile(BaseRepository repo, String name, String content) throws IOException {
148 File file = new File(repo.getDirectory(), name);
149 Files.write(content, file, utf8());
150 }
151
152
153
154
155
156
157
158
159
160 public void writeFile(String name) throws IOException {
161 writeFile(name, String.valueOf(count++) + "\n");
162 }
163
164 public void appendFile(String name) throws IOException {
165 File file = new File(getTestRepository().getDirectory(), name);
166 Files.append(String.valueOf(count++) + "\n", file, utf8());
167 }
168
169
170
171
172
173
174
175
176 public String readFile(String name) throws IOException {
177 File file = new File(getTestRepository().getDirectory(), name);
178 return Files.readFirstLine(file, utf8());
179 }
180
181
182
183
184
185
186
187 public void deleteFile(String name) {
188 File file = new File(getTestRepository().getDirectory(), name);
189 boolean deleted = file.delete();
190 if (!deleted) {
191 throw new RuntimeException("Could not delete: " + file);
192 }
193 }
194
195
196
197
198
199
200 public Changeset commit() throws IOException {
201 Repository repo = getTestRepository();
202 AddCommand.on(repo).execute();
203 CommitCommand cmd = CommitCommand.on(repo).user("testcase").message("testcase: " + getClass().getName());
204 return cmd.execute();
205 }
206
207
208
209
210
211
212
213 public Changeset createChangeset() throws IOException {
214 writeFile("dummyFileForCreatingChangesets", String.valueOf(count++));
215 return commit();
216 }
217
218
219
220
221
222
223
224 public void update(Changeset cs) throws IOException {
225 UpdateCommand.on(getTestRepository()).clean().rev(cs.getNode()).execute();
226 }
227
228 @After
229 public void closeTestRepository() throws IOException {
230 if (this.testRepository != null) {
231 this.testRepository.close();
232 deleteTempDir(this.testRepository.getDirectory());
233 this.testRepository = null;
234 }
235 if (this.testRepository2 != null) {
236 this.testRepository2.close();
237 deleteTempDir(this.testRepository2.getDirectory());
238 this.testRepository2 = null;
239 }
240 }
241
242
243
244
245
246
247
248
249
250 public static File repoFile(Repository repo, String... parts) {
251 File result = repo.getDirectory();
252 for (String part : parts) {
253 result = new File(result, part);
254 }
255 return result;
256 }
257
258
259
260
261
262
263
264 public static String getMissingFileErrorText() {
265 String error = "No such file or directory";
266 String osName = System.getProperty("os.name");
267 if (osName.startsWith("Windows")) {
268 error = "The system cannot find the file specified";
269 }
270 return error;
271 }
272
273
274
275
276
277
278
279
280 protected static File createTempDir() throws IOException {
281 return Files.createTempDir().getCanonicalFile();
282 }
283
284
285
286
287
288
289
290 public static void deleteTempDir(File file) throws IOException {
291 Utils.deleteTempDir(file);
292 }
293
294 protected void assertSingleton(Object obj, Collection<?> coll) {
295 Assert.assertEquals(obj, Utils.single(coll));
296 }
297
298 protected void assertFailedExecution(AbstractCommand cmd) {
299 assertFailedExecution(cmd, "");
300 }
301
302 protected void assertFailedExecution(AbstractCommand cmd, String msg) {
303 if (msg.length() > 0) {
304 msg = " Message: " + msg;
305 }
306 Assert.fail("Exception expected! Return code: " + cmd.getReturnCode() + "." + msg);
307 }
308
309
310
311
312
313
314
315
316
317 protected void execHgCommand(BaseRepository repo, String... args) {
318 try {
319 String[] arr = Utils.arrayConcat(new String[] { REPO_CONF.getHgBin(), "--repo",
320 repo.getDirectory().getAbsolutePath() }, args);
321
322 Process process = Runtime.getRuntime().exec(arr);
323 String stderr = Utils.readStream(process.getErrorStream(), repo.newDecoder());
324 Utils.consumeAll(process.getInputStream());
325
326 if (process.waitFor() != 0) {
327 throw new RuntimeException(stderr);
328 }
329 } catch (IOException e) {
330 throw new RuntimeIOException(e);
331 } catch (InterruptedException e) {
332 throw Utils.asRuntime(e);
333 }
334 }
335
336
337
338
339
340
341
342
343 protected Server getFirstServer(Repository repo) {
344 return repo.getServerPool().getServers().get(0);
345 }
346
347 protected static ServeState startServing(Repository repo,
348 String... additionalConfig) {
349
350
351 Assume.assumeTrue(!Utils.isWindows());
352
353 final File pidFile;
354
355 try {
356 pidFile = File.createTempFile("javahg", ".pid");
357
358 final Process process = Runtime.getRuntime().exec(
359 ObjectArrays.concat(
360 new String[] {
361 RepositoryConfiguration.DEFAULT.getHgBin(),
362 "serve", "--port", "0", "-d", "--pid-file",
363 pidFile.toString(), "-R",
364 repo.getDirectory().toString() },
365 additionalConfig, String.class));
366
367 HgInputStream in = new HgInputStream(process.getInputStream(),
368 repo.newDecoder());
369
370 Assert.assertTrue(in.find("(bound to *:".getBytes()));
371 final int port = in.readDecimal().intValue();
372 in.close();
373
374 return new ServeState() {
375
376 public int getPort() {
377 return port;
378 }
379
380 public void stop() {
381 BufferedReader in = null;;
382 try {
383
384 process.destroy();
385
386 in = new BufferedReader(new InputStreamReader(new FileInputStream(pidFile)));
387 killProcess(Integer.parseInt(in.readLine()));
388
389 } catch (Exception e) {
390 throw Utils.asRuntime(e);
391 } finally {
392 try {
393 in.close();
394 } catch (IOException e) {
395 throw Utils.asRuntime(e);
396 }
397 }
398 }};
399 } catch (IOException e) {
400 throw Utils.asRuntime(e);
401 }
402 }
403
404
405
406
407
408
409 protected static void killProcess(int pid) {
410 try {
411 Runtime rt = Runtime.getRuntime();
412 if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1) {
413 rt.exec("taskkill " + pid).waitFor();
414 } else {
415 rt.exec(new String[] { "kill", "-9", "" + pid }).waitFor();
416 }
417 } catch (IOException e) {
418 throw Utils.asRuntime(e);
419 } catch (InterruptedException e) {
420 throw Utils.asRuntime(e);
421 }
422 }
423
424 protected static class TestableCommand extends GenericCommand {
425
426 public TestableCommand(Repository repository, String commandName) {
427 super(repository, commandName);
428 }
429
430 public HgInputStream executeToStream(String... args) {
431 return launchStream(args);
432 }
433 }
434
435 protected interface ServeState
436 {
437 public int getPort();
438 public void stop();
439 }
440 }