package org.reasm.m68k;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nonnull;
import org.hamcrest.Matcher;
import org.junit.Test;
import org.reasm.*;
import org.reasm.source.SourceFile;
import org.reasm.testhelpers.UserSymbolMatcher;
import ca.fragag.Consumer;
import com.google.common.collect.ImmutableList;
/**
* Test class for {@link M68KArchitecture}.
*
* @author Francis Gagné
*/
public class M68KArchitectureTest {
@Nonnull
private static final UnsignedIntValue ONE_HUNDRED = new UnsignedIntValue(100);
@Nonnull
private static final UnsignedIntValue TWENTY = new UnsignedIntValue(20);
@Nonnull
private static final Consumer<AssemblyMessage> FAILING_ASSEMBLY_MESSAGE_CONSUMER = new Consumer<AssemblyMessage>() {
@Override
public void accept(AssemblyMessage message) {
fail();
}
};
@Nonnull
private static final Consumer<SymbolReference> FAILING_SYMBOL_REFERENCE_CONSUMER = new Consumer<SymbolReference>() {
@Override
public void accept(SymbolReference reference) {
fail();
}
};
@Nonnull
private static Assembly createAssembly1() {
final PredefinedSymbol fooSymbol = new PredefinedSymbol(SymbolContext.VALUE, "foo", SymbolType.CONSTANT, ONE_HUNDRED);
final PredefinedSymbol barSymbol = new PredefinedSymbol(SymbolContext.VALUE, "bar", SymbolType.CONSTANT, TWENTY);
final PredefinedSymbolTable predefinedSymbols = new PredefinedSymbolTable(Arrays.asList(fooSymbol, barSymbol));
final Configuration configuration = new Configuration(Environment.DEFAULT, new SourceFile("", ""), M68KArchitecture.MC68000)
.setPredefinedSymbols(predefinedSymbols);
final Assembly assembly = new Assembly(configuration);
return assembly;
}
/**
* Asserts that {@link M68KArchitecture#evaluateExpression(CharSequence, Assembly, Consumer, Consumer)} throws a
* {@link NullPointerException} when the <code>assembly</code> argument is <code>null</code>.
*/
@Test(expected = NullPointerException.class)
public void evaluateExpressionNullAssembly() {
M68KArchitecture.MC68000.evaluateExpression("2+2", null, null, null);
}
/**
* Asserts that {@link M68KArchitecture#evaluateExpression(CharSequence, Assembly, Consumer, Consumer)} throws a
* {@link NullPointerException} when the <code>expression</code> argument is <code>null</code>.
*/
@Test(expected = NullPointerException.class)
public void evaluateExpressionNullExpression() {
final Configuration configuration = new Configuration(Environment.DEFAULT, new SourceFile("", ""), M68KArchitecture.MC68000);
final Assembly assembly = new Assembly(configuration);
M68KArchitecture.MC68000.evaluateExpression(null, assembly, null, null);
}
/**
* Asserts that {@link M68KArchitecture#evaluateExpression(CharSequence, Assembly, Consumer, Consumer)} evaluates an expression.
*/
@Test
public void evaluateExpressionNullSymbolReferenceConsumer() {
final Assembly assembly = createAssembly1();
final Value value = M68KArchitecture.MC68000.evaluateExpression("foo+bar+3", assembly, null,
FAILING_ASSEMBLY_MESSAGE_CONSUMER);
assertThat(value, is((Value) new UnsignedIntValue(123)));
}
/**
* Asserts that {@link M68KArchitecture#evaluateExpression(CharSequence, Assembly, Consumer, Consumer)} correctly evaluates a
* simple expression.
*/
@Test
public void evaluateExpressionSimple() {
final Assembly assembly = createAssembly1();
final Value value = M68KArchitecture.MC68000.evaluateExpression("2+7*3", assembly, FAILING_SYMBOL_REFERENCE_CONSUMER,
FAILING_ASSEMBLY_MESSAGE_CONSUMER);
assertThat(value, is((Value) new UnsignedIntValue(23)));
}
/**
* Asserts that {@link M68KArchitecture#evaluateExpression(CharSequence, Assembly, Consumer, Consumer)} correctly evaluates an
* expression that contains symbol references.
*/
@Test
public void evaluateExpressionWithSymbols() {
final Assembly assembly = createAssembly1();
final List<SymbolReference> symbolReferences = new ArrayList<>();
final Consumer<SymbolReference> symbolReferenceConsumer = new Consumer<SymbolReference>() {
@Override
public void accept(SymbolReference symbolReference) {
symbolReferences.add(symbolReference);
}
};
final Value value = M68KArchitecture.MC68000.evaluateExpression("foo+bar+3", assembly, symbolReferenceConsumer,
FAILING_ASSEMBLY_MESSAGE_CONSUMER);
assertThat(value, is((Value) new UnsignedIntValue(123)));
assertThat(symbolReferences.size(), is(2));
SymbolReference symbolReference;
symbolReference = symbolReferences.get(0);
assertThat(symbolReference, is(notNullValue()));
assertThat(symbolReference.getContexts(), contains((Object) SymbolContext.VALUE));
assertThat(symbolReference.getName(), is("foo"));
assertThat(symbolReference.getSymbol(), is(notNullValue()));
assertThat(symbolReference.getSymbol(), is(instanceOf(UserSymbol.class)));
assertThat((UserSymbol) symbolReference.getSymbol(), is(new UserSymbolMatcher<>(SymbolContext.VALUE, "foo",
SymbolType.CONSTANT, ONE_HUNDRED)));
symbolReference = symbolReferences.get(1);
assertThat(symbolReference, is(notNullValue()));
assertThat(symbolReference.getContexts(), contains((Object) SymbolContext.VALUE));
assertThat(symbolReference.getName(), is("bar"));
assertThat(symbolReference.getSymbol(), is(notNullValue()));
assertThat(symbolReference.getSymbol(), is(instanceOf(UserSymbol.class)));
assertThat((UserSymbol) symbolReference.getSymbol(), is(new UserSymbolMatcher<>(SymbolContext.VALUE, "bar",
SymbolType.CONSTANT, TWENTY)));
}
/**
* Asserts that {@link M68KArchitecture#isLocalName(String)} returns <code>true</code> when the specified symbol name represents
* a local symbol or <code>false</code> when it doesn't.
*/
@Test
public void isLocalName() {
assertThat(M68KArchitecture.isLocalName(""), is(false));
assertThat(M68KArchitecture.isLocalName("A"), is(false));
assertThat(M68KArchitecture.isLocalName("@"), is(true));
assertThat(M68KArchitecture.isLocalName("@A"), is(true));
}
/**
* Asserts that {@link M68KArchitecture#M68KArchitecture(InstructionSet, String[])} correctly initializes an
* {@link M68KArchitecture}.
*/
@Test
public void m68kArchitecture() {
assertThat(M68KArchitecture.MC68000.getInstructionSet(), is(sameInstance(InstructionSet.MC68000)));
assertThat(M68KArchitecture.MC68000.getNames(), containsInAnyOrder(ImmutableList.<Matcher<? super String>> of(
equalTo("68000"), equalTo("MC68000"), equalTo("68008"), equalTo("MC68008"))));
}
}