/** * 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.mapred.gridmix; import java.io.IOException; import java.util.Arrays; import java.util.Random; import org.junit.Test; import static org.junit.Assert.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.io.DataInputBuffer; import org.apache.hadoop.io.DataOutputBuffer; import org.apache.hadoop.io.WritableComparator; import org.apache.hadoop.io.WritableUtils; public class TestGridmixRecord { private static final Log LOG = LogFactory.getLog(TestGridmixRecord.class); static void lengthTest(GridmixRecord x, GridmixRecord y, int min, int max) throws Exception { final Random r = new Random(); final long seed = r.nextLong(); r.setSeed(seed); LOG.info("length: " + seed); final DataInputBuffer in = new DataInputBuffer(); final DataOutputBuffer out1 = new DataOutputBuffer(); final DataOutputBuffer out2 = new DataOutputBuffer(); for (int i = min; i < max; ++i) { setSerialize(x, r.nextLong(), i, out1); // check write assertEquals(i, out1.getLength()); // write to stream x.write(out2); // check read in.reset(out1.getData(), 0, out1.getLength()); y.readFields(in); assertEquals(i, x.getSize()); assertEquals(i, y.getSize()); } // check stream read in.reset(out2.getData(), 0, out2.getLength()); for (int i = min; i < max; ++i) { y.readFields(in); assertEquals(i, y.getSize()); } } static void randomReplayTest(GridmixRecord x, GridmixRecord y, int min, int max) throws Exception { final Random r = new Random(); final long seed = r.nextLong(); r.setSeed(seed); LOG.info("randReplay: " + seed); final DataOutputBuffer out1 = new DataOutputBuffer(); for (int i = min; i < max; ++i) { final int s = out1.getLength(); x.setSeed(r.nextLong()); x.setSize(i); x.write(out1); assertEquals(i, out1.getLength() - s); } final DataInputBuffer in = new DataInputBuffer(); in.reset(out1.getData(), 0, out1.getLength()); final DataOutputBuffer out2 = new DataOutputBuffer(); // deserialize written records, write to separate buffer for (int i = min; i < max; ++i) { final int s = in.getPosition(); y.readFields(in); assertEquals(i, in.getPosition() - s); y.write(out2); } // verify written contents match assertEquals(out1.getLength(), out2.getLength()); // assumes that writes will grow buffer deterministically assertEquals("Bad test", out1.getData().length, out2.getData().length); assertArrayEquals(out1.getData(), out2.getData()); } static void eqSeedTest(GridmixRecord x, GridmixRecord y, int max) throws Exception { final Random r = new Random(); final long s = r.nextLong(); r.setSeed(s); LOG.info("eqSeed: " + s); assertEquals(x.fixedBytes(), y.fixedBytes()); final int min = x.fixedBytes() + 1; final DataOutputBuffer out1 = new DataOutputBuffer(); final DataOutputBuffer out2 = new DataOutputBuffer(); for (int i = min; i < max; ++i) { final long seed = r.nextLong(); setSerialize(x, seed, i, out1); setSerialize(y, seed, i, out2); assertEquals(x, y); assertEquals(x.hashCode(), y.hashCode()); // verify written contents match assertEquals(out1.getLength(), out2.getLength()); // assumes that writes will grow buffer deterministically assertEquals("Bad test", out1.getData().length, out2.getData().length); assertArrayEquals(out1.getData(), out2.getData()); } } static void binSortTest(GridmixRecord x, GridmixRecord y, int min, int max, WritableComparator cmp) throws Exception { final Random r = new Random(); final long s = r.nextLong(); r.setSeed(s); LOG.info("sort: " + s); final DataOutputBuffer out1 = new DataOutputBuffer(); final DataOutputBuffer out2 = new DataOutputBuffer(); for (int i = min; i < max; ++i) { final long seed1 = r.nextLong(); setSerialize(x, seed1, i, out1); assertEquals(0, x.compareSeed(seed1, Math.max(0, i - x.fixedBytes()))); final long seed2 = r.nextLong(); setSerialize(y, seed2, i, out2); assertEquals(0, y.compareSeed(seed2, Math.max(0, i - x.fixedBytes()))); // for eq sized records, ensure byte cmp where req final int chk = WritableComparator.compareBytes( out1.getData(), 0, out1.getLength(), out2.getData(), 0, out2.getLength()); assertEquals(chk, x.compareTo(y)); assertEquals(chk, cmp.compare( out1.getData(), 0, out1.getLength(), out2.getData(), 0, out2.getLength())); // write second copy, compare eq final int s1 = out1.getLength(); x.write(out1); assertEquals(0, cmp.compare(out1.getData(), 0, s1, out1.getData(), s1, out1.getLength() - s1)); final int s2 = out2.getLength(); y.write(out2); assertEquals(0, cmp.compare(out2.getData(), 0, s2, out2.getData(), s2, out2.getLength() - s2)); assertEquals(chk, cmp.compare(out1.getData(), 0, s1, out2.getData(), s2, out2.getLength() - s2)); } } static void checkSpec(GridmixKey a, GridmixKey b) throws Exception { final Random r = new Random(); final long s = r.nextLong(); r.setSeed(s); LOG.info("spec: " + s); final DataInputBuffer in = new DataInputBuffer(); final DataOutputBuffer out = new DataOutputBuffer(); a.setType(GridmixKey.REDUCE_SPEC); b.setType(GridmixKey.REDUCE_SPEC); for (int i = 0; i < 100; ++i) { final int in_rec = r.nextInt(Integer.MAX_VALUE); a.setReduceInputRecords(in_rec); final int out_rec = r.nextInt(Integer.MAX_VALUE); a.setReduceOutputRecords(out_rec); final int out_bytes = r.nextInt(Integer.MAX_VALUE); a.setReduceOutputBytes(out_bytes); final int min = WritableUtils.getVIntSize(in_rec) + WritableUtils.getVIntSize(out_rec) + WritableUtils.getVIntSize(out_bytes) + WritableUtils.getVIntSize(0); assertEquals(min + 2, a.fixedBytes()); // meta + vint min final int size = r.nextInt(1024) + a.fixedBytes() + 1; setSerialize(a, r.nextLong(), size, out); assertEquals(size, out.getLength()); assertTrue(a.equals(a)); assertEquals(0, a.compareTo(a)); in.reset(out.getData(), 0, out.getLength()); b.readFields(in); assertEquals(size, b.getSize()); assertEquals(in_rec, b.getReduceInputRecords()); assertEquals(out_rec, b.getReduceOutputRecords()); assertEquals(out_bytes, b.getReduceOutputBytes()); assertTrue(a.equals(b)); assertEquals(0, a.compareTo(b)); assertEquals(a.hashCode(), b.hashCode()); } } static void setSerialize(GridmixRecord x, long seed, int size, DataOutputBuffer out) throws IOException { x.setSeed(seed); x.setSize(size); out.reset(); x.write(out); } @Test public void testKeySpec() throws Exception { final int min = 6; final int max = 300; final GridmixKey a = new GridmixKey(GridmixKey.REDUCE_SPEC, 1, 0L); final GridmixKey b = new GridmixKey(GridmixKey.REDUCE_SPEC, 1, 0L); lengthTest(a, b, min, max); randomReplayTest(a, b, min, max); binSortTest(a, b, min, max, new GridmixKey.Comparator()); // 2 fixed GR bytes, 1 type, 3 spec eqSeedTest(a, b, max); checkSpec(a, b); } @Test public void testKeyData() throws Exception { final int min = 2; final int max = 300; final GridmixKey a = new GridmixKey(GridmixKey.DATA, 1, 0L); final GridmixKey b = new GridmixKey(GridmixKey.DATA, 1, 0L); lengthTest(a, b, min, max); randomReplayTest(a, b, min, max); binSortTest(a, b, min, max, new GridmixKey.Comparator()); // 2 fixed GR bytes, 1 type eqSeedTest(a, b, 300); } @Test public void testBaseRecord() throws Exception { final int min = 1; final int max = 300; final GridmixRecord a = new GridmixRecord(); final GridmixRecord b = new GridmixRecord(); lengthTest(a, b, min, max); randomReplayTest(a, b, min, max); binSortTest(a, b, min, max, new GridmixRecord.Comparator()); // 2 fixed GR bytes eqSeedTest(a, b, 300); } public static void main(String[] argv) throws Exception { boolean fail = false; final TestGridmixRecord test = new TestGridmixRecord(); try { test.testKeySpec(); } catch (Exception e) { fail = true; e.printStackTrace(); } try {test.testKeyData(); } catch (Exception e) { fail = true; e.printStackTrace(); } try {test.testBaseRecord(); } catch (Exception e) { fail = true; e.printStackTrace(); } System.exit(fail ? -1 : 0); } static void printDebug(GridmixRecord a, GridmixRecord b) throws IOException { DataOutputBuffer out = new DataOutputBuffer(); a.write(out); System.out.println("A " + Arrays.toString(Arrays.copyOf(out.getData(), out.getLength()))); out.reset(); b.write(out); System.out.println("B " + Arrays.toString(Arrays.copyOf(out.getData(), out.getLength()))); } }