/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.io; import java.io.*; import java.util.Arrays; import org.apache.hadoop.util.StringUtils; import org.junit.*; import junit.framework.TestCase; /** Unit tests for {@link ArrayPrimitiveWritable} */ public class TestArrayPrimitiveWritable extends TestCase { static final boolean[] b = {true, true, false}; static final char[] c = {'a', 'b', 'c'}; static final byte[] by = {1, 2, 3}; static final short[] sh = {1, 2, 3}; static final int[] i = {1, 2, 3}; static final long[] lo = {1L, 2L, 3L}; static final float[] f = {(float) 1.0, (float) 2.5, (float) 3.3}; static final double[] d = {1.0, 2.5, 3.3}; static final Object[] bigSet = {b, c, by, sh, i, lo, f, d}; static final Object[] expectedResultSet = {b, b, c, c, by, by, sh, sh, i, i, lo, lo, f, f, d, d}; final Object[] resultSet = new Object[bigSet.length * 2]; final DataOutputBuffer out = new DataOutputBuffer(); final DataInputBuffer in = new DataInputBuffer(); @Before public void resetBuffers() throws IOException { out.reset(); in.reset(); } @Test public void testMany() throws IOException { //Write a big set of data, one of each primitive type array for (Object x : bigSet) { //write each test object two ways //First, transparently via ObjectWritable ObjectWritable.writeObject(out, x, x.getClass(), null, true); //Second, explicitly via ArrayPrimitiveWritable (new ArrayPrimitiveWritable(x)).write(out); } //Now read the data back in in.reset(out.getData(), out.getLength()); for (int x = 0; x < resultSet.length; ) { //First, transparently resultSet[x++] = ObjectWritable.readObject(in, null); //Second, explicitly ArrayPrimitiveWritable apw = new ArrayPrimitiveWritable(); apw.readFields(in); resultSet[x++] = apw.get(); } //validate data structures and values assertEquals(expectedResultSet.length, resultSet.length); for (int x = 0; x < resultSet.length; x++) { assertEquals("ComponentType of array " + x, expectedResultSet[x].getClass().getComponentType(), resultSet[x].getClass().getComponentType()); } assertTrue("In and Out arrays didn't match values", Arrays.deepEquals(expectedResultSet, resultSet)); } @Test @SuppressWarnings("deprecation") public void testObjectLabeling() throws IOException { //Do a few tricky experiments to make sure things are being written //the way we expect //Write the data array with ObjectWritable //which will indirectly write it using APW.Internal ObjectWritable.writeObject(out, i, i.getClass(), null, true); //Write the corresponding APW directly with ObjectWritable ArrayPrimitiveWritable apw = new ArrayPrimitiveWritable(i); ObjectWritable.writeObject(out, apw, apw.getClass(), null, true); //Get ready to read it back in.reset(out.getData(), out.getLength()); //Read the int[] object as written by ObjectWritable, but //"going around" ObjectWritable String className = UTF8.readString(in); assertEquals("The int[] written by ObjectWritable was not labelled as " + "an ArrayPrimitiveWritable.Internal", ArrayPrimitiveWritable.Internal.class.getName(), className); ArrayPrimitiveWritable.Internal apwi = new ArrayPrimitiveWritable.Internal(); apwi.readFields(in); assertEquals("The ArrayPrimitiveWritable.Internal component type was corrupted", int.class, apw.getComponentType()); assertTrue("The int[] written by ObjectWritable as " + "ArrayPrimitiveWritable.Internal was corrupted", Arrays.equals(i, (int[])(apwi.get()))); //Read the APW object as written by ObjectWritable, but //"going around" ObjectWritable String declaredClassName = UTF8.readString(in); assertEquals("The APW written by ObjectWritable was not labelled as " + "declaredClass ArrayPrimitiveWritable", ArrayPrimitiveWritable.class.getName(), declaredClassName); className = UTF8.readString(in); assertEquals("The APW written by ObjectWritable was not labelled as " + "class ArrayPrimitiveWritable", ArrayPrimitiveWritable.class.getName(), className); ArrayPrimitiveWritable apw2 = new ArrayPrimitiveWritable(); apw2.readFields(in); assertEquals("The ArrayPrimitiveWritable component type was corrupted", int.class, apw2.getComponentType()); assertTrue("The int[] written by ObjectWritable as " + "ArrayPrimitiveWritable was corrupted", Arrays.equals(i, (int[])(apw2.get()))); } @Test public void testOldFormat() throws IOException { //Make sure we still correctly write the old format if desired. //Write the data array with old ObjectWritable API //which will set allowCompactArrays false. ObjectWritable.writeObject(out, i, i.getClass(), null); //Get ready to read it back in.reset(out.getData(), out.getLength()); //Read the int[] object as written by ObjectWritable, but //"going around" ObjectWritable @SuppressWarnings("deprecation") String className = UTF8.readString(in); assertEquals("The int[] written by ObjectWritable as a non-compact array " + "was not labelled as an array of int", i.getClass().getName(), className); int length = in.readInt(); assertEquals("The int[] written by ObjectWritable as a non-compact array " + "was not expected length", i.length, length); int[] readValue = new int[length]; try { for (int i = 0; i < length; i++) { readValue[i] = (int)((Integer)ObjectWritable.readObject(in, null)); } } catch (Exception e) { fail("The int[] written by ObjectWritable as a non-compact array " + "was corrupted. Failed to correctly read int[] of length " + length + ". Got exception:\n" + StringUtils.stringifyException(e)); } assertTrue("The int[] written by ObjectWritable as a non-compact array " + "was corrupted.", Arrays.equals(i, readValue)); } }