package net.yadan.banana.memory.malloc;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collection;
import net.yadan.banana.memory.IMemAllocator;
import net.yadan.banana.memory.OutOfMemoryException;
import net.yadan.banana.memory.initializers.MemSetInitializer;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(value = Parameterized.class)
public abstract class AbstractCharsTest {
protected IMemAllocator m;
protected int m_allocationSize;
public AbstractCharsTest(int numBlocks, int blockSize, int allocationSize) {
m_allocationSize = allocationSize;
init(numBlocks, blockSize);
}
public abstract void init(int numBlocks, int blockSize);
@Parameters
public static Collection<Object[]> data() {
//@formatter:off
Object[][] data = new Object[][] {
{ 100, 5, 5}, // normal non indexed block
{ 100, 5, 10},// single index block
{ 100, 5, 20},// single index block, full utilization
{ 200, 3, 7},
{ 200, 3, 14},
{ 200, 3, 60},
{ 50, 3, 9},
};
return Arrays.asList(data);
}
//@formatter:on
@After
public void postTest() {
if (m != null) {
assertEquals("Test leaks memory", 0, m.usedBlocks());
}
m = null;
}
@Override
public String toString() {
return m.toString();
}
@Test
public void testSetCharsFullBlocks() {
int p = m.malloc(m_allocationSize);
int numChars = m_allocationSize * 2;
char buf[] = new char[numChars];
for (int i = 0; i < numChars; i++) {
buf[i] = (char) ('a' + i);
}
m.setChars(p, 0, buf, 0, numChars);
for (int i = 0; i < numChars; i++) {
char e = (char) ('a' + i);
int ii = i / 2;
if (i % 2 == 0) {
char c = (char) m.getUpperShort(p, ii);
assertEquals(e, c);
} else {
char c = (char) m.getLowerShort(p, ii);
assertEquals(e, c);
}
}
m.free(p);
}
@Test
public void testGetCharsFullBlocks() {
int p = m.malloc(m_allocationSize);
int numChars = m_allocationSize * 2;
char buf[] = new char[numChars];
for (int i = 0; i < numChars; i++) {
buf[i] = (char) ('a' + i);
}
m.setChars(p, 0, buf, 0, numChars);
char out[] = new char[numChars];
m.getChars(p, 0, out, 0, numChars);
assertArrayEquals(buf, out);
m.free(p);
}
@Test
public void testSetCharsFullBlocks_even() {
int p = m.malloc(m_allocationSize);
// uninitialized memory will be initialized to -1
m.setInitializer(new MemSetInitializer(-1));
int numChars = m_allocationSize * 2 - 1;
char buf[] = new char[numChars];
for (int i = 0; i < numChars; i++) {
buf[i] = (char) ('a' + i);
}
m.setChars(p, 0, buf, 0, numChars);
for (int i = 0; i < numChars; i++) {
char e = buf[i];
int ii = i / 2;
if (i % 2 == 0) {
char c = (char) m.getUpperShort(p, ii);
assertEquals(e, c);
} else {
char c = (char) m.getLowerShort(p, ii);
assertEquals(e, c);
}
}
assertEquals(-1, m.getLowerShort(p, m_allocationSize - 1));
m.free(p);
}
@Test
public void testGetCharsFullBlocks_even() {
int p = m.malloc(m_allocationSize);
int numChars = m_allocationSize * 2;
char buf[] = new char[numChars];
for (int i = 0; i < numChars; i++) {
buf[i] = (char) ('a' + i);
}
m.setChars(p, 0, buf, 0, numChars);
char out[] = new char[numChars];
m.getChars(p, 0, out, 0, numChars);
assertArrayEquals(buf, out);
m.free(p);
}
@Test
public void testSetCharsPartialFirstBlock() {
int p = m.malloc(m_allocationSize);
int numChars = m_allocationSize * 2 - 2;
char buf[] = new char[numChars];
for (int i = 0; i < numChars; i++) {
buf[i] = (char) ('a' + i);
}
m.setInt(p, 0, -100);
m.setChars(p, 1, buf, 0, buf.length);
assertEquals(-100, m.getInt(p, 0));
for (int i = 0; i < numChars; i++) {
char e = buf[i];
int ii = i / 2 + 1;
if (i % 2 == 0) {
char c = (char) m.getUpperShort(p, ii);
assertEquals(e, c);
} else {
char c = (char) m.getLowerShort(p, ii);
assertEquals(e, c);
}
}
m.free(p);
}
@Test
public void testGetCharsPartialFirstBlock() {
int p = m.malloc(m_allocationSize);
int numChars = m_allocationSize * 2 - 2;
char buf[] = new char[numChars];
for (int i = 0; i < numChars; i++) {
buf[i] = (char) ('a' + i);
}
m.setInt(p, 0, -100);
m.setChars(p, 1, buf, 0, buf.length);
char out[] = new char[numChars];
m.getChars(p, 1, out, 0, numChars);
assertArrayEquals(buf, out);
m.free(p);
}
@Test
public void testSetCharsPartialFirstBlockDeep() {
int p = m.malloc(m_allocationSize);
int dst_offset = m.blockSize() + 1;
if (dst_offset > m_allocationSize) {
dst_offset = m_allocationSize / 2;
}
for (int i = 0; i < dst_offset; i++) {
m.setInt(p, i, 100 + i);
}
int numChars = (m_allocationSize - dst_offset) * 2;
char buf[] = new char[numChars];
for (int i = 0; i < numChars; i++) {
buf[i] = (char) ('a' + i);
}
m.setChars(p, dst_offset, buf, 0, buf.length);
// verify ints are correct using getInt
for (int i = 0; i < dst_offset; i++) {
assertEquals(100 + i, m.getInt(p, i));
}
for (int i = 0; i < numChars; i++) {
char e = buf[i];
int ii = i / 2 + dst_offset;
if (i % 2 == 0) {
char c = (char) m.getUpperShort(p, ii);
assertEquals(e, c);
} else {
char c = (char) m.getLowerShort(p, ii);
assertEquals(e, c);
}
}
m.free(p);
}
@Test
public void testGetCharsPartialFirstBlockDeep() {
int src_offset = m.blockSize() + 1;
if (src_offset > m_allocationSize) {
src_offset = m_allocationSize / 2;
}
int p = m.malloc(m_allocationSize);
int numChars = (m_allocationSize - src_offset) * 2;
char buf[] = new char[numChars];
for (int i = 0; i < numChars; i++) {
buf[i] = (char) ('a' + i);
}
for (int i = 0; i < src_offset; i++) {
m.setInt(p, i, 100 + i);
}
m.setChars(p, src_offset, buf, 0, buf.length);
char buf2[] = new char[numChars];
m.getChars(p, src_offset, buf2, 0, buf2.length);
assertArrayEquals(buf, buf2);
m.free(p);
}
@Test
public void testSetCharsPartialLastBlock() {
int p = m.malloc(m_allocationSize);
int numChars = (m_allocationSize - 1) * 2;
char buf[] = new char[numChars];
for (int i = 0; i < numChars; i++) {
buf[i] = (char) ('a' + i);
}
m.setInt(p, m_allocationSize - 1, -100);
m.setChars(p, 0, buf, 0, buf.length);
assertEquals(-100, m.getInt(p, m_allocationSize - 1));
for (int i = 0; i < numChars; i++) {
char e = buf[i];
int ii = i / 2;
if (i % 2 == 0) {
char c = (char) m.getUpperShort(p, ii);
assertEquals(e, c);
} else {
char c = (char) m.getLowerShort(p, ii);
assertEquals(e, c);
}
}
m.free(p);
}
@Test
public void testGetCharsPartialLastBlock() {
int p = m.malloc(m_allocationSize);
int numChars = (m_allocationSize - 1) * 2;
char buf[] = new char[numChars];
for (int i = 0; i < numChars; i++) {
buf[i] = (char) ('a' + i);
}
m.setInt(p, m_allocationSize - 1, -100);
m.setChars(p, 0, buf, 0, buf.length);
char buf2[] = new char[numChars];
m.getChars(p, 0, buf2, 0, numChars);
assertArrayEquals(buf, buf2);
m.free(p);
}
@Test
public void testSetGetCharsInLoop() {
try {
int maxBlocks = m.maxBlocks();
int blockSize = m.blockSize();
char buf[] = new char[(maxBlocks * 2) * blockSize];
for (int i = 0; i < buf.length; i++) {
buf[i] = (char) ('a' + i);
}
for (int numBlocks = 20; numBlocks < maxBlocks; numBlocks++) {
try {
int size = numBlocks * m.blockSize();
int p = m.malloc(size);
int numChars = size * 2;
m.setChars(p, 0, buf, 0, numChars);
char out[] = new char[numChars];
m.getChars(p, 0, out, 0, numChars);
for (int j = 0; j < size; j++) {
assertEquals("Char at index " + j, buf[j], out[j]);
}
m.free(p);
assertEquals(0, m.usedBlocks());
} catch (AssertionError e) {
System.out.println("Error, numBlocks = " + numBlocks);
throw e;
}
}
} catch (OutOfMemoryException e) {
// expected to happen in this test.
}
}
}