1 /*
   2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test
  26  * @bug     8145780
  27  * @author  a.stepanov
  28  * @summary Some checks for TIFFTag, TIFFTagSet
  29  * @run     main TIFFTagSetTest
  30  */
  31 
  32 
  33 import javax.imageio.plugins.tiff.*;
  34 
  35 import java.lang.reflect.Method;
  36 import java.util.*;
  37 
  38 
  39 public class TIFFTagSetTest {
  40 
  41     public static class TestSet extends TIFFTagSet {
  42 
  43         public static final TIFFTagSet SOME_SET =
  44             new TIFFTagSet(new ArrayList<TIFFTag>());
  45 
  46         private static TestSet theInstance = null;
  47 
  48         public static final int TAG_NUM_1  = 0;
  49         public static final int TAG_NUM_2  = 666;
  50         public static final int TAG_NUM_3  = Integer.MAX_VALUE;
  51 
  52         public static final String TAG_NAME_1  = "tag-1";
  53         public static final String TAG_NAME_2  = "tag-2";
  54         public static final String TAG_NAME_3  = "tag-3";
  55 
  56         public static final int VALUE_1 = 123;
  57         public static final int VALUE_2 = 321;
  58 
  59         public static final String VALUE_NAME_1 = "value-1";
  60         public static final String VALUE_NAME_2 = "value-2";
  61 
  62         public static final int VALUE_COUNT = 500;
  63 
  64 
  65         static class Tag1 extends TIFFTag {
  66             public Tag1() {
  67                 super(TAG_NAME_1,
  68                       TAG_NUM_1,
  69                       1 << TIFF_SHORT | 1 << TIFF_LONG,
  70                       VALUE_COUNT);
  71             }
  72         }
  73 
  74         static class Tag2 extends TIFFTag {
  75             public Tag2() {
  76                 super(TAG_NAME_2,
  77                       TAG_NUM_2,
  78                       1 << TIFF_DOUBLE);
  79 
  80                 addValueName(VALUE_1, VALUE_NAME_1);
  81                 addValueName(VALUE_2, VALUE_NAME_2);
  82             }
  83         }
  84 
  85         static class Tag3 extends TIFFTag {
  86             public Tag3() {
  87                 super(TAG_NAME_3,
  88                       TAG_NUM_3,
  89                       SOME_SET);
  90             }
  91         }
  92 
  93         private static List<TIFFTag> tags;
  94 
  95         private static void initTags() {
  96 
  97             tags = new ArrayList<TIFFTag>();
  98 
  99             tags.add(new TestSet.Tag1());
 100             tags.add(new TestSet.Tag2());
 101             tags.add(new TestSet.Tag3());
 102         }
 103 
 104         private TestSet() { super(tags); }
 105 
 106         public synchronized static TestSet getInstance() {
 107 
 108             if (theInstance == null) {
 109                 initTags();
 110                 theInstance = new TestSet();
 111                 tags = null;
 112             }
 113             return theInstance;
 114         }
 115     }
 116 
 117 
 118     private static void checkEq(String what, Object v, Object ref) {
 119         if (v == null) {
 120             throw new RuntimeException(what + " is null");
 121         } else if (!v.equals(ref)) {
 122             throw new RuntimeException("invalid " + what +
 123                 ", expected: " + ref + ", got: " + v);
 124         }
 125     }
 126 
 127 
 128 
 129 
 130     private final String className;
 131     public TIFFTagSetTest(String cName) { className = cName; }
 132 
 133     public void testNamesNumbers() throws ReflectiveOperationException {
 134 
 135         Class<?> c = Class.forName(className);
 136 
 137         Method getInstance = c.getMethod("getInstance", new Class[]{});
 138         Object o = getInstance.invoke(new Object[]{});
 139 
 140         TIFFTagSet tagSet = (TIFFTagSet) o;
 141         SortedSet tagNames   = tagSet.getTagNames();
 142         SortedSet tagNumbers = tagSet.getTagNumbers();
 143 
 144         int nTagNames = tagNames.size();
 145         if (nTagNames != tagNumbers.size()) {
 146             throw new RuntimeException("Error: unequal sizes for tag names set "
 147                     + "and tag numbers set");
 148         }
 149         System.out.println("\n" + nTagNames + " tag names/numbers\n");
 150 
 151         for (final Iterator itName = tagNames.iterator(); itName.hasNext(); ) {
 152 
 153             String tagName = (String) itName.next();
 154             // just in case
 155             if (tagName == null) {
 156                 throw new RuntimeException("null tag name");
 157             }
 158 
 159             TIFFTag tagByName = tagSet.getTag(tagName);
 160             System.out.println(
 161                 "name/number: \t" + tagName + "/" + tagByName.getNumber());
 162             checkEq("tag name", tagByName.getName(), tagName);
 163             TIFFTag tagByNum = tagSet.getTag(tagByName.getNumber());
 164             checkEq("tag name", tagByNum.getName(), tagName);
 165 
 166             if (tagByName.isIFDPointer() &&
 167                !tagByName.isDataTypeOK(TIFFTag.TIFF_IFD_POINTER)) {
 168                 throw new RuntimeException("Error: " + tagName +
 169                     "must be an IFD pointer");
 170             }
 171         }
 172         System.out.println("");
 173 
 174         for (final Iterator itNum = tagNumbers.iterator(); itNum.hasNext(); ) {
 175 
 176             int tagNum = (int) itNum.next();
 177             // just in case
 178             if (tagNum < 0) {
 179                 throw new RuntimeException("negative tag number");
 180             }
 181             TIFFTag tagByNum = tagSet.getTag(tagNum);
 182 
 183             System.out.println(
 184                 "number/name: \t" + tagNum + "/" + tagByNum.getName());
 185             checkEq("tag number", tagByNum.getNumber(), tagNum);
 186             TIFFTag tagByName = tagSet.getTag(tagByNum.getName());
 187             checkEq("tag number", tagByName.getNumber(), tagNum);
 188         }
 189 
 190         System.out.println("");
 191     }
 192 
 193 
 194     private static void testUserDefTagSet() {
 195 
 196         TIFFTagSet set = TestSet.getInstance();
 197 
 198         SortedSet tagNames = set.getTagNames();
 199         checkEq("tagNames set size", tagNames.size(), 3);
 200         if (! (tagNames.contains(TestSet.TAG_NAME_1) &&
 201                tagNames.contains(TestSet.TAG_NAME_2) &&
 202                tagNames.contains(TestSet.TAG_NAME_3)) ) {
 203             throw new RuntimeException("invalid tag names");
 204         }
 205 
 206         SortedSet tagNumbers = set.getTagNumbers();
 207         checkEq("tagNumbers set size", tagNumbers.size(), 3);
 208         if (! (tagNumbers.contains(TestSet.TAG_NUM_1) &&
 209                tagNumbers.contains(TestSet.TAG_NUM_2) &&
 210                tagNumbers.contains(TestSet.TAG_NUM_3)) ) {
 211             throw new RuntimeException("invalid tag numbers");
 212         }
 213 
 214         TIFFTag t1 = set.getTag(TestSet.TAG_NUM_1),
 215                 t2 = set.getTag(TestSet.TAG_NUM_2),
 216                 t3 = set.getTag(TestSet.TAG_NUM_3);
 217 
 218         checkEq(TestSet.TAG_NAME_1 + " name", t1.getName(), TestSet.TAG_NAME_1);
 219         checkEq(TestSet.TAG_NAME_2 + " name", t2.getName(), TestSet.TAG_NAME_2);
 220         checkEq(TestSet.TAG_NAME_3 + " name", t3.getName(), TestSet.TAG_NAME_3);
 221 
 222         // check count
 223         // was set
 224         checkEq(TestSet.TAG_NAME_1 + " count",
 225             t1.getCount(),  TestSet.VALUE_COUNT);
 226         // undefined
 227         checkEq(TestSet.TAG_NAME_2 + " count", t2.getCount(), -1);
 228         // see docs for constructor TIFFTag(String, int, TIFFTagSet)
 229         checkEq(TestSet.TAG_NAME_3 + " count", t3.getCount(),  1);
 230 
 231         // check datatypes
 232         checkEq(TestSet.TAG_NAME_1 + " datatypes", t1.getDataTypes(),
 233             1 << TIFFTag.TIFF_SHORT | 1 << TIFFTag.TIFF_LONG);
 234         boolean ok =  t1.isDataTypeOK(TIFFTag.TIFF_SHORT)  &&
 235                       t1.isDataTypeOK(TIFFTag.TIFF_LONG)   &&
 236                      !t1.isDataTypeOK(TIFFTag.TIFF_DOUBLE) &&
 237                      !t1.isDataTypeOK(TIFFTag.TIFF_IFD_POINTER);
 238         if (!ok) { throw new RuntimeException(TestSet.TAG_NAME_1 + ": " +
 239             "isDataTypeOK check failed"); }
 240         checkEq(TestSet.TAG_NAME_1 + ".isIFDPointer()", t1.isIFDPointer(), false);
 241 
 242         checkEq(TestSet.TAG_NAME_2 + " datatypes", t2.getDataTypes(),
 243             1 << TIFFTag.TIFF_DOUBLE);
 244         ok = !t2.isDataTypeOK(TIFFTag.TIFF_SHORT)  &&
 245              !t2.isDataTypeOK(TIFFTag.TIFF_LONG)   &&
 246               t2.isDataTypeOK(TIFFTag.TIFF_DOUBLE) &&
 247              !t2.isDataTypeOK(TIFFTag.TIFF_IFD_POINTER);
 248         if (!ok) { throw new RuntimeException(TestSet.TAG_NAME_2 + ": " +
 249             "isDataTypeOK check failed"); }
 250         checkEq(TestSet.TAG_NAME_2 + ".isIFDPointer()", t2.isIFDPointer(), false);
 251 
 252         // see docs for constructor TIFFTag(String, int, TIFFTagSet)
 253         checkEq(TestSet.TAG_NAME_3 + " datatypes", t3.getDataTypes(),
 254             1 << TIFFTag.TIFF_LONG | 1 << TIFFTag.TIFF_IFD_POINTER);
 255         ok = !t3.isDataTypeOK(TIFFTag.TIFF_SHORT)  &&
 256               t3.isDataTypeOK(TIFFTag.TIFF_LONG)   &&
 257              !t3.isDataTypeOK(TIFFTag.TIFF_DOUBLE) &&
 258               t3.isDataTypeOK(TIFFTag.TIFF_IFD_POINTER);
 259         if (!ok) { throw new RuntimeException(TestSet.TAG_NAME_3 + ": " +
 260             "isDataTypeOK check failed"); }
 261         checkEq(TestSet.TAG_NAME_3 + ".isIFDPointer()", t3.isIFDPointer(), true);
 262 
 263         // check value names
 264         checkEq(TestSet.TAG_NAME_1 + ".hasValueNames()",
 265             t1.hasValueNames(), false);
 266         checkEq(TestSet.TAG_NAME_2 + ".hasValueNames()",
 267             t2.hasValueNames(), true);
 268         checkEq(TestSet.TAG_NAME_3 + ".hasValueNames()",
 269             t3.hasValueNames(), false);
 270 
 271         if (t1.getNamedValues() != null && t3.getNamedValues() != null) {
 272             throw new RuntimeException(TestSet.TAG_NAME_1 + " and " +
 273                 TestSet.TAG_NAME_3 + " must have null value names arrays");
 274         }
 275 
 276         checkEq("number of " + TestSet.TAG_NAME_2 + " values",
 277             t2.getNamedValues().length, 2);
 278         checkEq("name of value " + TestSet.VALUE_1,
 279             t2.getValueName(TestSet.VALUE_1), TestSet.VALUE_NAME_1);
 280         checkEq("name of value " + TestSet.VALUE_2,
 281             t2.getValueName(TestSet.VALUE_2), TestSet.VALUE_NAME_2);
 282 
 283         // check tag sets
 284         if (!(t1.getTagSet() == null && t2.getTagSet() == null) &&
 285               t3.getTagSet().equals(TestSet.SOME_SET)) {
 286             throw new RuntimeException("invalid containing tag set");
 287         }
 288     }
 289 
 290     private static void checkArgs() {
 291 
 292         boolean ok = false;
 293         try {
 294             TIFFTag t = new TIFFTag(null, 0, 1 << TIFFTag.TIFF_LONG);
 295         } catch (Exception e) {
 296             ok = true;
 297         }
 298         if (!ok) {
 299             throw new RuntimeException("null names should not be allowed");
 300         }
 301 
 302         ok = false;
 303         try {
 304             TIFFTag t = new TIFFTag("abc", -1, 1 << TIFFTag.TIFF_LONG);
 305         } catch (Exception e) {
 306             ok = true;
 307         }
 308         if (!ok) {
 309             throw new RuntimeException("negative numbers should not be allowed");
 310         }
 311 
 312         ok = false;
 313         try {
 314             TIFFTag t = new TIFFTag("abc", 666, ~0x3fff);
 315         } catch (Exception e) {
 316             ok = true;
 317         }
 318         if (!ok) {
 319             throw new RuntimeException("disallowed data types were set");
 320         }
 321 
 322         ok = false;
 323         try {
 324             TIFFTag.getSizeOfType(TIFFTag.MIN_DATATYPE - 1);
 325         } catch (Exception e) {
 326             ok = true;
 327         }
 328         if (!ok) { throw new RuntimeException(
 329             "missing data types check for getSizeOfType()"); }
 330 
 331         ok = false;
 332         try {
 333             TIFFTag.getSizeOfType(TIFFTag.MAX_DATATYPE + 1);
 334         } catch (Exception e) {
 335             ok = true;
 336         }
 337         if (!ok) { throw new RuntimeException(
 338             "missing data types check for getSizeOfType()"); }
 339 
 340     }
 341 
 342 
 343     public static void main(String[] args) throws ReflectiveOperationException {
 344 
 345         String classNames[] = {"BaselineTIFFTagSet",
 346                                "ExifGPSTagSet",
 347                                "ExifInteroperabilityTagSet",
 348                                "ExifParentTIFFTagSet",
 349                                "ExifTIFFTagSet",
 350                                "FaxTIFFTagSet",
 351                                "GeoTIFFTagSet"};
 352 
 353         for (String cn: classNames) {
 354             System.out.println("Testing " + cn + ":");
 355             (new TIFFTagSetTest(
 356                 "javax.imageio.plugins.tiff." + cn)).testNamesNumbers();
 357         }
 358 
 359         System.out.println("\nTesting user-defined tag set:");
 360         testUserDefTagSet();
 361         (new TIFFTagSetTest("TIFFTagSetTest$TestSet")).testNamesNumbers();
 362 
 363         System.out.println("\nSome additional argument checks...");
 364         checkArgs();
 365         System.out.println("done");
 366     }
 367 }