1   /**
2    * Copyright 2010, CSIRO Australia.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  /**
18   * 
19   */
20  package au.csiro.netcdf;
21  
22  import java.io.BufferedWriter;
23  import java.io.ByteArrayOutputStream;
24  import java.io.File;
25  import java.io.FileWriter;
26  import java.io.IOException;
27  import java.io.PrintStream;
28  
29  import junit.framework.TestCase;
30  
31  import org.apache.commons.cli.Options;
32  import org.apache.commons.cli.ParseException;
33  
34  import au.csiro.netcdf.cli.Command;
35  
36  /**
37   * This class is a unit test suite to verify that the Extract command operates correctly.
38   * <p>
39   * Copyright 2010, CSIRO Australia All rights reserved.
40   * 
41   * @author Robert Bridle on 17/03/2010
42   * @version $Revision: 78 $ $Date: 2010-07-24 16:23:13 +1000 (Sat, 24 Jul 2010) $
43   */
44  public class TestExtractCommand extends TestCase
45  {
46      /**
47       * An instance of the extract command that we want to test.
48       */
49      private Command extractCommand = new NcCSVExtract();
50      
51      /**
52       * A dummy csv file that we can test the extract command on.
53       */
54      private final String dummyCSVFilename = System.getProperty("user.dir") + "\\test.csv";
55      
56      /**
57       * The contents of the dummy csv file, where letters index the columns and numbers index the rows.
58       */
59      private final String[] dummyCSVFileContents = new String[] { "A1, B1, C1" + System.getProperty("line.separator"), 
60                                                                   "A2, B2, C2" + System.getProperty("line.separator"), 
61                                                                   "A3, B3, B3" + System.getProperty("line.separator") };
62  
63      /**
64       * An invalid columnIndex of the dummy csv file.
65       */
66      private String invalidColumnIndex = "999";
67      
68      /**
69       * An invalid end rowIndex of the dummy csv file
70       */
71      private String invalidEndRowIndex = "999";
72      
73      /**
74       * An valid columnIndex of the dummy csv file.
75       */
76      private String validColumnIndex = "0";
77  
78      /**
79       * A valid start rowIndex of the dummy csv file.
80       */
81      private String validStartRowIndex = "1";
82  
83      /**
84       * A valid end rowIndex of the dummy csv file
85       */
86      private String validEndRowIndex = "2";
87          
88      /**
89       * The valid values of columnIndex=0, rowStart=1, rowEnd=2 of the dummy csv file.
90       */
91      private String validValuesCol0Row1Row2 = "A2" + System.getProperty("line.separator") + 
92                                                  "A3"+ System.getProperty("line.separator");
93  
94      /**
95       * The valid values of columnIndex=0 of the dummy csv file.
96       */
97      private String validValuesCol0Row0Row1Row2 = "A1" + System.getProperty("line.separator") + 
98                                                      "A2" + System.getProperty("line.separator") + 
99                                                      "A3" + System.getProperty("line.separator");
100 
101     /**
102      * Used to capture standard output
103      */
104     private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
105 
106     /*
107      * (non-Javadoc)
108      * 
109      * @see junit.framework.TestCase#setUp()
110      */
111     @Override
112     protected void setUp() throws Exception
113     {
114         super.setUp();
115         
116         // create dummy csv file with content.
117         this.createDummyCSVFile();
118         
119         // write standard output to a stream we can examine.
120         System.setOut(new PrintStream(outContent));
121     }
122 
123     /*
124      * (non-Javadoc)
125      * 
126      * @see junit.framework.TestCase#tearDown()
127      */
128     @Override
129     protected void tearDown() throws Exception
130     {
131         super.tearDown();
132         
133         System.setOut(null);
134         
135         // delete dummy csv file
136         File file = new File(this.dummyCSVFilename);
137         if(file.exists())
138         {
139             file.delete();
140         }
141     }
142 
143     /**
144      * Test that the commands options are used.
145      */
146     public final void testCreateOptions()
147     {
148         Options options = extractCommand.createOptions();
149 
150         assertTrue("The following option is not recognised by the command: " + NcCSVExtract.INPUT_FILE, options
151                 .hasOption(NcCSVExtract.INPUT_FILE));
152         assertTrue("The following option is not recognised by the command: " + NcCSVExtract.COLUMN_INDEX, options
153                 .hasOption(NcCSVExtract.COLUMN_INDEX));
154         assertTrue("The following option is not recognised by the command: " + NcCSVExtract.START_ROW, options
155                 .hasOption(NcCSVExtract.START_ROW));
156         assertTrue("The following option is not recognised by the command: " + NcCSVExtract.END_ROW, options
157                 .hasOption(NcCSVExtract.END_ROW));
158     }
159 
160     /**
161      * Test that the command's toString(0 displays the command's command name.
162      */
163     public final void testGetUsage()
164     {
165         assertTrue("The command does not display any usage information.", !extractCommand.getUsageString().isEmpty());
166     }
167 
168     /**
169      * Test running extract given a non-existent file name.
170      */
171     public final void testNonExistentInputFile()
172     {
173         String inputFileName = "C:\\abcdefghijklmnopqrstuvwxyz.csv";
174 
175         // make sure this file does not exist!
176         File file = new File(inputFileName);
177         assertFalse("This unit test can not be run if the following file exists: " + inputFileName, file.exists());
178 
179         String[] args = new String[] {extractCommand.getCommandName(), 
180                 "-"+NcCSVExtract.INPUT_FILE, inputFileName/*this file is known not exist*/, 
181                 "-"+NcCSVExtract.COLUMN_INDEX, "0" /*we could have specified any column index, since we expect this to fail*/};
182 
183         String errors = extractCommand.validCommand(args);
184         assertTrue("A non-existent file should return an error", !errors.isEmpty());
185     }
186     
187     /**
188      * Test running extract given a file with the wrong file extension.
189      */
190     public final void testInvalidInputFileExtension()
191     {
192         File file = new File("."); // this file has to exist
193         assertTrue("This unit test can not be run if the following file does not exist: .", file.exists());
194 
195         String[] args = new String[] {extractCommand.getCommandName(), 
196                 "-"+NcCSVExtract.INPUT_FILE, file.getPath() /*this file is known not exist*/, 
197                 "-"+NcCSVExtract.COLUMN_INDEX, "0" /*we could have specified any column index, since we expect this to fail*/};
198 
199         String errors = extractCommand.validCommand(args);
200         assertTrue("A file without a *.csv file extension should return an error", !errors.isEmpty());
201     }
202     
203     /**
204      * Test running extract given an invalid column index.
205      */
206     public final void testInvalidColumnIndex()
207     {
208         String[] args = new String[] {extractCommand.getCommandName(), 
209                 "-"+NcCSVExtract.INPUT_FILE, this.dummyCSVFilename/*this file is know to be a valid csv file*/, 
210                 "-"+NcCSVExtract.COLUMN_INDEX, this.invalidColumnIndex/*this is known to be a invalid column index*/}; 
211 
212         String errors = extractCommand.validCommand(args);
213         assertTrue("Valid arguments should not return an error", errors.isEmpty());
214         
215         try
216         {
217             extractCommand.execute(args);
218             fail("Referencing an invalid column index in a file should throw an exception.");
219         }
220         catch(ParseException pe)
221         {
222             // do nothing since the exception should be thrown
223             pe.printStackTrace();
224         }
225         catch(IOException ioe)
226         {
227             ioe.printStackTrace();
228             fail(ioe.getMessage());
229         }
230     }
231     
232     /**
233      * Test running extract given an invalid column index argument value.
234      */
235     public final void testInvalidColumnIndexArgValue()
236     {
237         String[] args = new String[] {extractCommand.getCommandName(), 
238                 "-"+NcCSVExtract.INPUT_FILE, this.dummyCSVFilename/*this file is know to be a valid csv file*/, 
239                 "-"+NcCSVExtract.COLUMN_INDEX, "ABCDEFG"/*columnIndex value should be numeric*/}; 
240 
241         String errors = extractCommand.validCommand(args);
242         assertTrue("Non-numeric columnIndex values should return an error", !errors.isEmpty());
243     }
244     
245     /**
246      * Test running extract given a valid column index.
247      */
248     public final void testValidColumnIndex()
249     {
250         String[] args = new String[] {extractCommand.getCommandName(), 
251                 "-"+NcCSVExtract.INPUT_FILE, this.dummyCSVFilename/*this file is know to be a valid csv file*/, 
252                 "-"+NcCSVExtract.COLUMN_INDEX, this.validColumnIndex/*this is known to be a invalid column index*/}; 
253 
254         String errors = extractCommand.validCommand(args);
255         assertTrue("Valid arguments should not return an error", errors.isEmpty());
256         
257         try
258         {
259             extractCommand.execute(args);
260             assertEquals(this.validValuesCol0Row0Row1Row2, outContent.toString());
261         }
262         catch(ParseException pe)
263         {
264             pe.printStackTrace();
265             fail(pe.getMessage());
266         }
267         catch(IOException ioe)
268         {
269             ioe.printStackTrace();
270             fail(ioe.getMessage());
271         }
272     }
273     
274     /**
275      * Test running extract given an valid row index range.
276      */
277     public final void testValidRowIndexRange()
278     {
279         String[] args = new String[] {extractCommand.getCommandName(), 
280                 "-"+NcCSVExtract.INPUT_FILE, this.dummyCSVFilename/*this file is know to be a valid csv file*/, 
281                 "-"+NcCSVExtract.COLUMN_INDEX, this.validColumnIndex/*this is known to be a valid column index*/, 
282                 "-"+NcCSVExtract.START_ROW, this.validStartRowIndex/*this is known to be a invalid row index*/,
283                 "-"+NcCSVExtract.END_ROW, this.validEndRowIndex/*this is known to be a invalid row index*/};
284 
285         String errors = extractCommand.validCommand(args);
286         assertTrue("Valid arguments should not return an error", errors.isEmpty());
287         
288         try
289         {
290             extractCommand.execute(args);
291             assertEquals(this.validValuesCol0Row1Row2, outContent.toString());
292         }
293         catch(ParseException pe)
294         {
295             pe.printStackTrace();
296             fail(pe.getMessage());
297         }
298         catch(IOException ioe)
299         {
300             ioe.printStackTrace();
301             fail(ioe.getMessage());
302         }
303     }
304     
305     /**
306      * Test running extract given an invalid row index range.
307      */
308     public final void testInvalidRowIndexRange()
309     {
310         String[] args = new String[] {extractCommand.getCommandName(), 
311                 "-"+NcCSVExtract.INPUT_FILE, this.dummyCSVFilename/*this file is know to be a valid csv file*/, 
312                 "-"+NcCSVExtract.COLUMN_INDEX, this.validColumnIndex/*this is known to be a valid column index*/, 
313                 "-"+NcCSVExtract.START_ROW, this.validStartRowIndex/*this is known to be a invalid row index*/,
314                 "-"+NcCSVExtract.END_ROW, this.invalidEndRowIndex/*this is known to be a invalid row index*/};
315 
316         String errors = extractCommand.validCommand(args);
317         assertTrue("Valid arguments should not return an error", errors.isEmpty());
318         
319         try
320         {
321             extractCommand.execute(args);
322             assertEquals(this.validValuesCol0Row1Row2, outContent.toString());
323         }
324         catch(ParseException pe)
325         {
326             pe.printStackTrace();
327             fail(pe.getMessage());
328         }
329         catch(IOException ioe)
330         {
331             ioe.printStackTrace();
332             fail(ioe.getMessage());
333         }
334     }
335     
336     /**
337      * Test running extract given an invalid start row argument value.
338      */
339     public final void testInvalidStartRowIndexArgValue()
340     {
341         String[] args = new String[] {extractCommand.getCommandName(), 
342                 "-"+NcCSVExtract.INPUT_FILE, this.dummyCSVFilename/*this file is know to be a valid csv file*/, 
343                 "-"+NcCSVExtract.COLUMN_INDEX, this.validColumnIndex/*this is known to be a valid column index*/, 
344                 "-"+NcCSVExtract.START_ROW, "ABCDEFG"/*startRow index value should be numeric*/};
345 
346         String errors = extractCommand.validCommand(args);
347         assertTrue("Non-numeric startRow index value should return an error", !errors.isEmpty());
348     }
349     
350     /**
351      * Test running extract given an invalid end row argument value.
352      */
353     public final void testInvalidEndRowIndexArgValue()
354     {
355         String[] args = new String[] {extractCommand.getCommandName(), 
356                 "-"+NcCSVExtract.INPUT_FILE, this.dummyCSVFilename/*this file is know to be a valid csv file*/, 
357                 "-"+NcCSVExtract.COLUMN_INDEX, this.validColumnIndex/*this is known to be a valid column index*/, 
358                 "-"+NcCSVExtract.START_ROW, "0"/*startRow index value is numeric*/,
359                 "-"+NcCSVExtract.END_ROW, "ABCDEFG"/*startRow index value should be numeric*/ };
360 
361         String errors = extractCommand.validCommand(args);
362         assertTrue("Non-numeric startRow index value should return an error", !errors.isEmpty());
363     }
364     
365     /**
366      * Makes a dummy csv file with known contents.
367      */
368     private void createDummyCSVFile()
369     {
370         try
371         {
372             // Create file
373             FileWriter fstream = new FileWriter(this.dummyCSVFilename);
374             BufferedWriter out = new BufferedWriter(fstream);
375             for(int i=0; i<this.dummyCSVFileContents.length; i++)
376             {
377                 out.write(this.dummyCSVFileContents[i]);   
378             }
379             // Close the output stream
380             out.close();
381         }
382         catch (Exception e)
383         {
384             // Catch exception if any
385             e.printStackTrace();
386             fail("Failed trying to create a dummy csv file for testing the extract command.");
387         }
388     }
389 }