package org.hipi.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.fail;
import org.hipi.mapreduce.BinaryOutputFormat;
import org.hipi.opencv.OpenCVMatWritable;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.RecordWriter;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.TaskAttemptID;
import org.apache.hadoop.mapreduce.TaskType;
import org.apache.hadoop.mapreduce.task.TaskAttemptContextImpl;
import org.apache.hadoop.util.ReflectionUtils;
import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_core.Mat;
import org.bytedeco.javacpp.opencv_core.Scalar;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.nio.FloatBuffer;
public class BinaryOutputFormatTestCase {
// Configuration objects for Record Writer
private TaskAttemptContext context;
private Job job;
private Configuration conf;
private FileSystem fileSystem;
// Test data
private NullWritable nullKey;
private NullWritable nullValue;
private static final int intKeyData = 0;
private static final int intValueData = 1;
private IntWritable intKey;
private IntWritable intValue;
private static final float[] cvValueData = new float[] {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f};
private static final int cvMatRows = 3;
private static final int cvMatCols = 3;
private OpenCVMatWritable cvValue;
// I/O configuration
private static final Path tempTestPath = new Path("file:///tmp/hipiBinaryOutputFormatTestPath");
private static final Path tempOutputPath = new Path("file:///tmp/hipiBinaryOutputFormatTestPath/_temporary/0/_temporary/attempt_bof-test_0000_m_000000_0/part-m-00000");
@Before
public void setup() throws IOException {
// Configure BinaryOutputFormat so that it emits proper RecordWriters
job = Job.getInstance();
conf = job.getConfiguration();
conf.set("fs.defaultFS", "file:///");
TaskAttemptID tID = new TaskAttemptID("bof-test", 0, TaskType.MAP, 0, 0);
context = new TaskAttemptContextImpl(conf, tID);
BinaryOutputFormat.setOutputPath(job, tempTestPath);
// Ensure test path hasn't been previously created
fileSystem = FileSystem.get(conf);
if(fileSystem.exists(tempTestPath)) {
fileSystem.delete(tempTestPath, true);
}
// Initialize data
nullKey = NullWritable.get();
nullValue = NullWritable.get();
intKey = new IntWritable(intKeyData);
intValue = new IntWritable(intValueData);
Mat cvValueMat = new Mat(cvMatRows, cvMatCols, opencv_core.CV_32FC1, new Scalar(0.0));
((FloatBuffer)cvValueMat.createBuffer()).put(cvValueData);
cvValue = new OpenCVMatWritable(cvValueMat);
}
@After
public void teardown() throws IOException {
//remove test path after testing has finished
job = Job.getInstance();
conf = job.getConfiguration();
conf.set("fs.defaultFS", "file:///");
fileSystem = FileSystem.get(conf);
if(fileSystem.exists(tempTestPath)) {
fileSystem.delete(tempTestPath, true);
}
}
@Test
public void testBinaryOutputFormatWithNonNullAndWritableKeyAndValue() throws IOException, InterruptedException {
@SuppressWarnings("unchecked")
BinaryOutputFormat<IntWritable, IntWritable> outputFormat = ReflectionUtils.newInstance(BinaryOutputFormat.class, conf);
RecordWriter<IntWritable, IntWritable> writer = outputFormat.getRecordWriter(context);
writer.write(intKey, intValue);
writer.close(context);
if(fileSystem.exists(tempOutputPath)) {
FSDataInputStream dis = fileSystem.open(tempOutputPath);
assertEquals("Keys are not equivalent.", intKey.get(), readIntWritable(dis).get());
assertEquals("Values are not equivalent.", intValue.get(), readIntWritable(dis).get());
} else {
fail("Output of record writer not located at: " + tempOutputPath + " as expected. Hadoop configuration may have changed.");
}
}
@Test
public void testBinaryOutputFormatWithNullWritableKey() throws IOException, InterruptedException {
@SuppressWarnings("unchecked")
BinaryOutputFormat<NullWritable, IntWritable> outputFormat = ReflectionUtils.newInstance(BinaryOutputFormat.class, conf);
RecordWriter<NullWritable, IntWritable> writer = outputFormat.getRecordWriter(context);
writer.write(nullKey, intValue);
writer.close(context);
if(fileSystem.exists(tempOutputPath)) {
FSDataInputStream dis = fileSystem.open(tempOutputPath);
assertEquals("Values are not equivalent.", intValue.get(), readIntWritable(dis).get());
assertEquals("Null values were written.", 0, dis.available());
} else {
fail("Output of record writer not located at: " + tempOutputPath + " as expected. Hadoop configuration may have changed.");
}
}
@Test
public void testBinaryOutputFormatWithNullWritableValue() throws IOException, InterruptedException {
@SuppressWarnings("unchecked")
BinaryOutputFormat<IntWritable, NullWritable> outputFormat = ReflectionUtils.newInstance(BinaryOutputFormat.class, conf);
RecordWriter<IntWritable, NullWritable> writer = outputFormat.getRecordWriter(context);
writer.write(intKey, nullValue);
writer.close(context);
if(fileSystem.exists(tempOutputPath)) {
FSDataInputStream dis = fileSystem.open(tempOutputPath);
assertEquals("Keys are not equivalent.", intKey.get(), readIntWritable(dis).get());
assertEquals("Null values were written.", 0, dis.available());
} else {
fail("Output of record writer not located at: " + tempOutputPath + " as expected. Hadoop configuration may have changed.");
}
}
@Test
public void testBinaryOutputFormatWithNullWritableKeyAndValue() throws IOException, InterruptedException {
@SuppressWarnings("unchecked")
BinaryOutputFormat<NullWritable, NullWritable> outputFormat = ReflectionUtils.newInstance(BinaryOutputFormat.class, conf);
RecordWriter<NullWritable, NullWritable> writer = outputFormat.getRecordWriter(context);
writer.write(nullKey, nullValue);
writer.close(context);
if(fileSystem.exists(tempOutputPath)) {
FSDataInputStream dis = fileSystem.open(tempOutputPath);
assertEquals("Null values were written.", 0, dis.available());
} else {
fail("Output of record writer not located at: " + tempOutputPath + " as expected. Hadoop configuration may have changed.");
}
}
@Test
public void testBinaryOutputFormatWithNullKey() throws IOException, InterruptedException {
@SuppressWarnings("unchecked")
BinaryOutputFormat<IntWritable, IntWritable> outputFormat = ReflectionUtils.newInstance(BinaryOutputFormat.class, conf);
RecordWriter<IntWritable, IntWritable> writer = outputFormat.getRecordWriter(context);
writer.write(null, intValue);
writer.close(context);
if(fileSystem.exists(tempOutputPath)) {
FSDataInputStream dis = fileSystem.open(tempOutputPath);
assertEquals("Values are not equivalent.", intValue.get(), readIntWritable(dis).get());
assertEquals("Null values were written.", 0, dis.available());
} else {
fail("Output of record writer not located at: " + tempOutputPath + " as expected. Hadoop configuration may have changed.");
}
}
@Test
public void testBinaryOutputFormatWithNullValue() throws IOException, InterruptedException {
@SuppressWarnings("unchecked")
BinaryOutputFormat<IntWritable, IntWritable> outputFormat = ReflectionUtils.newInstance(BinaryOutputFormat.class, conf);
RecordWriter<IntWritable, IntWritable> writer = outputFormat.getRecordWriter(context);
writer.write(intKey, null);
writer.close(context);
if(fileSystem.exists(tempOutputPath)) {
FSDataInputStream dis = fileSystem.open(tempOutputPath);
assertEquals("Keys are not equivalent.", intKey.get(), readIntWritable(dis).get());
assertEquals("Null values were written.", 0, dis.available());
} else {
fail("Output of record writer not located at: " + tempOutputPath + " as expected. Hadoop configuration may have changed.");
}
}
@Test
public void testBinaryOutputFormatWithNullKeyAndValue() throws IOException, InterruptedException {
@SuppressWarnings("unchecked")
BinaryOutputFormat<IntWritable, IntWritable> outputFormat = ReflectionUtils.newInstance(BinaryOutputFormat.class, conf);
RecordWriter<IntWritable, IntWritable> writer = outputFormat.getRecordWriter(context);
writer.write(null, null);
writer.close(context);
if(fileSystem.exists(tempOutputPath)) {
FSDataInputStream dis = fileSystem.open(tempOutputPath);
assertEquals("Null values were written.", 0, dis.available());
} else {
fail("Output of record writer not located at: " + tempOutputPath + " as expected. Hadoop configuration may have changed.");
}
}
@Test
public void testBinaryOutputFormatWithOpenCVMatWritableAndNullKey() throws IOException, InterruptedException {
@SuppressWarnings("unchecked")
BinaryOutputFormat<NullWritable, OpenCVMatWritable> outputFormat = ReflectionUtils.newInstance(BinaryOutputFormat.class, conf);
RecordWriter<NullWritable, OpenCVMatWritable> writer = outputFormat.getRecordWriter(context);
writer.write(nullKey, cvValue);
writer.close(context);
if(fileSystem.exists(tempOutputPath)) {
FSDataInputStream dis = fileSystem.open(tempOutputPath);
assertArrayEquals("Mats are not equivalent.", cvValueData, readMatDataToArray(dis), 0.05f);
assertEquals("Null values were written.", 0, dis.available());
} else {
fail("Output of record writer not located at: " + tempOutputPath + " as expected. Hadoop configuration may have changed.");
}
}
@Test
public void testBinaryOutputFormatWithOpenCVMatWritableAndIntKey() throws IOException, InterruptedException {
@SuppressWarnings("unchecked")
BinaryOutputFormat<IntWritable, OpenCVMatWritable> outputFormat = ReflectionUtils.newInstance(BinaryOutputFormat.class, conf);
RecordWriter<IntWritable, OpenCVMatWritable> writer = outputFormat.getRecordWriter(context);
writer.write(intKey, cvValue);
writer.close(context);
if(fileSystem.exists(tempOutputPath)) {
FSDataInputStream dis = fileSystem.open(tempOutputPath);
assertEquals("Keys are not equivalent.", intKey.get(), readIntWritable(dis).get());
assertArrayEquals("Mats are not equivalent.", cvValueData, readMatDataToArray(dis), 0.05f);
assertEquals("Not all data was read.", 0, dis.available());
} else {
fail("Output of record writer not located at: " + tempOutputPath + " as expected. Hadoop configuration may have changed.");
}
}
private IntWritable readIntWritable(FSDataInputStream dis) throws IOException {
IntWritable intWritable = new IntWritable();
intWritable.readFields(dis);
return intWritable;
}
private OpenCVMatWritable readOpenCVMatWritable(FSDataInputStream dis) throws IOException {
OpenCVMatWritable openCVMatWritable = new OpenCVMatWritable();
openCVMatWritable.readFields(dis);
return openCVMatWritable;
}
// Tests assume use of mats containing floats
private float[] readMatDataToArray(FSDataInputStream dis) throws IOException {
Mat newMat = readOpenCVMatWritable(dis).getMat();
float[] newData = new float[cvValueData.length];
((FloatBuffer)newMat.createBuffer()).get(newData);
return newData;
}
}