Path: blob/master/test/jdk/javax/imageio/plugins/tiff/TIFFFieldTest.java
41153 views
/*1* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @bug 8152183 8149562 8169725 816972826* @author a.stepanov27* @summary Some checks for TIFFField methods28* @run main TIFFFieldTest29*/3031import java.util.List;32import java.util.ArrayList;33import javax.imageio.metadata.IIOMetadataNode;34import javax.imageio.plugins.tiff.*;35import org.w3c.dom.NamedNodeMap;36import org.w3c.dom.Node;3738public class TIFFFieldTest {3940private final static String NAME = "tag"; // tag name41private final static int NUM = 12345; // tag number42private final static int MIN_TYPE = TIFFTag.MIN_DATATYPE;43private final static int MAX_TYPE = TIFFTag.MAX_DATATYPE;44private final static String CONSTRUCT = "can construct TIFFField with ";4546private void check(boolean ok, String msg) {47if (!ok) { throw new RuntimeException(msg); }48}4950private void testConstructors() {5152// test constructors5354TIFFTag tag = new TIFFTag(55NAME, NUM, 1 << TIFFTag.TIFF_SHORT | 1 << TIFFTag.TIFF_LONG);56TIFFField f;5758// constructor: TIFFField(tag, value)59boolean ok = false;60try { new TIFFField(null, 0); }61catch (NullPointerException e) { ok = true; }62check(ok, CONSTRUCT + "null tag");6364ok = false;65try { new TIFFField(tag, -1); }66catch (IllegalArgumentException e) { ok = true; }67check(ok, CONSTRUCT + "negative value");6869ok = false;70try { new TIFFField(tag, 1L << 32); }71catch (IllegalArgumentException e) { ok = true; }72check(ok, CONSTRUCT + "value > 0xffffffff");7374ok = false;75try {76TIFFTag t = new TIFFTag(NAME, NUM, 1 << TIFFTag.TIFF_SHORT);77new TIFFField(t, 0x10000);78} catch (IllegalArgumentException e) { ok = true; }79check(ok, CONSTRUCT + "value 0x10000 incompatible with TIFF_SHORT");8081ok = false;82try {83TIFFTag t = new TIFFTag(NAME, NUM, 1 << TIFFTag.TIFF_LONG);84new TIFFField(t, 0xffff);85} catch (IllegalArgumentException e) { ok = true; }86check(ok, CONSTRUCT + "value 0xffff incompatible with TIFF_LONG");8788// check value type recognition89int v = 1 << 16;90f = new TIFFField(tag, v - 1);91check(f.getType() == TIFFTag.TIFF_SHORT, "must be treated as short");92check(f.isIntegral(), "must be integral");93f = new TIFFField(tag, v);94check(f.getType() == TIFFTag.TIFF_LONG, "must be treated as long");9596// other checks97check(f.getAsLongs().length == 1, "invalid long[] size");98check(f.isIntegral(), "must be integral");99check((f.getDirectory() == null) && !f.hasDirectory(),100"must not have directory");101check(f.getValueAsString(0).equals(String.valueOf(v)),102"invalid string representation of value");103check(f.getTag().getNumber() == f.getTagNumber(),104"invalid tag number");105check(f.getCount() == 1, "invalid count");106check(f.getTagNumber() == NUM, "invalid tag number");107108// constructor: TIFFField(tag, type, count)109int type = TIFFTag.TIFF_SHORT;110111ok = false;112try { new TIFFField(null, type, 1); }113catch (NullPointerException e) { ok = true; }114check(ok, CONSTRUCT + "null tag");115116ok = false;117try { new TIFFField(tag, MAX_TYPE + 1, 1); }118catch (IllegalArgumentException e) { ok = true; }119check(ok, CONSTRUCT + "invalid type tag");120121// check that count == 1 for TIFF_IFD_POINTER122ok = false;123try { new TIFFField(tag, TIFFTag.TIFF_IFD_POINTER, 0); }124catch (IllegalArgumentException e) { ok = true; }125check(ok, "only count = 1 should be allowed for IFDPointer");126127ok = false;128try { new TIFFField(tag, TIFFTag.TIFF_IFD_POINTER, 2); }129catch (IllegalArgumentException e) { ok = true; }130check(ok, "only count = 1 should be allowed for IFDPointer");131132// check that count == 0 is not allowed for TIFF_RATIONAL, TIFF_SRATIONAL133// (see fix for JDK-8149120)134ok = false;135try { new TIFFField(tag, TIFFTag.TIFF_RATIONAL, 0); }136catch (IllegalArgumentException e) { ok = true; }137check(ok, "count = 0 should not be allowed for Rational");138139ok = false;140try { new TIFFField(tag, TIFFTag.TIFF_SRATIONAL, 0); }141catch (IllegalArgumentException e) { ok = true; }142check(ok, "count = 0 should not be allowed for SRational");143144ok = false;145try { new TIFFField(tag, type, -1); }146catch (IllegalArgumentException e) { ok = true; }147check(ok, CONSTRUCT + "with invalid data count");148149f = new TIFFField(tag, type, 0);150check(f.getCount() == 0, "invalid count");151check(!f.hasDirectory(), "must not have directory");152153// constructor: TIFFField(tag, type, count, data)154double a[] = {0.1, 0.2, 0.3};155ok = false;156try { new TIFFField(null, TIFFTag.TIFF_DOUBLE, a.length, a); }157catch (NullPointerException e) { ok = true; }158check(ok, CONSTRUCT + "null tag");159160ok = false;161try { new TIFFField(tag, type, a.length - 1, a); }162catch (IllegalArgumentException e) { ok = true; }163check(ok, CONSTRUCT + "invalid data count");164165String a2[] = {"one", "two"};166ok = false;167try { new TIFFField(tag, type, 2, a2); }168catch (IllegalArgumentException e) { ok = true; }169check(ok, CONSTRUCT + "invalid data type");170check((f.getDirectory() == null) && !f.hasDirectory(),171"must not have directory");172173ok = false;174try {175TIFFTag t = new TIFFTag(NAME, NUM, 1 << TIFFTag.TIFF_RATIONAL);176long[][] tiffRationals = new long[6][3];177new TIFFField(t, TIFFTag.TIFF_RATIONAL, tiffRationals.length,178tiffRationals);179} catch (IllegalArgumentException e) {180ok = true;181}182183ok = false;184try {185TIFFTag t = new TIFFTag(NAME, NUM, 1 << TIFFTag.TIFF_SRATIONAL);186int[][] tiffSRationals = new int[6][3];187new TIFFField(t, TIFFTag.TIFF_SRATIONAL, tiffSRationals.length,188tiffSRationals);189} catch (IllegalArgumentException e) {190ok = true;191}192193ok = false;194try {195TIFFTag t = new TIFFTag(NAME, NUM, 1 << TIFFTag.TIFF_LONG);196long[] tiffLongs = new long[] {0, -7, 10};197new TIFFField(t, TIFFTag.TIFF_LONG, tiffLongs.length,198tiffLongs);199} catch (IllegalArgumentException e) {200ok = true;201}202203ok = false;204try {205TIFFTag t = new TIFFTag(NAME, NUM, 1 << TIFFTag.TIFF_LONG);206long[] tiffLongs = new long[] {0, 7, 0x100000000L};207new TIFFField(t, TIFFTag.TIFF_LONG, tiffLongs.length,208tiffLongs);209} catch (IllegalArgumentException e) {210ok = true;211}212213ok = false;214try {215TIFFTag t = new TIFFTag(NAME, NUM, 1 << TIFFTag.TIFF_IFD_POINTER);216long[] tiffLongs = new long[] {-7};217new TIFFField(t, TIFFTag.TIFF_IFD_POINTER, tiffLongs.length,218tiffLongs);219} catch (IllegalArgumentException e) {220ok = true;221}222223ok = false;224try {225TIFFTag t = new TIFFTag(NAME, NUM, 1 << TIFFTag.TIFF_IFD_POINTER);226long[] tiffLongs = new long[] {0x100000000L};227new TIFFField(t, TIFFTag.TIFF_IFD_POINTER, tiffLongs.length,228tiffLongs);229} catch (IllegalArgumentException e) {230ok = true;231}232233ok = false;234try {235TIFFTag t = new TIFFTag(NAME, NUM, 1 << TIFFTag.TIFF_RATIONAL);236long[][] tiffRationals = new long[][] {237{10, 2},238{1, -3},239{4, 7}240};241new TIFFField(t, TIFFTag.TIFF_RATIONAL, tiffRationals.length,242tiffRationals);243} catch (IllegalArgumentException e) {244ok = true;245}246247ok = false;248try {249TIFFTag t = new TIFFTag(NAME, NUM, 1 << TIFFTag.TIFF_RATIONAL);250long[][] tiffRationals = new long[][] {251{10, 2},252{0x100000000L, 3},253{4, 7}254};255new TIFFField(t, TIFFTag.TIFF_RATIONAL, tiffRationals.length,256tiffRationals);257} catch (IllegalArgumentException e) {258ok = true;259}260261// constructor: TIFFField(tag, type, offset, dir)262List<TIFFTag> tags = new ArrayList<>();263tags.add(tag);264TIFFTagSet sets[] = {new TIFFTagSet(tags)};265TIFFDirectory dir = new TIFFDirectory(sets, null);266267ok = false;268try { new TIFFField(null, type, 4L, dir); }269catch (NullPointerException e) { ok = true; }270check(ok, CONSTRUCT + "null tag");271272ok = false;273try { new TIFFField(tag, type, 0L, dir); }274catch (IllegalArgumentException e) { ok = true; }275check(ok, CONSTRUCT + "non-positive offset");276277long offset = 4;278279for (int t = MIN_TYPE; t <= MAX_TYPE; t++) {280281tag = new TIFFTag(NAME, NUM, 1 << t);282283// only TIFF_LONG and TIFF_IFD_POINTER types are allowed284if (t == TIFFTag.TIFF_LONG || t == TIFFTag.TIFF_IFD_POINTER) {285286f = new TIFFField(tag, t, offset, dir);287check(f.hasDirectory(), "must have directory");288289check(f.getDirectory().getTag(NUM).getName().equals(NAME),290"invalid tag name");291292check(f.getCount() == 1, "invalid count");293check(f.getAsLong(0) == offset, "invalid offset");294} else {295ok = false;296try { new TIFFField(tag, t, offset, dir); }297catch (IllegalArgumentException e) { ok = true; }298check(ok, CONSTRUCT + "invalid data type");299}300}301302type = TIFFTag.TIFF_IFD_POINTER;303tag = new TIFFTag(NAME, NUM, 1 << type);304ok = false;305try { new TIFFField(tag, type, offset, null); }306catch (NullPointerException e) { ok = true; }307check(ok, CONSTRUCT + "null TIFFDirectory");308309type = TIFFTag.TIFF_LONG;310tag = new TIFFTag(NAME, NUM, 1 << type);311ok = false;312try { new TIFFField(tag, type, offset, null); }313catch (NullPointerException e) { ok = true; }314check(ok, CONSTRUCT + "null TIFFDirectory");315}316317private void testTypes() {318319// test getTypeName(), getTypeByName() methods320321boolean ok = false;322try { TIFFField.getTypeName(MIN_TYPE - 1); }323catch (IllegalArgumentException e) { ok = true; }324check(ok, "invalid data type number used");325326ok = false;327try { TIFFField.getTypeName(MAX_TYPE + 1); }328catch (IllegalArgumentException e) { ok = true; }329check(ok, "invalid data type number used");330331for (int type = MIN_TYPE; type <= MAX_TYPE; type++) {332String name = TIFFField.getTypeName(type);333check(TIFFField.getTypeByName(name) == type, "invalid type");334}335336for (int type = MIN_TYPE; type <= MAX_TYPE; type++) {337338TIFFTag tag = new TIFFTag(NAME, NUM, 1 << type);339TIFFField f = new TIFFField(tag, type, 1);340check(f.getType() == type, "invalid type");341342// check that invalid data types can not be used343for (int type2 = MIN_TYPE; type2 <= MAX_TYPE; ++type2) {344if (type2 != type) {345ok = false;346try { new TIFFField(tag, type2, 1); } // invalid type347catch (IllegalArgumentException e) { ok = true; }348check(ok, "invalid type was successfully set");349}350}351}352}353354private void testGetAs() {355356// test getAs...() methods357358int type = TIFFTag.TIFF_SHORT;359TIFFTag tag = new TIFFTag(NAME, NUM, 1 << TIFFTag.TIFF_SHORT);360361short v = 123;362TIFFField f = new TIFFField(tag, v);363364check(f.getAsInt(0) == (int) v, "invalid int value");365check(f.getAsLong(0) == (long) v, "invalid long value");366check(f.getAsFloat(0) == (float) v, "invalid float value");367check(f.getAsDouble(0) == (double) v, "invalid double value");368check(f.getValueAsString(0).equals(Short.toString(v)),369"invalid string representation");370371check(f.getAsInts().length == 1, "inavlid array size");372check((int) v == f.getAsInts()[0], "invalid int value");373374float fa[] = {0.01f, 1.01f};375type = TIFFTag.TIFF_FLOAT;376f = new TIFFField(377new TIFFTag(NAME, NUM, 1 << type), type, fa.length, fa);378check(f.getCount() == fa.length, "invalid count");379float fa2[] = f.getAsFloats();380check(fa2.length == fa.length, "invalid array size");381382for (int i = 0; i < fa.length; i++) {383check(fa2[i] == fa[i], "invalid value");384check(f.getAsDouble(i) == fa[i], "invalid value");385check(f.getAsInt(i) == (int) fa[i], "invalid value"); // cast to int386check(f.getValueAsString(i).equals(Float.toString(fa[i])),387"invalid string representation");388}389390byte ba[] = {-1, -10, -100};391type = TIFFTag.TIFF_BYTE;392f = new TIFFField(393new TIFFTag(NAME, NUM, 1 << type), type, ba.length, ba);394check(f.getCount() == ba.length, "invalid count");395byte ba2[] = f.getAsBytes();396check(ba2.length == ba.length, "invalid count");397398for (int i = 0; i < ba.length; i++) {399check(ba[i] == ba2[i], "invalid value");400check(ba[i] == (byte) f.getAsDouble(i), "invalid value");401check(ba[i] == (byte) f.getAsLong(i), "invalid value");402403int unsigned = ba[i] & 0xff;404check(f.getAsInt(i) == unsigned, "must be treated as unsigned");405}406407char ca[] = {'a', 'z', 0xffff};408type = TIFFTag.TIFF_SHORT;409f = new TIFFField(410new TIFFTag(NAME, NUM, 1 << type), type, ca.length, ca);411check(f.getCount() == ca.length, "invalid count");412char ca2[] = f.getAsChars();413check(ba2.length == ba.length, "invalid count");414415for (int i = 0; i < ca.length; i++) {416check(ca[i] == ca2[i], "invalid value");417check(ca[i] == (char) f.getAsDouble(i), "invalid value");418check(ca[i] == (char) f.getAsLong(i), "invalid value");419check(ca[i] == (char) f.getAsInt(i), "invalid value");420}421422type = TIFFTag.TIFF_DOUBLE;423double da[] = {0.1, 0.2, 0.3};424f = new TIFFField(425new TIFFTag(NAME, NUM, 1 << type), type, da.length, da);426check(!f.isIntegral(), "isIntegral must be false");427428double da2[] = f.getAsDoubles();429check(f.getData() instanceof double[], "invalid data type");430double da3[] = (double[]) f.getData();431check((da.length == da2.length) &&432(da.length == da2.length) &&433(da.length == f.getCount()),434"invalid data count");435for (int i = 0; i < da.length; ++i) {436check(da[i] == da2[i], "invalid data");437check(da[i] == da3[i], "invalid data");438}439440boolean ok = false;441try { f.getAsShorts(); }442catch (ClassCastException e) { ok = true; }443check(ok, "invalid data cast");444445ok = false;446try { f.getAsRationals(); }447catch (ClassCastException e) { ok = true; }448check(ok, "invalid data cast");449450ok = false;451try { TIFFField.createArrayForType(TIFFTag.MIN_DATATYPE - 1, 1); }452catch (IllegalArgumentException e) { ok = true; }453check(ok, "can create array with invalid datatype");454455ok = false;456try { TIFFField.createArrayForType(TIFFTag.MAX_DATATYPE + 1, 1); }457catch (IllegalArgumentException e) { ok = true; }458check(ok, "can create array with invalid datatype");459460ok = false;461try { TIFFField.createArrayForType(TIFFTag.TIFF_FLOAT, -1); }462catch (IllegalArgumentException e) { ok = true; }463check(ok, "can create array with negative count");464465int n = 3;466Object467RA = TIFFField.createArrayForType(TIFFTag.TIFF_RATIONAL, n),468SRA = TIFFField.createArrayForType(TIFFTag.TIFF_SRATIONAL, n);469check(RA instanceof long[][], "invalid data type");470check(SRA instanceof int[][], "invalid data type");471472long ra[][] = (long[][]) RA;473int sra[][] = (int[][]) SRA;474check((ra.length == n) && (sra.length == n), "invalid data size");475for (int i = 0; i < n; i++) {476check((ra[i].length == 2) && (sra[i].length == 2),477"invalid data size");478ra[i][0] = 1; ra[i][1] = 5 + i;479sra[i][0] = -1; sra[i][1] = 5 + i;480}481482type = TIFFTag.TIFF_RATIONAL;483TIFFField f1 = new TIFFField(484new TIFFTag(NAME, NUM, 1 << type), type, n, ra);485type = TIFFTag.TIFF_SRATIONAL;486TIFFField f2 = new TIFFField(487new TIFFTag(NAME, NUM, 1 << type), type, n, sra);488489check((f1.getCount() == ra.length) && (f2.getCount() == sra.length),490"invalid data count");491492check(f1.getAsRationals().length == n, "invalid data count");493check(f2.getAsSRationals().length == n, "invalid data count");494for (int i = 0; i < n; i++) {495long r[] = f1.getAsRational(i);496check(r.length == 2, "invalid data format");497check((r[0] == 1) && (r[1] == i + 5), "invalid data");498499int sr[] = f2.getAsSRational(i);500check(sr.length == 2, "invalid data format");501check((sr[0] == -1) && (sr[1] == i + 5), "invalid data");502503// check string representation504String s = Long.toString(r[0]) + "/" + Long.toString(r[1]);505check(s.equals(f1.getValueAsString(i)),506"invalid string representation");507508s = Integer.toString(sr[0]) + "/" + Integer.toString(sr[1]);509check(s.equals(f2.getValueAsString(i)),510"invalid string representation");511512// see the documentation for getAsInt:513// TIFF_SRATIONAL or TIFF_RATIONAL format are evaluated514// by dividing the numerator into the denominator using515// double-precision arithmetic and then casting to int516check(f1.getAsInt(i) == (int)(r[0] / r[1]),517"invalid result for getAsInt");518check(f2.getAsInt(i) == (int)(r[0] / r[1]),519"invalid result for getAsInt");520}521522ok = false;523try { f1.getAsRational(ra.length); }524catch (ArrayIndexOutOfBoundsException e) { ok = true; }525check(ok, "invalid index");526527String sa[] = {"-1.e-25", "22", "-1.23E5"};528type = TIFFTag.TIFF_ASCII;529f = new TIFFField(530new TIFFTag(NAME, NUM, 1 << type), type, sa.length, sa);531532// test clone() method533TIFFField cloned = null;534try { cloned = f.clone(); } catch (CloneNotSupportedException e) {535throw new RuntimeException(e);536}537538check(f.getCount() == cloned.getCount(), "invalid cloned field count");539540check(f.getCount() == sa.length, "invalid data count");541for (int i = 0; i < sa.length; i++) {542check(sa[i].equals(f.getAsString(i)), "invalid data");543// see docs: "data in TIFF_ASCII format will be parsed as by544// the Double.parseDouble method, with the result cast to int"545check(f.getAsInt(i) ==546(int) Double.parseDouble(sa[i]), "invalid data");547check(f.getAsDouble(i) == Double.parseDouble(sa[i]), "invalid data");548549check(sa[i].equals(cloned.getAsString(i)), "invalid cloned data");550}551}552553private void testCreateFromNode() {554555int type = TIFFTag.TIFF_LONG;556557List<TIFFTag> tags = new ArrayList<>();558int v = 1234567;559TIFFTag tag = new TIFFTag(NAME, NUM, 1 << type);560tags.add(tag);561TIFFTagSet ts = new TIFFTagSet(tags);562563boolean ok = false;564try {565TIFFField.createFromMetadataNode(ts, null);566} catch (IllegalArgumentException e) {567// createFromMetadataNode() formerly threw a NullPointerException568// if its Node parameter was null, but the specification has been569// modified to allow only IllegalArgumentExceptions, perhaps with570// a cause set. In the present invocation the cause would be set571// to a NullPointerException but this is not explicitly specified572// hence not verified here.573ok = true;574}575check(ok, "can create TIFFField from a null node");576577TIFFField f = new TIFFField(tag, v);578Node node = f.getAsNativeNode();579check(node.getNodeName().equals(f.getClass().getSimpleName()),580"invalid node name");581582NamedNodeMap attrs = node.getAttributes();583for (int i = 0; i < attrs.getLength(); i++) {584String an = attrs.item(i).getNodeName().toLowerCase();585String av = attrs.item(i).getNodeValue();586if (an.contains("name")) {587check(av.equals(NAME), "invalid tag name");588} else if (an.contains("number")) {589check(av.equals(Integer.toString(NUM)), "invalid tag number");590}591}592593// invalid node594IIOMetadataNode nok = new IIOMetadataNode("NOK");595596ok = false;597try { TIFFField.createFromMetadataNode(ts, nok); }598catch (IllegalArgumentException e) { ok = true; }599check(ok, CONSTRUCT + "invalid node name");600601TIFFField f2 = TIFFField.createFromMetadataNode(ts, node);602check(f2.getType() == type, "invalid type");603check(f2.getTagNumber() == NUM, "invalid tag number");604check(f2.getTag().getName().equals(NAME), "invalid tag name");605check(f2.getCount() == 1, "invalid count");606check(f2.getAsInt(0) == v, "invalid value");607}608609public static void main(String[] args) {610611TIFFFieldTest test = new TIFFFieldTest();612test.testConstructors();613test.testCreateFromNode();614test.testTypes();615test.testGetAs();616}617}618619620