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  package au.csiro.netcdf;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.ByteArrayOutputStream;
21  import java.io.File;
22  import java.io.IOException;
23  import java.io.PrintStream;
24  import java.util.ArrayList;
25  import java.util.Arrays;
26  import java.util.List;
27  
28  import junit.framework.TestCase;
29  
30  import org.apache.commons.cli.Options;
31  
32  import ucar.ma2.DataType;
33  import ucar.nc2.Attribute;
34  import ucar.nc2.Dimension;
35  import ucar.nc2.NetcdfFile;
36  import ucar.nc2.NetcdfFileWriteable;
37  import ucar.nc2.Variable;
38  import au.csiro.netcdf.cli.Command;
39  import au.csiro.netcdf.util.NetCDFUtils;
40  
41  /**
42   * This class is a unit test suite to verify that the NcDefineAttributes command operates correctly.
43   * <p>
44   * Copyright 2010, CSIRO Australia
45   * 
46   * @author James Dempsey on 23/03/2010
47   * @version $Revision: 78 $ $Date: 2010-07-24 16:23:13 +1000 (Sat, 24 Jul 2010) $
48   */
49  public class TestNcDefineAttributes extends TestCase
50  {
51      /**
52       * Used to capture standard output
53       */
54      private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
55  
56      /**
57       * The name of the command line option used for specifying the output netCDF file name.
58       */
59      private static final String OUTPUT_FILE = "outputFileName";
60      
61      /**
62       * The name of the command line option used for specifying the global attributes of a netCDF file.
63       */
64      private static final String ATTRIBUTES = "attributes";
65      
66      /**
67       * The name of the command line option used for specifying the name of the variable.
68       */
69      private static final String VARIABLE_NAME = "variable";
70      
71      /** Data for the variable  */
72      private static final String VARIABLE_NAME_VALUE = "myVar";
73      
74      /**
75       * The testing value for the dimension option.
76       */
77      private static final String DIM_NAME = "myDimension";
78  
79      /**
80       * The name of the netCDF file to write to.
81       */
82      private static final String NC_FILE_NAME = System.getProperty("user.dir") + "\\ABC.nc";
83  
84      /** Name of the first Attribute */
85      private static final String ATTR1_NAME = "Attr1";
86  
87      /** Data for the first Attribute */
88      private static final String ATTR1_DATA = "This only a test attribute.";
89  
90      /** Name of the second Attribute */
91      private static final String ATTR2_NAME = "Project";
92  
93      /** Data for the second Attribute */
94      private static final String ATTR2_DATA = "Murray Darling Basin Sustainable Yields (MDBSY)";
95  
96      /** Name of the third, float, Attribute */
97      private static final String ATTR3_NAME = "Float Val";
98  
99      /** Data for the third, float, Attribute */
100     private static final String ATTR3_DATA = "17.5f";
101     
102     /** Name for history Attribute */
103     private static final String ATTR_HISTORY = "history";
104     
105     /** Value for history Attribute */
106     private static final String ATTR_HISTORY_VALUE = "LAST UPDATED: 2010-03-23 05:02:18 UTC\n";
107 
108     /** Name for author Attribute */
109     private static final String ATTR_AUTHOR = "author";
110     
111     /** Value for author Attribute */
112     private static final String ATTR_AUTHOR_VALUE = "John Citizen";
113 
114     /** List of attribute values likely to be found in a netCDF file */
115     private static final String INPUT_ATTRIBUTE_STRING = ATTR_HISTORY + "=" +
116         "BUREAU OF METEOROLOGY \n"  +
117         "[HEADER] \n" +
118         "RAINFALL ANALYSIS: 2007010120070101 \n" +
119         "LENGTH SCALE FOR ANALYSIS 80.0 \n" +
120         "LATITUDE - LONGITUDE GRID \n" +
121         "ROW NUMBER AT SOUTHWEST CORNER 691 \n" +
122         "COLUMN NUMBER AT SOUTHWEST CORNER 1 \n" +
123         "ROW CHANGES WITH LONGITUDE \n" +
124         "NUMBER OF LONGITUDES IN GRID 886 \n" +
125         "NUMBER OF LATITUDES IN GRID 691 \n" +
126         "SOUTHWEST LONGITUDE 112.000 \n" +
127         "SOUTHWEST LATITUDE 44.500 \n" +
128         "GRID INCREMENT OF LONGITUDE 0.050 \n" +
129         "GRID INCREMENT OF LATITUDE 0.050 \n" +
130         "NUMBER OF STATIONS REPORTING 6461 \n" +
131         "MEAN DIFF ANAL/OBSERVATION: 0.0 RMDIF: 0.0 \n" +
132         "[ANALYSIS ARRAY] \n" +
133         ATTR_HISTORY_VALUE +
134         "" + 
135         "," + 
136         "" +
137         ATTR_AUTHOR + "=" +
138         ATTR_AUTHOR_VALUE;
139     
140     /** Complex list of attribute values including special characters */
141     private static final String SPECIAL_CHAR_INPUT_ATTRIBUTE_STRING = ATTR_HISTORY + "=" +
142         " 01234567890 "  +
143         " +\\=-~!@#$%^&*() " +
144         " []{}|" +
145         " ;': " +
146         " \\,./<>? " +
147         ATTR_HISTORY_VALUE +
148         "," + 
149         "" +
150         ATTR_AUTHOR + "=" +
151         ATTR_AUTHOR_VALUE;
152     
153     /**
154      * An instance of the NcDefineAttributes command that we want to test.
155      */
156     private Command ncDefineAttr = new NcDefineAttributes();
157 
158     /*
159      * (non-Javadoc)
160      * 
161      * @see junit.framework.TestCase#setUp()
162      */
163     @Override
164     protected void setUp() throws Exception
165     {
166         super.setUp();
167 
168         // write standard output to a stream we can examine.
169         System.setOut(new PrintStream(outContent));
170     }
171 
172     /*
173      * (non-Javadoc)
174      * 
175      * @see junit.framework.TestCase#tearDown()
176      */
177     @Override
178     protected void tearDown() throws Exception
179     {
180         super.tearDown();
181 
182         System.setOut(null);
183     }
184 
185     /**
186      * Test that the commands options are used.
187      */
188     public final void testCreateOptions()
189     {
190         Options options = ncDefineAttr.createOptions();
191 
192         assertTrue("The following option is not recognised by the command: " + OUTPUT_FILE, 
193                 options.hasOption(OUTPUT_FILE));
194         assertTrue("The following option is not recognised by the command: " + ATTRIBUTES, 
195                 options.hasOption(ATTRIBUTES));
196 
197     }
198 
199     /**
200      * Test a valid command creates a netCDF file with the specified Dimension name and size
201      */
202     public final void testExecuteNoAttr()
203     {
204         String[] args = new String[] { ncDefineAttr.getCommandName(), 
205                 "-" + OUTPUT_FILE, NC_FILE_NAME };
206 
207         try
208         {
209             File ncFile = new File(NC_FILE_NAME);
210             if (ncFile.exists())
211             {
212                 ncFile.delete();
213             }
214 
215             ncDefineAttr.execute(args);
216             assertTrue("The nc file was not created: " + NC_FILE_NAME, ncFile.exists());
217 
218             NetcdfFile netcdfFile = NetcdfFile.open(NC_FILE_NAME);
219             Attribute attr = netcdfFile.findGlobalAttribute(ATTR1_NAME);
220             assertNull("The Attribute was defined: " + ATTR1_NAME, attr);
221 
222             netcdfFile.close();
223             ncFile.delete();
224         }
225         catch (Exception e)
226         {
227             e.printStackTrace();
228             fail(e.getMessage());
229         }
230     }
231 
232     /**
233      * Test a valid command creates a netCDF file with the specified Dimension name and size
234      */
235     public final void testExecuteExistingFile()
236     {
237         String[] args = new String[] { ncDefineAttr.getCommandName(), 
238                 "-" + OUTPUT_FILE, NC_FILE_NAME,
239                 "-" + ATTRIBUTES, ATTR1_NAME+"="+ATTR1_DATA };
240 
241         try
242         {
243             File ncFile = new File(NC_FILE_NAME);
244             if (ncFile.exists())
245             {
246                 ncFile.delete();
247             }
248 
249             ncDefineAttr.execute(args);
250             assertTrue("The nc file was not created: " + NC_FILE_NAME, ncFile.exists());
251 
252             NetcdfFile netcdfFile = NetcdfFile.open(NC_FILE_NAME);
253             Attribute attr = netcdfFile.findGlobalAttribute(ATTR1_NAME);
254             assertNotNull("The Attribute was not defined: " + ATTR1_NAME, attr);
255             assertEquals("The Attrbute had the wrong data: " + ATTR1_NAME,
256                     ATTR1_DATA, attr.getStringValue());
257 
258             netcdfFile.close();
259             
260             // Now run a second time on the same file
261             args[4] = ATTR2_NAME+"="+ATTR2_DATA;
262             ncDefineAttr.execute(args);
263             assertTrue("The nc file was not created: " + NC_FILE_NAME, ncFile.exists());
264             
265             netcdfFile = NetcdfFile.open(NC_FILE_NAME);
266             attr = netcdfFile.findGlobalAttribute(ATTR1_NAME);
267             assertNotNull("The Attribute was lost: " + ATTR1_NAME, attr);
268             assertEquals("The Attrbute had the wrong data: " + ATTR1_NAME,
269                     ATTR1_DATA, attr.getStringValue());
270             attr = netcdfFile.findGlobalAttribute(ATTR2_NAME);
271             assertNotNull("The Attribute was not defined: " + ATTR2_NAME, attr);
272             assertEquals("The Attrbute had the wrong data: " + ATTR2_NAME,
273                     ATTR2_DATA, attr.getStringValue());
274 
275             netcdfFile.close();
276             ncFile.delete();
277         }
278         catch (Exception e)
279         {
280             e.printStackTrace();
281             fail(e.getMessage());
282         }
283     }
284 
285     /**
286      * Test a valid command creates a netCDF file with the specified Dimension name and size
287      */
288     public final void testExecuteValidMultiAttr()
289     {
290         String[] args = new String[] { ncDefineAttr.getCommandName(), 
291                 "-" + OUTPUT_FILE, NC_FILE_NAME,
292                 "-" + ATTRIBUTES, ATTR1_NAME + "=" + ATTR1_DATA + "," + ATTR2_NAME + "=" + ATTR2_DATA };
293 
294         try
295         {
296             File ncFile = new File(NC_FILE_NAME);
297             if (ncFile.exists())
298             {
299                 ncFile.delete();
300             }
301 
302             ncDefineAttr.execute(args);
303             assertTrue("The nc file was not created: " + NC_FILE_NAME, ncFile.exists());
304 
305             NetcdfFile netcdfFile = NetcdfFile.open(NC_FILE_NAME);
306             Attribute attr = netcdfFile.findGlobalAttribute(ATTR1_NAME);
307             assertTrue("The Attribute was not defined: " + ATTR1_NAME, (attr != null));
308             assertEquals("The Attrbute had the wrong data: " + ATTR1_NAME,
309                     ATTR1_DATA, attr.getStringValue());
310 
311             attr = netcdfFile.findGlobalAttribute(ATTR2_NAME);
312             assertNotNull("The Attribute was not defined: " + ATTR2_NAME, attr);
313             assertEquals("The Attrbute had the wrong data: " + ATTR2_NAME,
314                     ATTR2_DATA, attr.getStringValue());
315             
316             netcdfFile.close();
317             ncFile.delete();
318         }
319         catch (Exception e)
320         {
321             e.printStackTrace();
322             fail(e.getMessage());
323         }
324     }
325 
326     /**
327      * Test a valid command creates a netCDF file with a float attribute
328      * @throws Exception If there is an error running the test
329      */
330     public final void testExecuteValidFloatAttr() throws Exception
331     {
332         String[] args = new String[] { ncDefineAttr.getCommandName(), 
333                 "-" + OUTPUT_FILE, NC_FILE_NAME,
334                 "-" + ATTRIBUTES, ATTR3_NAME + "=" + ATTR3_DATA,
335                 "-t", "float"};
336 
337         File ncFile = new File(NC_FILE_NAME);
338         if (ncFile.exists())
339         {
340             ncFile.delete();
341         }
342 
343         ncDefineAttr.execute(args);
344         assertTrue("The nc file was not created: " + NC_FILE_NAME, ncFile.exists());
345 
346         NetcdfFile netcdfFile = NetcdfFile.open(NC_FILE_NAME);
347         Attribute attr = netcdfFile.findGlobalAttribute(ATTR3_NAME);
348         assertTrue("The Attribute was not defined: " + ATTR3_NAME, (attr != null));
349         assertEquals("The Attrbute " + ATTR3_NAME + " had a string value. ",
350                 null, attr.getStringValue());
351         assertEquals("The Attrbute had the wrong data: " + ATTR3_NAME,
352                 Float.parseFloat(ATTR3_DATA), (Float)attr.getNumericValue(), 0.01f);
353         
354         netcdfFile.close();
355         ncFile.delete();
356     }
357 
358     /**
359      * Test a valid command creates a netCDF file with a short attribute
360      * @throws Exception If there is an error running the test
361      */
362     public final void testExecuteValidShortAttr() throws Exception
363     {
364         final String shortAttrName = "Short";
365         String[] args = new String[] { ncDefineAttr.getCommandName(), 
366                 "-" + OUTPUT_FILE, NC_FILE_NAME,
367                 "-" + ATTRIBUTES, shortAttrName + "=57",
368                 "-t", "short"};
369 
370         File ncFile = new File(NC_FILE_NAME);
371         if (ncFile.exists())
372         {
373             ncFile.delete();
374         }
375 
376         ncDefineAttr.execute(args);
377         assertTrue("The nc file was not created: " + NC_FILE_NAME, ncFile.exists());
378 
379         NetcdfFile netcdfFile = NetcdfFile.open(NC_FILE_NAME);
380         Attribute attr = netcdfFile.findGlobalAttribute(shortAttrName);
381         assertTrue("The Attribute was not defined: " + shortAttrName, (attr != null));
382         assertEquals("The Attrbute " + shortAttrName + " had a string value. ",
383                 null, attr.getStringValue());
384         assertEquals("The Attrbute had the wrong data: " + shortAttrName,
385                 (short) 57, (Short)attr.getNumericValue(), 0);
386         
387         netcdfFile.close();
388         ncFile.delete();
389     }
390 
391     /**
392      * Test a valid command creates a netCDF file with an integer attribute
393      * @throws Exception If there is an error running the test
394      */
395     public final void testExecuteValidIntAttr() throws Exception
396     {
397         final String intAttrName = "Integer";
398         final int intAttrValue = 67991082;
399         String[] args = new String[] { ncDefineAttr.getCommandName(), 
400                 "-" + OUTPUT_FILE, NC_FILE_NAME,
401                 "-" + ATTRIBUTES, intAttrName + "=" + String.valueOf(intAttrValue),
402                 "-t", "int"};
403 
404         File ncFile = new File(NC_FILE_NAME);
405         if (ncFile.exists())
406         {
407             ncFile.delete();
408         }
409 
410         ncDefineAttr.execute(args);
411         assertTrue("The nc file was not created: " + NC_FILE_NAME, ncFile.exists());
412 
413         NetcdfFile netcdfFile = NetcdfFile.open(NC_FILE_NAME);
414         Attribute attr = netcdfFile.findGlobalAttribute(intAttrName);
415         assertTrue("The Attribute was not defined: " + intAttrName, (attr != null));
416         assertEquals("The Attrbute " + intAttrName + " had a string value. ",
417                 null, attr.getStringValue());
418         assertEquals("The Attrbute had the wrong data: " + intAttrName,
419                 intAttrValue, (Integer)attr.getNumericValue(), 0);
420         
421         netcdfFile.close();
422         ncFile.delete();
423     }
424 
425     /**
426      * Test a valid command creates a netCDF file with an integer attribute
427      * @throws Exception If there is an error running the test
428      */
429     public final void testExecuteInvalidType() throws Exception
430     {
431         final String intAttrName = "Integer";
432         final int intAttrValue = 67991082;
433         String[] args = new String[] { ncDefineAttr.getCommandName(), 
434                 "-" + OUTPUT_FILE, NC_FILE_NAME,
435                 "-" + ATTRIBUTES, intAttrName + "=" + String.valueOf(intAttrValue),
436                 "-t", "integer"};
437 
438         File ncFile = new File(NC_FILE_NAME);
439         if (ncFile.exists())
440         {
441             ncFile.delete();
442         }
443 
444         try
445         {
446             ncDefineAttr.execute(args);
447             ncFile.delete();
448             fail("Type of integer should have been rejected.");
449         }
450         catch (IllegalArgumentException e)
451         {
452             // We can only test the start of the message as the supported types is a set and thus the order is not deterministic
453             assertTrue("Incorrect error message", e.getMessage().startsWith("variableDataType value is not a valid data type: integer. "
454                     + "Allowed data types are: ["));
455         }
456 
457     }
458 
459 
460     /**
461      * Test that required options are reported if missing 
462      */
463     public final void testMissingRequiredOption()
464     {
465         String[] args = new String[] { ncDefineAttr.getCommandName(), 
466                 "-" + ATTRIBUTES, ATTR1_NAME+"="+ATTR1_DATA };
467 
468         String errors = ncDefineAttr.validCommand(args);
469         assertTrue("Command without output file option should return an error", !errors.isEmpty());
470         assertEquals("Error string was not correct", "\nMissing required option: o", errors);
471     }
472 
473     /**
474      * Test that an invalid attribute is rejected
475      */
476     public final void testInvalidAttr()
477     {
478         String[] args = new String[] { ncDefineAttr.getCommandName(), 
479                 "-" + OUTPUT_FILE, NC_FILE_NAME,
480                 "-" + ATTRIBUTES, ATTR1_NAME};
481 
482         String errors = ncDefineAttr.validCommand(args);
483         assertTrue("Command with invalid attribute string should return an error", !errors.isEmpty());
484         assertEquals("Error string was not correct",
485                 "\nattributes value is not a comma separated String of attribute-value pairs: Attr1", errors);
486     }
487 
488     /**
489      * Test that a missing optional attribute is accepted
490      */
491     public final void testMissingAttr()
492     {
493         String[] args = new String[] { ncDefineAttr.getCommandName(), 
494                 "-" + OUTPUT_FILE, NC_FILE_NAME};
495 
496         String errors = ncDefineAttr.validCommand(args);
497         assertEquals("Command with missing " + ATTRIBUTES + " attribute should not return an error", "", errors);
498     }
499 
500     /**
501      * Test the command's usage string
502      */
503     public final void testGetUsage()
504     {
505         String usage = ncDefineAttr.getUsageString(); 
506         assertTrue("The command does not display any usage information.", 
507                 !usage.isEmpty());
508         assertTrue("The usage information does not contain the command name.", 
509                 usage.contains(ncDefineAttr.getCommandName()));
510     }
511     
512     /**
513      * Test setting global attribute via standard input
514      * 
515      * @throws IOException
516      */
517     public final void testStandardInputAttribute() throws IOException
518     {
519         File ncFile = null;
520         NetcdfFile netcdfFile = null;
521         try
522         {
523             ncFile = new File(NC_FILE_NAME);
524             if (ncFile.exists())
525             {
526                 ncFile.delete();
527             }
528 
529             List<Attribute> attributes = new ArrayList<Attribute>(Arrays.asList(new Attribute(ATTR1_NAME, ATTR1_DATA)));
530             attributes.addAll(NetCDFUtils.readAttributesFromStream(new ByteArrayInputStream(INPUT_ATTRIBUTE_STRING
531                     .getBytes("UTF-8"))));
532             
533             ((NcDefineAttributes) ncDefineAttr).execute(NC_FILE_NAME, attributes, true /* isLargeFileSupport */);
534 
535             assertTrue("The nc file was not created: " + NC_FILE_NAME, ncFile.exists());
536 
537             netcdfFile = NetcdfFile.open(NC_FILE_NAME);
538             Attribute attr = netcdfFile.findGlobalAttribute(ATTR1_NAME);
539             assertTrue("The Attribute was not defined: " + ATTR1_NAME, (attr != null));
540             assertEquals("The Attrbute had the wrong data: " + ATTR1_NAME, ATTR1_DATA, attr.getStringValue());
541 
542             attr = netcdfFile.findGlobalAttribute(ATTR_HISTORY);
543             assertTrue("The Attribute was not defined: " + ATTR_HISTORY, (attr != null));
544             assertTrue("The Attrbute had the wrong data: " + ATTR_HISTORY, attr.getStringValue().contains(
545                     "NUMBER OF STATIONS REPORTING 6461 \n"));
546 
547             attr = netcdfFile.findGlobalAttribute(ATTR_AUTHOR);
548             assertTrue("The Attribute was not defined: " + ATTR_AUTHOR, (attr != null));
549             assertTrue("The Attrbute had the wrong data: " + ATTR_AUTHOR, attr.getStringValue()
550                     .contains(ATTR_AUTHOR_VALUE));
551         }
552         catch (Exception e)
553         {
554             e.printStackTrace();
555             fail(e.getMessage());
556         }
557         finally
558         {
559             if(netcdfFile != null && ncFile != null)
560             {
561                 netcdfFile.close();
562                 ncFile.delete();
563             }
564         }
565     }
566     
567     /**
568      * Test setting a complex global attribute via standard input
569      * 
570      * @throws IOException
571      */
572     public final void testStandardInputComplexAttribute() throws IOException
573     {
574         File ncFile = null;
575         NetcdfFile netcdfFile = null;
576         try
577         {
578             ncFile = new File(NC_FILE_NAME);
579             if (ncFile.exists())
580             {
581                 ncFile.delete();
582             }
583 
584             List<Attribute> attributes = NetCDFUtils.readAttributesFromStream(new ByteArrayInputStream(
585                     SPECIAL_CHAR_INPUT_ATTRIBUTE_STRING.getBytes("UTF-8")));
586             
587             ((NcDefineAttributes) ncDefineAttr).execute(NC_FILE_NAME, attributes /*
588                                                                                   * no attributes specified on command
589                                                                                   * line
590                                                                                   */, true /* isLargeFileSupport */);
591 
592             assertTrue("The nc file was not created: " + NC_FILE_NAME, ncFile.exists());
593 
594             netcdfFile = NetcdfFile.open(NC_FILE_NAME);
595             Attribute attr = netcdfFile.findGlobalAttribute(ATTR_HISTORY);
596             assertTrue("The Attribute was not defined: " + ATTR_HISTORY, (attr != null));
597             assertTrue("The Attrbute had the wrong data: " + ATTR_HISTORY, attr.getStringValue().contains(
598                     ATTR_HISTORY_VALUE));
599 
600             attr = netcdfFile.findGlobalAttribute(ATTR_AUTHOR);
601             assertTrue("The Attribute was not defined: " + ATTR_AUTHOR, (attr != null));
602             assertTrue("The Attrbute had the wrong data: " + ATTR_AUTHOR, attr.getStringValue()
603                     .contains(ATTR_AUTHOR_VALUE));
604 
605         }
606         catch (Exception e)
607         {
608             e.printStackTrace();
609             fail(e.getMessage());
610         }
611         finally
612         {
613             if(netcdfFile != null && ncFile != null)
614             {
615                 netcdfFile.close();
616                 ncFile.delete();
617             }
618         }
619     }
620     
621     /**
622      * Test delete a global attribute
623      * @throws Exception
624      */
625     public final void testDeleteGlobalAttribute() throws Exception
626     {
627         String[] args = new String[] { ncDefineAttr.getCommandName(), 
628                 "-" + OUTPUT_FILE, NC_FILE_NAME,
629                 "-" + ATTRIBUTES, ATTR3_NAME + "=" + ATTR3_DATA,
630                 "-t", "float"};
631         NetcdfFile netcdfFile = null;
632         File ncFile = null;
633 
634         try
635         {
636             ncFile = new File(NC_FILE_NAME);
637             if (ncFile.exists())
638             {
639                 ncFile.delete();
640             }
641     
642             ncDefineAttr.execute(args);
643             assertTrue("The nc file was not created: " + NC_FILE_NAME, ncFile.exists());
644     
645             netcdfFile = NetcdfFile.open(NC_FILE_NAME);
646             Attribute attr = netcdfFile.findGlobalAttribute(ATTR3_NAME);
647             assertTrue("The Attribute was not defined: " + ATTR3_NAME, (attr != null));
648             assertEquals("The Attrbute " + ATTR3_NAME + " had a string value. ",
649                     null, attr.getStringValue());
650             assertEquals("The Attrbute had the wrong data: " + ATTR3_NAME,
651                     Float.parseFloat(ATTR3_DATA), (Float)attr.getNumericValue(), 0.01f);
652             
653             netcdfFile.close();
654             
655             // now delete the attribute
656             args[4] = ATTR3_NAME+"="+"null";
657             ncDefineAttr.execute(args);  
658             netcdfFile = NetcdfFile.open(NC_FILE_NAME);
659             
660             attr = netcdfFile.findGlobalAttribute(ATTR3_NAME);
661             assertTrue("The Attribute was not deleted: " + ATTR3_NAME, (attr == null));
662         }
663         finally
664         {
665             if(netcdfFile != null && ncFile != null)
666             {
667                 netcdfFile.close();
668                 ncFile.delete();
669             }
670         }
671     }
672     
673     /**
674      * Test delete a variable attribute
675      * @throws IOException
676      */
677     public final void testDeleteVariableAttribute() throws IOException
678     {
679         String[] args = new String[] { ncDefineAttr.getCommandName(), 
680                 "-" + OUTPUT_FILE, NC_FILE_NAME,
681                 "-" + ATTRIBUTES, 
682                 ATTR1_NAME+"="+ATTR1_DATA,
683                 "-"+VARIABLE_NAME,
684                 VARIABLE_NAME_VALUE};
685         NetcdfFile netcdfFile = null;
686         File ncFile = null;
687         
688         try
689         {
690             ncFile = new File(NC_FILE_NAME);
691             if (ncFile.exists())
692             {
693                 ncFile.delete();
694             }
695 
696             // create dummy netCDF file with content.
697             createDummyNCFile(NC_FILE_NAME, DataType.CHAR);
698             assertTrue("The nc file was not created: " + NC_FILE_NAME, ncFile.exists());
699             
700             ncDefineAttr.execute(args);          
701             netcdfFile = NetcdfFile.open(NC_FILE_NAME);
702             
703             Variable variable = netcdfFile.findVariable(VARIABLE_NAME_VALUE);
704             assertTrue("The Variable was not defined: " + VARIABLE_NAME_VALUE, (variable != null));
705             
706             Attribute attr = variable.findAttribute(ATTR1_NAME);
707             assertTrue("The Attribute was not defined: " + ATTR1_NAME, (attr != null));
708             assertTrue("The Attrbute had the wrong data: " + ATTR1_NAME, attr.getStringValue().contains(
709                     ATTR1_DATA));
710 
711             netcdfFile.close();
712             
713             // now delete the attribute
714             args[4] = ATTR1_NAME+"="+"null";
715             ncDefineAttr.execute(args);  
716             netcdfFile = NetcdfFile.open(NC_FILE_NAME);
717             variable = netcdfFile.findVariable(VARIABLE_NAME_VALUE);
718             assertTrue("The Variable was not defined: " + VARIABLE_NAME_VALUE, (variable != null));
719             
720             attr = variable.findAttribute(ATTR1_NAME);
721             assertTrue("The Attribute was not deleted: " + ATTR1_NAME, (attr == null));
722 
723         }catch (Exception e)
724         {
725             e.printStackTrace();
726             fail(e.getMessage());
727         }
728         finally
729         {
730             if(netcdfFile != null && ncFile != null)
731             {
732                 netcdfFile.close();
733                 ncFile.delete();
734             }
735         }
736     }
737     
738     /**
739      * Test adding attributes to an existing variable
740      * 
741      * @throws IOException
742      */
743     public final void testVariableAttribute() throws IOException
744     {
745         String[] args = new String[] { ncDefineAttr.getCommandName(), 
746                 "-" + OUTPUT_FILE, NC_FILE_NAME,
747                 "-" + ATTRIBUTES, 
748                 ATTR1_NAME+"="+ATTR1_DATA,
749                 "-"+VARIABLE_NAME,
750                 VARIABLE_NAME_VALUE};
751         NetcdfFile netcdfFile = null;
752         File ncFile = null;
753         
754         try
755         {
756             ncFile = new File(NC_FILE_NAME);
757             if (ncFile.exists())
758             {
759                 ncFile.delete();
760             }
761 
762             // create dummy netCDF file with content.
763             createDummyNCFile(NC_FILE_NAME, DataType.CHAR);
764             assertTrue("The nc file was not created: " + NC_FILE_NAME, ncFile.exists());
765             
766             ncDefineAttr.execute(args);          
767             netcdfFile = NetcdfFile.open(NC_FILE_NAME);
768             
769             Variable variable = netcdfFile.findVariable(VARIABLE_NAME_VALUE);
770             assertTrue("The Variable was not defined: " + VARIABLE_NAME_VALUE, (variable != null));
771             
772             Attribute attr = variable.findAttribute(ATTR1_NAME);
773             assertTrue("The Attribute was not defined: " + ATTR1_NAME, (attr != null));
774             assertTrue("The Attrbute had the wrong data: " + ATTR1_NAME, attr.getStringValue().contains(
775                     ATTR1_DATA));
776 
777         }catch (Exception e)
778         {
779             e.printStackTrace();
780             fail(e.getMessage());
781         }
782         finally
783         {
784             if(netcdfFile != null && ncFile != null)
785             {
786                 netcdfFile.close();
787                 ncFile.delete();
788             }
789         }
790     }
791 
792     /**
793      * Test adding attributes to a non-existing variable
794      * 
795      * @throws Exception
796      */
797     public final void testVariableAttributeNoVar() throws Exception
798     {
799         String[] args = new String[] { ncDefineAttr.getCommandName(), 
800                 "-" + OUTPUT_FILE, NC_FILE_NAME };
801         try
802         {
803             File ncFile = new File(NC_FILE_NAME);
804             if (ncFile.exists())
805             {
806                 ncFile.delete();
807             }
808 
809             ncDefineAttr.execute(args);
810             assertTrue("The nc file was not created: " + NC_FILE_NAME, ncFile.exists());
811            
812             // Now run a second time on the same file
813             args = new String[] { ncDefineAttr.getCommandName(), 
814                     "-" + OUTPUT_FILE, NC_FILE_NAME,
815                     ATTR1_NAME+"="+ATTR1_DATA,
816                     "-"+VARIABLE_NAME,
817                     VARIABLE_NAME_VALUE};
818             
819             ncDefineAttr.execute(args);
820             fail("adding attribute to non-existing variable should have failed.");
821 
822         }
823         catch (IllegalArgumentException expected)
824         {
825             // expected exception
826         }
827         catch (Exception e)
828         {            
829             throw e;
830         }
831         finally
832         {
833             File ncFile = new File(NC_FILE_NAME);
834             if (ncFile.exists())
835             {
836                 ncFile.delete();
837             }
838         }
839     }
840     
841     /**
842      * Makes a dummy netCDF file with known contents.
843      */
844     private void createDummyNCFile(String outputFilename, DataType dType) throws IOException
845     {
846         NetcdfFileWriteable ncFile = null;
847 
848         ncFile = NetcdfFileWriteable.createNew(outputFilename, true);
849         try
850         {
851             Dimension dimension = new Dimension(DIM_NAME, 10, true /* isShared */, false /* isUnlimited */, false /* isVariableLength */);
852             ncFile.addDimension(null, dimension);
853             ncFile.addVariable(VARIABLE_NAME_VALUE, dType, DIM_NAME);
854             ncFile.create();
855         }
856         finally
857         {
858             ncFile.close();
859         }
860     }
861 }