1 package org.codehaus.plexus.util.cli;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.io.Writer;
22 import java.nio.file.Files;
23
24 import org.codehaus.plexus.util.IOUtil;
25 import org.codehaus.plexus.util.Os;
26 import org.codehaus.plexus.util.StringUtils;
27 import org.codehaus.plexus.util.cli.shell.BourneShell;
28 import org.codehaus.plexus.util.cli.shell.CmdShell;
29 import org.codehaus.plexus.util.cli.shell.Shell;
30 import org.junit.jupiter.api.BeforeEach;
31 import org.junit.jupiter.api.Test;
32
33 import static org.junit.jupiter.api.Assertions.assertEquals;
34 import static org.junit.jupiter.api.Assertions.assertTrue;
35 import static org.junit.jupiter.api.Assertions.fail;
36
37
38
39
40
41
42
43
44 public class CommandlineTest {
45 private String baseDir;
46
47
48
49
50
51
52 @BeforeEach
53 public void setUp() throws Exception {
54 baseDir = System.getProperty("basedir");
55
56 if (baseDir == null) {
57 baseDir = new File(".").getCanonicalPath();
58 }
59 }
60
61
62
63
64 @Test
65 public void testCommandlineWithoutCommandInConstructor() {
66 Commandline cmd = new Commandline(new Shell());
67 cmd.setWorkingDirectory(baseDir);
68 cmd.createArgument().setValue("cd");
69 cmd.createArgument().setValue(".");
70
71
72 assertEquals("cd .", cmd.toString());
73 }
74
75
76
77
78 @Test
79 public void testCommandlineWithCommandInConstructor() {
80 Commandline cmd = new Commandline("cd .", new Shell());
81 cmd.setWorkingDirectory(baseDir);
82
83
84 assertEquals("cd .", cmd.toString());
85 }
86
87
88
89
90
91
92 @Test
93 public void testExecuteBinaryOnPath() throws Exception {
94
95 Commandline cmd = new Commandline();
96 cmd.setWorkingDirectory(baseDir);
97 cmd.setExecutable("mvn");
98 assertEquals("mvn", cmd.getShell().getOriginalExecutable());
99 cmd.createArg().setValue("-version");
100 Process process = cmd.execute();
101 String out = IOUtil.toString(process.getInputStream());
102 assertTrue(out.contains("Apache Maven"));
103 assertTrue(out.contains("Maven home:"));
104 assertTrue(out.contains("Java version:"));
105 }
106
107
108
109
110
111
112 @org.junit.jupiter.api.Test
113 public void testExecute() throws Exception {
114
115 Commandline cmd = new Commandline();
116 cmd.setWorkingDirectory(baseDir);
117 cmd.setExecutable("echo");
118 assertEquals("echo", cmd.getShell().getOriginalExecutable());
119 cmd.createArgument().setValue("Hello");
120
121 Process process = cmd.execute();
122 assertEquals("Hello", IOUtil.toString(process.getInputStream()).trim());
123 }
124
125
126
127
128 @Test
129 public void testSetLine() {
130 Commandline cmd = new Commandline(new Shell());
131 cmd.setWorkingDirectory(baseDir);
132 cmd.setExecutable("echo");
133 cmd.createArgument().setLine(null);
134 cmd.createArgument().setLine("Hello");
135
136
137 assertEquals("echo Hello", cmd.toString());
138 }
139
140
141
142
143 @Test
144 public void testCreateCommandInReverseOrder() {
145 Commandline cmd = new Commandline(new Shell());
146 cmd.setWorkingDirectory(baseDir);
147 cmd.createArgument().setValue(".");
148 cmd.createArgument(true).setValue("cd");
149
150
151 assertEquals("cd .", cmd.toString());
152 }
153
154
155
156
157 @Test
158 public void testSetFile() {
159 Commandline cmd = new Commandline(new Shell());
160 cmd.setWorkingDirectory(baseDir);
161 cmd.createArgument().setValue("more");
162 File f = new File("test.txt");
163 cmd.createArgument().setFile(f);
164 String fileName = f.getAbsolutePath();
165 if (fileName.contains(" ")) {
166 fileName = "\"" + fileName + "\"";
167 }
168
169
170 assertEquals("more " + fileName, cmd.toString());
171 }
172
173
174
175
176
177
178 @Test
179 public void testGetShellCommandLineWindows() throws Exception {
180 Commandline cmd = new Commandline(new CmdShell());
181 cmd.setExecutable("c:\\Program Files\\xxx");
182 cmd.addArguments(new String[] {"a", "b"});
183 String[] shellCommandline = cmd.getShellCommandline();
184
185 assertEquals(5, shellCommandline.length, "Command line size");
186
187 assertEquals("cmd.exe", shellCommandline[0]);
188 assertEquals("/X", shellCommandline[1]);
189 assertEquals("/D", shellCommandline[2]);
190 assertEquals("/C", shellCommandline[3]);
191 String expectedShellCmd = "\"c:" + File.separator + "Program Files" + File.separator + "xxx\" a b";
192 expectedShellCmd = "\"" + expectedShellCmd + "\"";
193 assertEquals(expectedShellCmd, shellCommandline[4]);
194 }
195
196
197
198
199
200
201 @Test
202 public void testGetShellCommandLineWindowsWithSeveralQuotes() throws Exception {
203 Commandline cmd = new Commandline(new CmdShell());
204 cmd.setExecutable("c:\\Program Files\\xxx");
205 cmd.addArguments(new String[] {"c:\\Documents and Settings\\whatever", "b"});
206 String[] shellCommandline = cmd.getShellCommandline();
207
208 assertEquals(5, shellCommandline.length, "Command line size");
209
210 assertEquals("cmd.exe", shellCommandline[0]);
211 assertEquals("/X", shellCommandline[1]);
212 assertEquals("/D", shellCommandline[2]);
213 assertEquals("/C", shellCommandline[3]);
214 String expectedShellCmd = "\"c:" + File.separator + "Program Files" + File.separator
215 + "xxx\" \"c:\\Documents and Settings\\whatever\" b";
216 expectedShellCmd = "\"" + expectedShellCmd + "\"";
217 assertEquals(expectedShellCmd, shellCommandline[4]);
218 }
219
220
221
222
223
224
225 @Test
226 public void testGetShellCommandLineBash() throws Exception {
227 Commandline cmd = new Commandline(new BourneShell());
228 cmd.setExecutable("/bin/echo");
229 cmd.addArguments(new String[] {"hello world"});
230
231 String[] shellCommandline = cmd.getShellCommandline();
232
233 assertEquals(3, shellCommandline.length, "Command line size");
234
235 assertEquals("/bin/sh", shellCommandline[0]);
236 assertEquals("-c", shellCommandline[1]);
237 String expectedShellCmd = "'/bin/echo' 'hello world'";
238 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
239 expectedShellCmd = "'\\bin\\echo' \'hello world\'";
240 }
241 assertEquals(expectedShellCmd, shellCommandline[2]);
242 }
243
244
245
246
247
248
249 @Test
250 public void testGetShellCommandLineBash_WithWorkingDirectory() throws Exception {
251 Commandline cmd = new Commandline(new BourneShell());
252 cmd.setExecutable("/bin/echo");
253 cmd.addArguments(new String[] {"hello world"});
254 File root = File.listRoots()[0];
255 File workingDirectory = new File(root, "path with spaces");
256 cmd.setWorkingDirectory(workingDirectory);
257
258 String[] shellCommandline = cmd.getShellCommandline();
259
260 assertEquals(3, shellCommandline.length, "Command line size");
261
262 assertEquals("/bin/sh", shellCommandline[0]);
263 assertEquals("-c", shellCommandline[1]);
264 String expectedShellCmd = "cd '" + root.getAbsolutePath() + "path with spaces' && '/bin/echo' 'hello world'";
265 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
266 expectedShellCmd = "cd '" + root.getAbsolutePath() + "path with spaces' && '\\bin\\echo' 'hello world'";
267 }
268 assertEquals(expectedShellCmd, shellCommandline[2]);
269 }
270
271
272
273
274
275
276 @Test
277 public void testGetShellCommandLineBash_WithSingleQuotedArg() throws Exception {
278 Commandline cmd = new Commandline(new BourneShell());
279 cmd.setExecutable("/bin/echo");
280 cmd.addArguments(new String[] {"\'hello world\'"});
281
282 String[] shellCommandline = cmd.getShellCommandline();
283
284 assertEquals(3, shellCommandline.length, "Command line size");
285
286 assertEquals("/bin/sh", shellCommandline[0]);
287 assertEquals("-c", shellCommandline[1]);
288 String expectedShellCmd = "'/bin/echo' ''\"'\"'hello world'\"'\"''";
289 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
290 expectedShellCmd = expectedShellCmd.replace("/bin/echo", "\\bin\\echo");
291 }
292 assertEquals(expectedShellCmd, shellCommandline[2]);
293 }
294
295
296
297
298
299
300 @Test
301 public void testGetShellCommandLineNonWindows() throws Exception {
302 Commandline cmd = new Commandline(new BourneShell());
303 cmd.setExecutable("/usr/bin");
304 cmd.addArguments(new String[] {"a", "b"});
305 String[] shellCommandline = cmd.getShellCommandline();
306
307 assertEquals(3, shellCommandline.length, "Command line size");
308
309 assertEquals("/bin/sh", shellCommandline[0]);
310 assertEquals("-c", shellCommandline[1]);
311
312 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
313 assertEquals("'\\usr\\bin' 'a' 'b'", shellCommandline[2]);
314 } else {
315 assertEquals("'/usr/bin' 'a' 'b'", shellCommandline[2]);
316 }
317 }
318
319
320
321
322
323
324 @Test
325 public void testEnvironment() throws Exception {
326 Commandline cmd = new Commandline();
327 cmd.addEnvironment("name", "value");
328 assertEquals("name=value", cmd.getEnvironmentVariables()[0]);
329 }
330
331
332
333
334
335
336 @Test
337 public void testEnvironmentWitOverrideSystemEnvironment() throws Exception {
338 Commandline cmd = new Commandline();
339 cmd.addSystemEnvironment();
340 cmd.addEnvironment("JAVA_HOME", "/usr/jdk1.5");
341 String[] environmentVariables = cmd.getEnvironmentVariables();
342
343 for (String environmentVariable : environmentVariables) {
344 if ("JAVA_HOME=/usr/jdk1.5".equals(environmentVariable)) {
345 return;
346 }
347 }
348
349 fail("can't find JAVA_HOME=/usr/jdk1.5");
350 }
351
352
353
354
355
356
357 @Test
358 public void testQuotedPathWithSingleApostrophe() throws Exception {
359 File dir = new File(System.getProperty("basedir"), "target/test/quotedpath'test");
360 createAndCallScript(dir, "echo Quoted");
361
362 dir = new File(System.getProperty("basedir"), "target/test/quoted path'test");
363 createAndCallScript(dir, "echo Quoted");
364 }
365
366
367
368
369
370
371 @Test
372 public void testPathWithShellExpansionStrings() throws Exception {
373 File dir = new File(System.getProperty("basedir"), "target/test/dollar$test");
374 createAndCallScript(dir, "echo Quoted");
375 }
376
377
378
379
380
381
382 @Test
383 public void testQuotedPathWithQuotationMark() throws Exception {
384 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
385 System.out.println("testQuotedPathWithQuotationMark() skipped on Windows");
386 return;
387 }
388
389 File dir = new File(System.getProperty("basedir"), "target/test/quotedpath\"test");
390 createAndCallScript(dir, "echo Quoted");
391
392 dir = new File(System.getProperty("basedir"), "target/test/quoted path\"test");
393 createAndCallScript(dir, "echo Quoted");
394 }
395
396
397
398
399
400
401
402 @Test
403 public void testQuotedPathWithQuotationMarkAndApostrophe() throws Exception {
404 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
405 System.out.println("testQuotedPathWithQuotationMarkAndApostrophe() skipped on Windows");
406 return;
407 }
408
409 File dir = new File(System.getProperty("basedir"), "target/test/quotedpath\"'test");
410 createAndCallScript(dir, "echo Quoted");
411
412 dir = new File(System.getProperty("basedir"), "target/test/quoted path\"'test");
413 createAndCallScript(dir, "echo Quoted");
414 }
415
416
417
418
419
420
421 @Test
422 public void testOnlyQuotedPath() throws Exception {
423 File dir = new File(System.getProperty("basedir"), "target/test/quotedpath\'test");
424
425 File javaHome = new File(System.getProperty("java.home"));
426 File java;
427 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
428 java = new File(javaHome, "/bin/java.exe");
429 } else {
430 java = new File(javaHome, "/bin/java");
431 }
432
433 if (!java.exists()) {
434 throw new IOException(java.getAbsolutePath() + " doesn't exist");
435 }
436
437 String javaBinStr = java.getAbsolutePath();
438 if (Os.isFamily(Os.FAMILY_WINDOWS) && javaBinStr.contains(" ")) {
439 javaBinStr = "\"" + javaBinStr + "\"";
440 }
441
442 createAndCallScript(dir, javaBinStr + " -version");
443 }
444
445
446
447
448
449
450 @Test
451 public void testDollarSignInArgumentPath() throws Exception {
452 File dir = new File(System.getProperty("basedir"), "target/test");
453 if (!dir.exists()) {
454 assertTrue(dir.mkdirs(), "Can't create dir:" + dir.getAbsolutePath());
455 }
456
457 Writer writer = null;
458 try {
459 writer = Files.newBufferedWriter(dir.toPath().resolve("test$1.txt"));
460 IOUtil.copy("Success", writer);
461 } finally {
462 IOUtil.close(writer);
463 }
464
465 Commandline cmd = new Commandline();
466
467 cmd.getShell().setQuotedArgumentsEnabled(true);
468 cmd.setExecutable("cat");
469 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
470 cmd.setExecutable("dir");
471 }
472 cmd.setWorkingDirectory(dir);
473 cmd.createArg().setLine("test$1.txt");
474
475 executeCommandLine(cmd);
476 }
477
478
479
480
481
482
483 @Test
484 public void testTimeOutException() throws Exception {
485 File javaHome = new File(System.getProperty("java.home"));
486 File java;
487 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
488 java = new File(javaHome, "/bin/java.exe");
489 } else {
490 java = new File(javaHome, "/bin/java");
491 }
492
493 if (!java.exists()) {
494 throw new IOException(java.getAbsolutePath() + " doesn't exist");
495 }
496
497 Commandline cli = new Commandline();
498 cli.setExecutable(java.getAbsolutePath());
499 cli.createArg().setLine("-version");
500 CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
501 try {
502
503 CommandLineUtils.executeCommandLine(cli, new DefaultConsumer(), err, 1);
504 } catch (CommandLineTimeOutException e) {
505
506 }
507 }
508
509
510
511
512
513
514
515 private static void makeExecutable(File path) throws IOException {
516 if (path == null) {
517 throw new IllegalArgumentException("The file is null");
518 }
519
520 if (!path.isFile()) {
521 throw new IllegalArgumentException("The file '" + path.getAbsolutePath() + "' should be a file");
522 }
523
524 if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
525 Process proc = Runtime.getRuntime().exec(new String[] {"chmod", "a+x", path.getAbsolutePath()});
526 while (true) {
527 try {
528 proc.waitFor();
529 break;
530 } catch (InterruptedException e) {
531
532 }
533 }
534 }
535 }
536
537
538
539
540
541
542
543
544
545 private static void createAndCallScript(File dir, String content) throws Exception {
546 if (!dir.exists()) {
547 assertTrue(dir.mkdirs(), "Can't create dir:" + dir.getAbsolutePath());
548 }
549
550
551 File bat;
552 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
553 bat = new File(dir, "echo.bat");
554 } else {
555 bat = new File(dir, "echo");
556 }
557
558 Writer w = Files.newBufferedWriter(bat.toPath());
559 try {
560 IOUtil.copy(content, w);
561 } finally {
562 IOUtil.close(w);
563 }
564
565
566 makeExecutable(bat);
567
568 Commandline cmd = new Commandline();
569 cmd.setExecutable(bat.getAbsolutePath());
570 cmd.setWorkingDirectory(dir);
571
572
573 executeCommandLine(cmd);
574 }
575
576
577
578
579
580
581
582 private static void executeCommandLine(Commandline cmd) throws Exception {
583 CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
584
585 try {
586 System.out.println("Command line is: " + StringUtils.join(cmd.getShellCommandline(), " "));
587
588 int exitCode = CommandLineUtils.executeCommandLine(cmd, new DefaultConsumer(), err);
589
590 if (exitCode != 0) {
591 String msg = "Exit code: " + exitCode + " - " + err.getOutput();
592 throw new Exception(msg.toString());
593 }
594 } catch (CommandLineException e) {
595 throw new Exception("Unable to execute command: " + e.getMessage(), e);
596 }
597 }
598 }