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(4, shellCommandline.length, "Command line size");
186
187 assertEquals("cmd.exe", shellCommandline[0]);
188 assertEquals("/X", shellCommandline[1]);
189 assertEquals("/C", shellCommandline[2]);
190 String expectedShellCmd = "\"c:" + File.separator + "Program Files" + File.separator + "xxx\" a b";
191 expectedShellCmd = "\"" + expectedShellCmd + "\"";
192 assertEquals(expectedShellCmd, shellCommandline[3]);
193 }
194
195
196
197
198
199
200 @Test
201 public void testGetShellCommandLineWindowsWithSeveralQuotes() throws Exception {
202 Commandline cmd = new Commandline(new CmdShell());
203 cmd.setExecutable("c:\\Program Files\\xxx");
204 cmd.addArguments(new String[] {"c:\\Documents and Settings\\whatever", "b"});
205 String[] shellCommandline = cmd.getShellCommandline();
206
207 assertEquals(4, shellCommandline.length, "Command line size");
208
209 assertEquals("cmd.exe", shellCommandline[0]);
210 assertEquals("/X", shellCommandline[1]);
211 assertEquals("/C", shellCommandline[2]);
212 String expectedShellCmd = "\"c:" + File.separator + "Program Files" + File.separator
213 + "xxx\" \"c:\\Documents and Settings\\whatever\" b";
214 expectedShellCmd = "\"" + expectedShellCmd + "\"";
215 assertEquals(expectedShellCmd, shellCommandline[3]);
216 }
217
218
219
220
221
222
223 @Test
224 public void testGetShellCommandLineBash() throws Exception {
225 Commandline cmd = new Commandline(new BourneShell());
226 cmd.setExecutable("/bin/echo");
227 cmd.addArguments(new String[] {"hello world"});
228
229 String[] shellCommandline = cmd.getShellCommandline();
230
231 assertEquals(3, shellCommandline.length, "Command line size");
232
233 assertEquals("/bin/sh", shellCommandline[0]);
234 assertEquals("-c", shellCommandline[1]);
235 String expectedShellCmd = "'/bin/echo' 'hello world'";
236 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
237 expectedShellCmd = "'\\bin\\echo' \'hello world\'";
238 }
239 assertEquals(expectedShellCmd, shellCommandline[2]);
240 }
241
242
243
244
245
246
247 @Test
248 public void testGetShellCommandLineBash_WithWorkingDirectory() throws Exception {
249 Commandline cmd = new Commandline(new BourneShell());
250 cmd.setExecutable("/bin/echo");
251 cmd.addArguments(new String[] {"hello world"});
252 File root = File.listRoots()[0];
253 File workingDirectory = new File(root, "path with spaces");
254 cmd.setWorkingDirectory(workingDirectory);
255
256 String[] shellCommandline = cmd.getShellCommandline();
257
258 assertEquals(3, shellCommandline.length, "Command line size");
259
260 assertEquals("/bin/sh", shellCommandline[0]);
261 assertEquals("-c", shellCommandline[1]);
262 String expectedShellCmd = "cd '" + root.getAbsolutePath() + "path with spaces' && '/bin/echo' 'hello world'";
263 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
264 expectedShellCmd = "cd '" + root.getAbsolutePath() + "path with spaces' && '\\bin\\echo' 'hello world'";
265 }
266 assertEquals(expectedShellCmd, shellCommandline[2]);
267 }
268
269
270
271
272
273
274 @Test
275 public void testGetShellCommandLineBash_WithSingleQuotedArg() throws Exception {
276 Commandline cmd = new Commandline(new BourneShell());
277 cmd.setExecutable("/bin/echo");
278 cmd.addArguments(new String[] {"\'hello world\'"});
279
280 String[] shellCommandline = cmd.getShellCommandline();
281
282 assertEquals(3, shellCommandline.length, "Command line size");
283
284 assertEquals("/bin/sh", shellCommandline[0]);
285 assertEquals("-c", shellCommandline[1]);
286 String expectedShellCmd = "'/bin/echo' ''\"'\"'hello world'\"'\"''";
287 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
288 expectedShellCmd = expectedShellCmd.replace("/bin/echo", "\\bin\\echo");
289 }
290 assertEquals(expectedShellCmd, shellCommandline[2]);
291 }
292
293
294
295
296
297
298 @Test
299 public void testGetShellCommandLineNonWindows() throws Exception {
300 Commandline cmd = new Commandline(new BourneShell());
301 cmd.setExecutable("/usr/bin");
302 cmd.addArguments(new String[] {"a", "b"});
303 String[] shellCommandline = cmd.getShellCommandline();
304
305 assertEquals(3, shellCommandline.length, "Command line size");
306
307 assertEquals("/bin/sh", shellCommandline[0]);
308 assertEquals("-c", shellCommandline[1]);
309
310 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
311 assertEquals("'\\usr\\bin' 'a' 'b'", shellCommandline[2]);
312 } else {
313 assertEquals("'/usr/bin' 'a' 'b'", shellCommandline[2]);
314 }
315 }
316
317
318
319
320
321
322 @Test
323 public void testEnvironment() throws Exception {
324 Commandline cmd = new Commandline();
325 cmd.addEnvironment("name", "value");
326 assertEquals("name=value", cmd.getEnvironmentVariables()[0]);
327 }
328
329
330
331
332
333
334 @Test
335 public void testEnvironmentWitOverrideSystemEnvironment() throws Exception {
336 Commandline cmd = new Commandline();
337 cmd.addSystemEnvironment();
338 cmd.addEnvironment("JAVA_HOME", "/usr/jdk1.5");
339 String[] environmentVariables = cmd.getEnvironmentVariables();
340
341 for (String environmentVariable : environmentVariables) {
342 if ("JAVA_HOME=/usr/jdk1.5".equals(environmentVariable)) {
343 return;
344 }
345 }
346
347 fail("can't find JAVA_HOME=/usr/jdk1.5");
348 }
349
350
351
352
353
354
355 @Test
356 public void testQuotedPathWithSingleApostrophe() throws Exception {
357 File dir = new File(System.getProperty("basedir"), "target/test/quotedpath'test");
358 createAndCallScript(dir, "echo Quoted");
359
360 dir = new File(System.getProperty("basedir"), "target/test/quoted path'test");
361 createAndCallScript(dir, "echo Quoted");
362 }
363
364
365
366
367
368
369 @Test
370 public void testPathWithShellExpansionStrings() throws Exception {
371 File dir = new File(System.getProperty("basedir"), "target/test/dollar$test");
372 createAndCallScript(dir, "echo Quoted");
373 }
374
375
376
377
378
379
380 @Test
381 public void testQuotedPathWithQuotationMark() throws Exception {
382 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
383 System.out.println("testQuotedPathWithQuotationMark() skipped on Windows");
384 return;
385 }
386
387 File dir = new File(System.getProperty("basedir"), "target/test/quotedpath\"test");
388 createAndCallScript(dir, "echo Quoted");
389
390 dir = new File(System.getProperty("basedir"), "target/test/quoted path\"test");
391 createAndCallScript(dir, "echo Quoted");
392 }
393
394
395
396
397
398
399
400 @Test
401 public void testQuotedPathWithQuotationMarkAndApostrophe() throws Exception {
402 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
403 System.out.println("testQuotedPathWithQuotationMarkAndApostrophe() skipped on Windows");
404 return;
405 }
406
407 File dir = new File(System.getProperty("basedir"), "target/test/quotedpath\"'test");
408 createAndCallScript(dir, "echo Quoted");
409
410 dir = new File(System.getProperty("basedir"), "target/test/quoted path\"'test");
411 createAndCallScript(dir, "echo Quoted");
412 }
413
414
415
416
417
418
419 @Test
420 public void testOnlyQuotedPath() throws Exception {
421 File dir = new File(System.getProperty("basedir"), "target/test/quotedpath\'test");
422
423 File javaHome = new File(System.getProperty("java.home"));
424 File java;
425 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
426 java = new File(javaHome, "/bin/java.exe");
427 } else {
428 java = new File(javaHome, "/bin/java");
429 }
430
431 if (!java.exists()) {
432 throw new IOException(java.getAbsolutePath() + " doesn't exist");
433 }
434
435 String javaBinStr = java.getAbsolutePath();
436 if (Os.isFamily(Os.FAMILY_WINDOWS) && javaBinStr.contains(" ")) {
437 javaBinStr = "\"" + javaBinStr + "\"";
438 }
439
440 createAndCallScript(dir, javaBinStr + " -version");
441 }
442
443
444
445
446
447
448 @Test
449 public void testDollarSignInArgumentPath() throws Exception {
450 File dir = new File(System.getProperty("basedir"), "target/test");
451 if (!dir.exists()) {
452 assertTrue(dir.mkdirs(), "Can't create dir:" + dir.getAbsolutePath());
453 }
454
455 Writer writer = null;
456 try {
457 writer = Files.newBufferedWriter(dir.toPath().resolve("test$1.txt"));
458 IOUtil.copy("Success", writer);
459 } finally {
460 IOUtil.close(writer);
461 }
462
463 Commandline cmd = new Commandline();
464
465 cmd.getShell().setQuotedArgumentsEnabled(true);
466 cmd.setExecutable("cat");
467 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
468 cmd.setExecutable("dir");
469 }
470 cmd.setWorkingDirectory(dir);
471 cmd.createArg().setLine("test$1.txt");
472
473 executeCommandLine(cmd);
474 }
475
476
477
478
479
480
481 @Test
482 public void testTimeOutException() throws Exception {
483 File javaHome = new File(System.getProperty("java.home"));
484 File java;
485 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
486 java = new File(javaHome, "/bin/java.exe");
487 } else {
488 java = new File(javaHome, "/bin/java");
489 }
490
491 if (!java.exists()) {
492 throw new IOException(java.getAbsolutePath() + " doesn't exist");
493 }
494
495 Commandline cli = new Commandline();
496 cli.setExecutable(java.getAbsolutePath());
497 cli.createArg().setLine("-version");
498 CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
499 try {
500
501 CommandLineUtils.executeCommandLine(cli, new DefaultConsumer(), err, 1);
502 } catch (CommandLineTimeOutException e) {
503
504 }
505 }
506
507
508
509
510
511
512
513 private static void makeExecutable(File path) throws IOException {
514 if (path == null) {
515 throw new IllegalArgumentException("The file is null");
516 }
517
518 if (!path.isFile()) {
519 throw new IllegalArgumentException("The file '" + path.getAbsolutePath() + "' should be a file");
520 }
521
522 if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
523 Process proc = Runtime.getRuntime().exec(new String[] {"chmod", "a+x", path.getAbsolutePath()});
524 while (true) {
525 try {
526 proc.waitFor();
527 break;
528 } catch (InterruptedException e) {
529
530 }
531 }
532 }
533 }
534
535
536
537
538
539
540
541
542
543 private static void createAndCallScript(File dir, String content) throws Exception {
544 if (!dir.exists()) {
545 assertTrue(dir.mkdirs(), "Can't create dir:" + dir.getAbsolutePath());
546 }
547
548
549 File bat;
550 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
551 bat = new File(dir, "echo.bat");
552 } else {
553 bat = new File(dir, "echo");
554 }
555
556 Writer w = Files.newBufferedWriter(bat.toPath());
557 try {
558 IOUtil.copy(content, w);
559 } finally {
560 IOUtil.close(w);
561 }
562
563
564 makeExecutable(bat);
565
566 Commandline cmd = new Commandline();
567 cmd.setExecutable(bat.getAbsolutePath());
568 cmd.setWorkingDirectory(dir);
569
570
571 executeCommandLine(cmd);
572 }
573
574
575
576
577
578
579
580 private static void executeCommandLine(Commandline cmd) throws Exception {
581 CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
582
583 try {
584 System.out.println("Command line is: " + StringUtils.join(cmd.getShellCommandline(), " "));
585
586 int exitCode = CommandLineUtils.executeCommandLine(cmd, new DefaultConsumer(), err);
587
588 if (exitCode != 0) {
589 String msg = "Exit code: " + exitCode + " - " + err.getOutput();
590 throw new Exception(msg.toString());
591 }
592 } catch (CommandLineException e) {
593 throw new Exception("Unable to execute command: " + e.getMessage(), e);
594 }
595 }
596 }