package org.edumips64.core;
import org.edumips64.BaseTest;
import org.edumips64.core.is.InstructionBuilder;
import org.edumips64.utils.io.LocalFileUtils;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ParserTest extends BaseTest {
private Parser parser;
private Memory memory;
@Before
public void setUp() throws Exception {
memory = new Memory();
CPU cpu = new CPU(memory, config);
SymbolTable symTab = new SymbolTable(memory);
IOManager iom = new IOManager(new LocalFileUtils(), memory);
Dinero dinero = new Dinero(memory);
InstructionBuilder instructionBuilder = new InstructionBuilder(memory, iom, cpu, dinero, config);
parser = new Parser(new LocalFileUtils(), symTab, memory, instructionBuilder);
}
/** Allows easier testing of .data section contents by adding the ".data" prefix and the "\n.code\nSYSCALL 0" suffix. */
private void ParseData(String dataSectionContents) throws Exception {
parser.doParsing(".data\n " + dataSectionContents + "\n.code\nSYSCALL 0");
}
/** Parse a double value */
private void ParseDouble(String doubleValue) throws Exception {
ParseData(".double " + doubleValue);
}
@Test
public void EscapeSequencesTest() throws Exception {
// Java has no raw srings, so all special characters need to be escaped twice.
String expected = "\\\"\t\n\0";
ParseData(".ascii \"\\\\\\\"\\t\\n\\0\"");
MemoryElement el = memory.getCellByIndex(0);
StringBuilder actual = new StringBuilder();
for (int i = 0; i < 5; ++i) {
actual.append((char) el.readByte(i));
}
assertEquals(actual.toString(), expected);
}
@Test(expected = ParserMultiException.class)
public void InvalidEscapeSequencesTest() throws Exception {
ParseData(".ascii \"\\x\"");
}
@Test(expected = ParserMultiException.class)
public void InvalidPlaceholder() throws Exception {
ParseData(".ascii \"%x\"");
}
@Test
public void ParseHex() throws Exception {
ParseData(".word 0x10");
MemoryElement el = memory.getCellByIndex(0);
assertEquals(el.readByte(0), 16);
}
@Test
public void Spaces() throws Exception {
// The user should be able to reserve space in small and larger amounts, specifying the amount in hexadecimal
// if they so desire.
ParseData(".space 0x10");
ParseData(".space 16");
ParseData(".space 8");
ParseData(".space 1");
}
@Test(expected = ParserMultiException.class)
public void NoSpaces() throws Exception {
ParseData(".space");
}
@Test(expected = ParserMultiException.class)
public void InvalidSpaces() throws Exception {
ParseData(".space yo");
}
@Test
public void SpecialFPTest() throws Exception {
ParseDouble("POSITIVEINFINITY"); // +Inf
ParseDouble("NEGATIVEINFINITY"); // -Inf
ParseDouble("POSITIVEZERO"); // +0
ParseDouble("NEGATIVEZERO"); // -0
ParseDouble("SNAN"); // Signaling NaN
ParseDouble("QNAN"); // Quiet NaN
}
@Test
public void FPNumbersTest() throws Exception {
ParseDouble("1.5"); // a positive number
ParseDouble("-1.5"); // a negative number
ParseDouble("1.7E308"); // a positive big number
ParseDouble("-1.7E308"); // a negative big number
ParseDouble("9.0E-324"); // a positive small number
ParseDouble("-9.0E-324"); // a negative small number
ParseDouble("-6.0E-324"); // a negative very small number
ParseDouble("6.0E-324"); // a positive very small number
}
@Test(expected = ParserMultiException.class)
public void FPOverflowPositiveNumberTest() throws Exception {
parser.getFCSR().setFPExceptions(CPU.FPExceptions.OVERFLOW, true);
ParseDouble("-1.8E308");
}
@Test(expected = ParserMultiException.class)
public void FPOverflowNegativeNumberTest() throws Exception {
parser.getFCSR().setFPExceptions(CPU.FPExceptions.OVERFLOW, true);
ParseDouble("4.95E324");
}
@Test
public void FPOverflowNoThrowOnDisabledExceptionsTest() throws Exception {
parser.getFCSR().setFPExceptions(CPU.FPExceptions.OVERFLOW, false);
ParseDouble("4.95E324");
}
/** Regression test for issue #95 */
@Test
public void CRLFParsingTest() throws Exception {
parser.doParsing(".data\r\n.double 8\r\n.code\r\nSYSCALL 0\r\n");
}
/** Regression tests for issue #1 */
@Test
public void NotOutOfBoundsTest() throws Exception {
// Test that all the values just before overflow are parsed correctly.
ParseData(".byte -128");
ParseData(".byte 127");
ParseData(".word16 -32768");
ParseData(".word16 32767");
ParseData(".word32 -2147483648");
ParseData(".word32 2147483647");
ParseData(".word -9223372036854775808");
ParseData(".word 9223372036854775807");
ParseData(".word64 -9223372036854775808");
ParseData(".word64 9223372036854775807");
}
@Test(expected = ParserMultiException.class)
public void OutOfBoundsByteTest() throws Exception {
ParseData(".byte 128");
}
@Test(expected = ParserMultiException.class)
public void NegativeOutOfBoundsByteTest() throws Exception {
ParseData(".byte -129");
}
@Test(expected = ParserMultiException.class)
public void OutOfBoundsHalfWordTest() throws Exception {
ParseData(".word16 32768");
}
@Test(expected = ParserMultiException.class)
public void NegativeOutOfBoundsHalfWordTest() throws Exception {
ParseData(".word16 -32769");
}
@Test(expected = ParserMultiException.class)
public void OutOfBoundsWordTest() throws Exception {
ParseData(".word32 2147483648");
}
@Test(expected = ParserMultiException.class)
public void NegativeOutOfBoundsWordTest() throws Exception {
ParseData(".word32 -2147483649");
}
@Test(expected = ParserMultiException.class)
public void OutOfBoundsDoubleWordTest() throws Exception {
ParseData(".word 9223372036854775808");
}
@Test(expected = ParserMultiException.class)
public void NegativeOutOfBoundsDoubleWordTest() throws Exception {
ParseData(".word -9223372036854775809");
}
}