/**
* Copyright 2011-2017 Asakusa Framework Team.
*
* Licensed 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 com.asakusafw.runtime.flow;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.text.MessageFormat;
import org.apache.hadoop.io.Writable;
import org.junit.Test;
import com.asakusafw.runtime.model.DataModel;
import com.asakusafw.runtime.value.IntOption;
/**
* Test for {@link FileMapListBuffer}.
*/
public class FileMapListBufferTest {
/**
* creates an empty buffer.
*/
@Test
public void createEmpty() {
FileMapListBuffer<Holder> buf = new FileMapListBuffer<>();
buf.begin();
buf.end();
assertThat(buf.size(), is(0));
buf.shrink();
}
/**
* creates a buffer with one element.
*/
@Test
public void createSingle() {
FileMapListBuffer<Holder> buf = new FileMapListBuffer<>();
buf.begin();
assertThat(buf.isExpandRequired(), is(true));
buf.expand(new Holder(""));
assertThat(buf.isExpandRequired(), is(false));
buf.advance().value = "Hello";
buf.end();
assertThat(buf.size(), is(1));
assertThat(buf.get(0), is(new Holder("Hello")));
buf.shrink();
}
/**
* reuses element objects.
*/
@Test
public void reuse() {
FileMapListBuffer<Holder> buf = new FileMapListBuffer<>();
buf.begin();
assertThat(buf.isExpandRequired(), is(true));
buf.expand(new Holder(""));
buf.advance().value = "Hello";
buf.end();
buf.shrink();
buf.begin();
buf.advance().value = "World";
buf.end();
assertThat(buf.size(), is(1));
assertThat(buf.get(0), is(new Holder("World")));
buf.shrink();
}
/**
* creates a big buffer.
*/
@Test
public void createBigList() {
int size = 10000000;
long begin = System.currentTimeMillis();
ListBuffer<Holder> buf = new FileMapListBuffer<>();
buf.begin();
for (int i = 0; i < size; i++) {
if (buf.isExpandRequired()) {
buf.expand(new Holder(""));
}
buf.advance().value = String.valueOf(i);
}
buf.end();
long written = System.currentTimeMillis();
System.out.println(MessageFormat.format(
"Elapsed for write: {0}ms",
written - begin));
for (int i = 0; i < size; i++) {
buf.get(i);
}
long read = System.currentTimeMillis();
System.out.println(MessageFormat.format(
"Elapsed for read: {0}ms",
read - written));
assertThat(buf.size(), is(size));
for (int i = 0; i < size; i++) {
assertThat(buf.get(i).value, is(String.valueOf(i)));
}
buf.shrink();
}
/**
* w/ multiple records.
* @throws Exception if failed
*/
@Test
public void huge() throws Exception {
long t0 = System.currentTimeMillis();
ListBuffer<IntOption> list = new FileMapListBuffer<>();
try {
int begin = 0;
int end = 100_000_000;
int size = range(list, begin, end);
assertThat(list.size(), is(size));
long t1 = System.currentTimeMillis();
for (int i = 0, n = end - begin; i < n; i++) {
IntOption value = list.get(i);
assertEquals(i + begin, value.get());
}
long t2 = System.currentTimeMillis();
System.out.printf("SpLB - write: %,dms, read: %,dms%n", t1 - t0, t2 - t1);
} finally {
list.shrink();
}
}
@SuppressWarnings("deprecation")
private static int range(ListBuffer<IntOption> buffer, int begin, int end) {
buffer.begin();
for (int i = begin; i < end; i++) {
if (buffer.isExpandRequired()) {
buffer.expand(new IntOption());
}
buffer.advance().modify(i);
}
buffer.end();
return end - begin;
}
/**
* over expand.
*/
@Test(expected = IndexOutOfBoundsException.class)
public void over_expand() {
FileMapListBuffer<Holder> buf = new FileMapListBuffer<>();
try {
buf.begin();
while (true) {
buf.expand(new Holder(""));
}
} finally {
buf.shrink();
}
}
/**
* missing advance.
*/
@Test(expected = IndexOutOfBoundsException.class)
public void get_UpperOutOfBounds() {
FileMapListBuffer<Holder> buf = new FileMapListBuffer<>();
try {
buf.begin();
buf.end();
buf.get(0);
} finally {
buf.shrink();
}
}
/**
* negative index.
*/
@Test(expected = IndexOutOfBoundsException.class)
public void get_LowerOutOfBounds() {
FileMapListBuffer<Holder> buf = new FileMapListBuffer<>();
try {
buf.begin();
buf.end();
buf.get(-1);
} finally {
buf.shrink();
}
}
static class Holder implements DataModel<Holder>, Writable {
String value;
Holder(String value) {
this.value = value;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Holder other = (Holder) obj;
if (value == null) {
if (other.value != null) {
return false;
}
} else if (!value.equals(other.value)) {
return false;
}
return true;
}
@Override
public String toString() {
return String.valueOf(value);
}
@Override
public void write(DataOutput out) throws IOException {
if (value != null) {
out.writeBoolean(true);
out.writeUTF(value);
} else {
out.writeBoolean(false);
}
}
@Override
public void readFields(DataInput in) throws IOException {
if (in.readBoolean()) {
value = in.readUTF();
} else {
value = null;
}
}
@Override
public void reset() {
value = null;
}
@Override
public void copyFrom(Holder other) {
value = other.value;
}
}
}