View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.cli2.application;
18  
19  import java.io.BufferedReader;
20  import java.io.IOException;
21  import java.io.PrintWriter;
22  import java.io.StringReader;
23  import java.io.StringWriter;
24  
25  import junit.framework.Test;
26  import junit.framework.TestCase;
27  import junit.framework.TestSuite;
28  
29  import org.apache.commons.cli2.Argument;
30  import org.apache.commons.cli2.CommandLine;
31  import org.apache.commons.cli2.Group;
32  import org.apache.commons.cli2.Option;
33  import org.apache.commons.cli2.OptionException;
34  import org.apache.commons.cli2.builder.ArgumentBuilder;
35  import org.apache.commons.cli2.builder.DefaultOptionBuilder;
36  import org.apache.commons.cli2.builder.GroupBuilder;
37  import org.apache.commons.cli2.commandline.Parser;
38  import org.apache.commons.cli2.option.ArgumentImpl;
39  import org.apache.commons.cli2.option.SourceDestArgument;
40  import org.apache.commons.cli2.util.HelpFormatter;
41  
42  /**
43   * <p>Test the <code>cp</code> command. Duplicated Option types are not
44   * tested e.g. -a and -d are the same Option type.</p>
45   *
46   * <p>The following is the man output for 'cp'. See
47   * <a href="http://www.rt.com/man/cp.1.html">http://www.rt.com/man/cp.1.html</a>.</p>
48   *
49   * <pre>
50   *  CP(1) FSF CP(1)
51   *
52   *  NAME cp - copy files and directories
53   *
54   *  SYNOPSIS cp [OPTION]... SOURCE DEST cp [OPTION]... SOURCE... DIRECTORY
55   *
56   *  DESCRIPTION Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.
57   *
58   *  -a, --archive same as -dpR
59   *
60   *  -b, --backup make backup before removal
61   *
62   *  -d, --no-dereference preserve links
63   *
64   *  -f, --force remove existing destinations, never prompt
65   *
66   *  -i, --interactive prompt before overwrite
67   *
68   *  -l, --link link files instead of copying
69   *
70   *  -p, --preserve preserve file attributes if possible
71   *
72   *  -P, --parents append source path to DIRECTORY
73   * -r copy recursively, non-directories as files
74   *
75   *  --sparse=WHEN control creation of sparse files
76   *
77   *  -R, --recursive copy directories recursively
78   *
79   *  -s, --symbolic-link make symbolic links instead of copying
80   *
81   *  -S, --suffix=SUFFIX override the usual backup suffix
82   *
83   *  -u, --update copy only when the SOURCE file is newer than the destination file or when the destination file is missing
84   *
85   *  -v, --verbose explain what is being done
86   *
87   *  -V, --version-control=WORD override the usual version control
88   *
89   *  -x, --one-file-system stay on this file system
90   *
91   *  --help display this help and exit
92   *
93   *  --version output version information and exit
94   *
95   *  By default, sparse SOURCE files are detected by a crude heuristic and the corresponding DEST file is made sparse as well. That is the behavior selected by --sparse=auto. Specify --sparse=always to create a sparse DEST file when- ever the SOURCE file contains a long enough sequence of zero bytes. Use --sparse=never to inhibit creation of sparse files.
96   *
97   *  The backup suffix is ~, unless set with SIMPLE_BACKUP_SUF- FIX. The version control may be set with VERSION_CONTROL, values are:
98   * t, numbered make numbered backups
99   *
100  *  nil, existing numbered if numbered backups exist, simple other- wise
101  *
102  *  never, simple always make simple backups
103  *
104  *  As a special case, cp makes a backup of SOURCE when the force and backup options are given and SOURCE and DEST are the same name for an existing, regular file. * </pre>
105  * </pre>
106  *
107  * @author Rob Oxspring
108  * @author John Keyes
109  */
110 public class CpTest extends TestCase {
111 
112     /** Option Builder */
113     private static final DefaultOptionBuilder oBuilder =
114         new DefaultOptionBuilder();
115 
116     /** Argument Builder */
117     private static final ArgumentBuilder aBuilder = new ArgumentBuilder();
118 
119     /** Group Builder */
120     private static final GroupBuilder gBuilder = new GroupBuilder();
121 
122     private Group options;
123 
124     public static Test suite() {
125         return new TestSuite(CpTest.class);
126     }
127 
128     private ArgumentImpl source;
129     private ArgumentImpl dest;
130     private Argument targets;
131 
132     private Option archive;
133     private Option backup;
134     private Option noDereference;
135     private Option force;
136     private Option interactive;
137     private Option link;
138     private Option preserve;
139     private Option parents;
140     private Option recursive1;
141     private Option sparse;
142     private Option recursive2;
143     private Option symbolicLink;
144     private Option suffix;
145     private Option update;
146     private Option verbose;
147     private Option versionControl;
148     private Option oneFileSystem;
149     private Option help;
150     private Option version;
151 
152     public void setUp() {
153         source =
154             (ArgumentImpl)aBuilder.withName("SOURCE").withMinimum(1).create();
155         dest =
156             (ArgumentImpl)aBuilder
157                 .withName("DEST")
158                 .withMinimum(1)
159                 .withMaximum(1)
160                 .create();
161         targets = new SourceDestArgument(source, dest);
162 
163         archive =
164             oBuilder
165                 .withShortName("a")
166                 .withLongName("archive")
167                 .withDescription("same as -dpR")
168                 .create();
169 
170         backup =
171             oBuilder
172                 .withShortName("b")
173                 .withLongName("backup")
174                 .withDescription("make backup before removal")
175                 .create();
176 
177         noDereference =
178             oBuilder
179                 .withShortName("d")
180                 .withLongName("no-dereference")
181                 .withDescription("preserve links")
182                 .create();
183 
184         force =
185             oBuilder
186                 .withShortName("f")
187                 .withLongName("force")
188                 .withDescription("remove existing destinations, never prompt")
189                 .create();
190 
191         interactive =
192             oBuilder
193                 .withShortName("i")
194                 .withLongName("interactive")
195                 .withDescription("prompt before overwrite")
196                 .create();
197 
198         link =
199             oBuilder
200                 .withShortName("l")
201                 .withLongName("link")
202                 .withDescription("link files instead of copying")
203                 .create();
204 
205         preserve =
206             oBuilder
207                 .withShortName("p")
208                 .withLongName("preserve")
209                 .withDescription("preserve file attributes if possible")
210                 .create();
211 
212         parents =
213             oBuilder
214                 .withShortName("P")
215                 .withLongName("parents")
216                 .withDescription("append source path to DIRECTORY")
217                 .create();
218 
219         recursive1 =
220             oBuilder
221                 .withShortName("r")
222                 .withDescription("copy recursively, non-directories as files")
223                 .create();
224 
225         sparse =
226             oBuilder
227                 .withLongName("sparse")
228                 .withDescription("control creation of sparse files")
229                 .withArgument(
230                     aBuilder
231                         .withName("WHEN")
232                         .withMinimum(1)
233                         .withMaximum(1)
234                         .withInitialSeparator('=')
235                         .create())
236                 .create();
237 
238         recursive2 =
239             oBuilder
240                 .withShortName("R")
241                 .withLongName("recursive")
242                 .withDescription("copy directories recursively")
243                 .create();
244 
245         symbolicLink =
246             oBuilder
247                 .withShortName("s")
248                 .withLongName("symbolic-link")
249                 .withDescription("make symbolic links instead of copying")
250                 .create();
251 
252         suffix =
253             oBuilder
254                 .withShortName("S")
255                 .withLongName("suffix")
256                 .withDescription("override the usual backup suffix")
257                 .withArgument(
258                     aBuilder
259                         .withName("SUFFIX")
260                         .withMinimum(1)
261                         .withMaximum(1)
262                         .create())
263                 .create();
264 
265         update =
266             oBuilder
267                 .withShortName("u")
268                 .withLongName("update")
269                 .withDescription("copy only when the SOURCE file is newer than the destination file or when the destination file is missing")
270                 .create();
271 
272         verbose =
273             oBuilder
274                 .withShortName("v")
275                 .withLongName("verbose")
276                 .withDescription("explain what is being done")
277                 .create();
278 
279         versionControl =
280             oBuilder
281                 .withShortName("V")
282                 .withLongName("version-contol")
283                 .withDescription("explain what is being done")
284                 .withArgument(
285                     aBuilder
286                         .withName("WORD")
287                         .withInitialSeparator('=')
288                         .withMinimum(1)
289                         .withMaximum(1)
290                         .create())
291                 .create();
292 
293         oneFileSystem =
294             oBuilder
295                 .withShortName("x")
296                 .withLongName("one-file-system")
297                 .withDescription("stay on this file system")
298                 .create();
299 
300         help =
301             oBuilder
302                 .withLongName("help")
303                 .withDescription("display this help and exit")
304                 .create();
305 
306         version =
307             oBuilder
308                 .withLongName("version")
309                 .withDescription("output version information and exit")
310                 .create();
311 
312         options =
313             gBuilder
314                 .withOption(archive)
315                 .withOption(backup)
316                 .withOption(noDereference)
317                 .withOption(force)
318                 .withOption(interactive)
319                 .withOption(link)
320                 .withOption(preserve)
321                 .withOption(parents)
322                 .withOption(recursive1)
323                 .withOption(sparse)
324                 .withOption(recursive2)
325                 .withOption(symbolicLink)
326                 .withOption(suffix)
327                 .withOption(update)
328                 .withOption(verbose)
329                 .withOption(versionControl)
330                 .withOption(oneFileSystem)
331                 .withOption(help)
332                 .withOption(version)
333                 .withOption(targets)
334                 .withName("OPTIONS")
335                 .create();
336     }
337 
338     public void testNoSource() {
339         Parser parser = new Parser();
340         parser.setGroup(options);
341         try {
342             parser.parse(new String[0]);
343         }
344         catch (OptionException mve) {
345             assertEquals(
346                 "Missing value(s) SOURCE [SOURCE ...]",
347                 mve.getMessage());
348         }
349     }
350 
351     public void testOneSource() throws OptionException {
352         final String[] args = new String[] { "source1", "dest1" };
353         final Parser parser = new Parser();
354         parser.setGroup(options);
355         final CommandLine commandLine = parser.parse(args);
356 
357         assertTrue(commandLine.getValues(source).contains("source1"));
358         assertEquals(1, commandLine.getValues(source).size());
359         assertTrue(commandLine.getValues(dest).contains("dest1"));
360         assertEquals(1, commandLine.getValues(dest).size());
361     }
362 
363     public void testMultiSource() throws OptionException {
364         final String[] args =
365             new String[] { "source1", "source2", "source3", "dest1" };
366         final Parser parser = new Parser();
367         parser.setGroup(options);
368         final CommandLine commandLine = parser.parse(args);
369 
370         assertTrue(commandLine.getValues(source).contains("source1"));
371         assertTrue(commandLine.getValues(source).contains("source2"));
372         assertTrue(commandLine.getValues(source).contains("source3"));
373         assertEquals(3, commandLine.getValues(source).size());
374 
375         assertTrue(commandLine.getValues(dest).contains("dest1"));
376         assertEquals(1, commandLine.getValues(dest).size());
377     }
378 
379     public void testHelp() throws IOException {
380         final StringWriter out = new StringWriter();
381         final HelpFormatter helpFormatter = new HelpFormatter();
382         helpFormatter.setGroup(options);
383         helpFormatter.setPrintWriter(new PrintWriter(out));
384         helpFormatter.print();
385 
386         final BufferedReader in =
387             new BufferedReader(new StringReader(out.toString()));
388         assertEquals(
389             "Usage:                                                                          ",
390             in.readLine());
391         assertEquals(
392             " [-a -b -d -f -i -l -p -P -r --sparse <WHEN> -R -s -S <SUFFIX> -u -v -V <WORD>  ",
393             in.readLine());
394         assertEquals(
395             "-x --help --version] <SOURCE1> [<SOURCE2> ...] <DEST>                           ",
396             in.readLine());
397         assertEquals(
398             "OPTIONS                                                                         ",
399             in.readLine());
400         assertEquals(
401             "  -a (--archive)                same as -dpR                                    ",
402             in.readLine());
403         assertEquals(
404             "  -b (--backup)                 make backup before removal                      ",
405             in.readLine());
406         assertEquals(
407             "  -d (--no-dereference)         preserve links                                  ",
408             in.readLine());
409         assertEquals(
410             "  -f (--force)                  remove existing destinations, never prompt      ",
411             in.readLine());
412         assertEquals(
413             "  -i (--interactive)            prompt before overwrite                         ",
414             in.readLine());
415         assertEquals(
416             "  -l (--link)                   link files instead of copying                   ",
417             in.readLine());
418         assertEquals(
419             "  -p (--preserve)               preserve file attributes if possible            ",
420             in.readLine());
421         assertEquals(
422             "  -P (--parents)                append source path to DIRECTORY                 ",
423             in.readLine());
424         assertEquals(
425             "  -r                            copy recursively, non-directories as files      ",
426             in.readLine());
427         assertEquals(
428             "  --sparse WHEN                 control creation of sparse files                ",
429             in.readLine());
430         assertEquals(
431             "  -R (--recursive)              copy directories recursively                    ",
432             in.readLine());
433         assertEquals(
434             "  -s (--symbolic-link)          make symbolic links instead of copying          ",
435             in.readLine());
436         assertEquals(
437             "  -S (--suffix) SUFFIX          override the usual backup suffix                ",
438             in.readLine());
439         assertEquals(
440             "  -u (--update)                 copy only when the SOURCE file is newer than    ",
441             in.readLine());
442         assertEquals(
443             "                                the destination file or when the destination    ",
444             in.readLine());
445         assertEquals(
446             "                                file is missing                                 ",
447             in.readLine());
448         assertEquals(
449             "  -v (--verbose)                explain what is being done                      ",
450             in.readLine());
451         assertEquals(
452             "  -V (--version-contol) WORD    explain what is being done                      ",
453             in.readLine());
454         assertEquals(
455             "  -x (--one-file-system)        stay on this file system                        ",
456             in.readLine());
457         assertEquals(
458             "  --help                        display this help and exit                      ",
459             in.readLine());
460         assertEquals(
461             "  --version                     output version information and exit             ",
462             in.readLine());
463         assertEquals(
464             "  SOURCE [SOURCE ...]                                                           ",
465             in.readLine());
466         assertEquals(
467             "  DEST                                                                          ",
468             in.readLine());
469         assertNull(in.readLine());
470     }
471 }