/*
Copyright 2014 Google Inc. All Rights Reserved.
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.google.security.zynamics.binnavi.disassembly.Modules;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.google.security.zynamics.binnavi.Common.CommonTestObjects;
import com.google.security.zynamics.binnavi.Database.Exceptions.CouldntDeleteException;
import com.google.security.zynamics.binnavi.Database.Exceptions.CouldntLoadDataException;
import com.google.security.zynamics.binnavi.Database.Exceptions.CouldntSaveDataException;
import com.google.security.zynamics.binnavi.Database.Exceptions.LoadCancelledException;
import com.google.security.zynamics.binnavi.Database.Interfaces.SQLProvider;
import com.google.security.zynamics.binnavi.Database.MockClasses.MockDatabase;
import com.google.security.zynamics.binnavi.Database.MockClasses.MockSqlProvider;
import com.google.security.zynamics.binnavi.Exceptions.MaybeNullException;
import com.google.security.zynamics.binnavi.Tagging.CTag;
import com.google.security.zynamics.binnavi.debug.debugger.DebuggerTemplate;
import com.google.security.zynamics.binnavi.disassembly.COperandTree;
import com.google.security.zynamics.binnavi.disassembly.COperandTreeNode;
import com.google.security.zynamics.binnavi.disassembly.CStringReplacement;
import com.google.security.zynamics.binnavi.disassembly.IDatabaseObject;
import com.google.security.zynamics.binnavi.disassembly.INaviFunction;
import com.google.security.zynamics.binnavi.disassembly.MockCreator;
import com.google.security.zynamics.binnavi.disassembly.UnrelocatedAddress;
import com.google.security.zynamics.binnavi.disassembly.views.CView;
import com.google.security.zynamics.binnavi.disassembly.views.CViewFilter;
import com.google.security.zynamics.binnavi.disassembly.views.INaviView;
import com.google.security.zynamics.zylib.disassembly.CAddress;
import com.google.security.zynamics.zylib.disassembly.ExpressionType;
import com.google.security.zynamics.zylib.disassembly.GraphType;
import com.google.security.zynamics.zylib.disassembly.IAddress;
import com.google.security.zynamics.zylib.disassembly.IReference;
import com.google.security.zynamics.zylib.disassembly.MockAddress;
import com.google.security.zynamics.zylib.disassembly.ViewType;
import com.google.security.zynamics.zylib.types.lists.FilledList;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@RunWith(JUnit4.class)
public final class CModuleTest {
private final SQLProvider m_sql = new MockSqlProvider();
private MockModuleListener m_listener;
private CModule m_module;
private final String md5 = CommonTestObjects.MD5;
private final String sha1 = CommonTestObjects.SHA1;
@Before
public void setUp() {
m_listener = new MockModuleListener();
m_module = MockCreator.createModule(m_sql);
m_module.addListener(m_listener);
}
@Test
public void test_C_Constructors() {
try {
new CModule(0, "Name", "Comment", new Date(), new Date(), md5, sha1, 0, 0, new CAddress(0),
new CAddress(0), null, null, Integer.MAX_VALUE, false, new MockSqlProvider());
fail();
} catch (final IllegalArgumentException exception) {
}
try {
new CModule(1, null, "Comment", new Date(), new Date(), md5, sha1, 0, 0, new CAddress(0),
new CAddress(0), null, null, Integer.MAX_VALUE, false, new MockSqlProvider());
fail();
} catch (final NullPointerException exception) {
}
try {
new CModule(1, "Name", null, new Date(), new Date(), md5, sha1, 0, 0, new CAddress(0),
new CAddress(0), null, null, Integer.MAX_VALUE, false, new MockSqlProvider());
fail();
} catch (final NullPointerException exception) {
}
try {
new CModule(1, "Name", "Comment", null, new Date(), md5, sha1, 0, 0, new CAddress(0),
new CAddress(0), null, null, Integer.MAX_VALUE, false, new MockSqlProvider());
fail();
} catch (final NullPointerException exception) {
}
try {
new CModule(1, "Name", "Comment", new Date(), null, md5, sha1, 0, 0, new CAddress(0),
new CAddress(0), null, null, Integer.MAX_VALUE, false, new MockSqlProvider());
fail();
} catch (final NullPointerException exception) {
}
try {
new CModule(1, "Name", "Comment", new Date(), new Date(), null, sha1, 0, 0, new CAddress(0),
new CAddress(0), null, null, Integer.MAX_VALUE, false, new MockSqlProvider());
fail();
} catch (final NullPointerException exception) {
}
try {
new CModule(1, "Name", "Comment", new Date(), new Date(),
"123456781234567812345678123456789", sha1, 0, 0, new CAddress(0), new CAddress(0), null,
null, Integer.MAX_VALUE, false, new MockSqlProvider());
fail();
} catch (final IllegalArgumentException exception) {
}
try {
new CModule(1, "Name", "Comment", new Date(), new Date(), md5, null, 0, 0, new CAddress(0),
new CAddress(0), null, null, Integer.MAX_VALUE, false, new MockSqlProvider());
fail();
} catch (final NullPointerException exception) {
}
try {
new CModule(1, "Name", "Comment", new Date(), new Date(), md5,
"12345678123456781234567812345678123456789", 0, 0, new CAddress(0), new CAddress(0),
null, null, Integer.MAX_VALUE, false, new MockSqlProvider());
fail();
} catch (final IllegalArgumentException exception) {
}
try {
new CModule(1, "Name", "Comment", new Date(), new Date(), md5, sha1, -1, 0, new CAddress(0),
new CAddress(0), null, null, Integer.MAX_VALUE, false, new MockSqlProvider());
fail();
} catch (final IllegalArgumentException exception) {
}
try {
new CModule(1, "Name", "Comment", new Date(), new Date(), md5, sha1, 0, -1, new CAddress(0),
new CAddress(0), null, null, Integer.MAX_VALUE, false, new MockSqlProvider());
fail();
} catch (final IllegalArgumentException exception) {
}
try {
new CModule(1, "Name", "Comment", new Date(), new Date(), md5, sha1, 0, 0, null,
new CAddress(0), null, null, Integer.MAX_VALUE, false, new MockSqlProvider());
fail();
} catch (final NullPointerException exception) {
}
try {
new CModule(1, "Name", "Comment", new Date(), new Date(), md5, sha1, 0, 0, new CAddress(0),
null, null, null, Integer.MAX_VALUE, false, new MockSqlProvider());
fail();
} catch (final NullPointerException exception) {
}
try {
new CModule(1, "Name", "Comment", new Date(), new Date(), md5, sha1, 0, 0, new CAddress(0),
new CAddress(0), null, null, Integer.MAX_VALUE, false, null);
fail();
} catch (final NullPointerException exception) {
}
final MockSqlProvider sql = new MockSqlProvider();
final CModule module =
new CModule(123, "Name", "Comment", new Date(), new Date(), md5, sha1, 55, 66,
new CAddress(0x555), new CAddress(0x666), new DebuggerTemplate(1, "Mock Debugger",
"localhaus", 88, sql), null, Integer.MAX_VALUE, false, sql);
assertEquals(123, module.getConfiguration().getId());
assertEquals("Name", module.getConfiguration().getName());
assertEquals("Comment", module.getConfiguration().getDescription());
assertEquals(md5, module.getConfiguration().getMD5());
assertEquals(sha1, module.getConfiguration().getSha1());
assertEquals(55, module.getFunctionCount());
assertEquals(66, module.getCustomViewCount());
assertEquals("00000555", module.getConfiguration().getFileBase().toHexString());
assertEquals("00000666", module.getConfiguration().getImageBase().toHexString());
assertEquals("Mock Debugger", module.getConfiguration().getDebuggerTemplate().getName());
assertNotNull(module.getConfiguration().getDebugger());
assertTrue(module.inSameDatabase(sql));
}
@Test
public void test_C_getFunction() throws CouldntLoadDataException, MaybeNullException,
LoadCancelledException {
try {
m_module.getContent().getFunctionContainer().getFunction((IAddress) null);
fail();
} catch (final NullPointerException exception) {
}
m_module.load();
for (final INaviFunction function : m_module.getContent().getFunctionContainer().getFunctions()) {
assertEquals(function,
m_module.getContent().getFunctionContainer().getFunction(function.getAddress()));
assertEquals(function,
m_module.getContent().getFunctionContainer().getFunction(function.getName()));
}
}
@Test
public void test_C_getFunction2() throws CouldntLoadDataException, LoadCancelledException {
try {
m_module.getContent().getViewContainer().getFunction((INaviView) null);
fail();
} catch (final NullPointerException exception) {
}
m_module.load();
int counter = 0;
final List<INaviFunction> functions =
m_module.getContent().getFunctionContainer().getFunctions();
for (final INaviView view : m_module.getContent().getViewContainer().getNativeFlowgraphViews()) {
assertEquals(functions.get(counter),
m_module.getContent().getViewContainer().getFunction(view));
counter++;
}
}
@Test
public void test_C_getterFunctions() throws CouldntLoadDataException, LoadCancelledException {
assertEquals(66, m_module.getCustomViewCount());
assertEquals(55, m_module.getFunctionCount());
assertEquals(122, m_module.getViewCount());
m_module.load();
assertEquals(0, m_module.getCustomViewCount());
assertEquals(1, m_module.getFunctionCount());
assertEquals(2, m_module.getViewCount());
}
@Test
public void testAddresses() throws CouldntSaveDataException {
assertEquals("00000555", m_module.getConfiguration().getFileBase().toHexString());
m_module.getConfiguration().setFileBase(new CAddress(0x02000000));
// Check listener events
assertEquals("changedFileBase=02000000/", m_listener.eventList);
// Check module
assertEquals("02000000", m_module.getConfiguration().getFileBase().toHexString());
m_module.getConfiguration().setFileBase(new CAddress(0x02000000));
// Check listener events
assertEquals("changedFileBase=02000000/", m_listener.eventList);
// ------------------------------------------ Image Base
// -------------------------------------------------
assertEquals("00000666", m_module.getConfiguration().getImageBase().toHexString());
m_module.getConfiguration().setImageBase(new CAddress(0xFFFFFFFFL));
// Check listener events
assertEquals("changedFileBase=02000000/changedImageBase=FFFFFFFF/", m_listener.eventList);
// Check module
assertEquals("FFFFFFFF", m_module.getConfiguration().getImageBase().toHexString());
m_module.getConfiguration().setImageBase(new CAddress(0xFFFFFFFFL));
// Check listener events
assertEquals("changedFileBase=02000000/changedImageBase=FFFFFFFF/", m_listener.eventList);
}
@Test
public void testClose() throws CouldntLoadDataException, LoadCancelledException {
m_module.load();
m_listener.canClose = false;
assertFalse(m_module.close());
m_listener.canClose = true;
assertTrue(m_module.close());
try {
m_module.close();
fail();
} catch (final IllegalStateException e) {
}
}
@Test
public void testCreateInstruction() throws CouldntLoadDataException, LoadCancelledException {
m_module.load();
final byte[] data = {(byte) 0x90};
assertNotNull(m_module.createInstruction(new MockAddress(), "add",
new ArrayList<COperandTree>(), data, "ARM"));
}
@Test
public void testCreateOperand() throws CouldntLoadDataException, LoadCancelledException {
m_module.load();
final List<IReference> references = new ArrayList<IReference>();
final COperandTreeNode node =
new COperandTreeNode(1, 2, "2", new CStringReplacement("bar"), references, m_sql,
m_module.getTypeManager(), m_module.getContent().getTypeInstanceContainer());
assertNotNull(m_module.createOperand(node));
}
@Test
public void testCreateOperandExpression() throws CouldntLoadDataException, LoadCancelledException {
m_module.load();
assertNotNull(m_module.createOperandExpression("foo", ExpressionType.SYMBOL));
}
@Test
public void testDebugger() throws CouldntSaveDataException {
assertNull(m_module.getConfiguration().getDebugger());
assertNull(m_module.getConfiguration().getDebuggerTemplate());
final DebuggerTemplate template = MockCreator.createDebuggerTemplate(m_sql);
m_module.getConfiguration().setDebuggerTemplate(template);
assertNotNull(m_module.getConfiguration().getDebugger());
assertEquals(template, m_module.getConfiguration().getDebuggerTemplate());
m_module.getConfiguration().setDebuggerTemplate(null);
assertNull(m_module.getConfiguration().getDebugger());
assertNull(m_module.getConfiguration().getDebuggerTemplate());
}
@Test
public void testGetData() throws CouldntLoadDataException, LoadCancelledException {
m_module.load();
assertNotNull(m_module.getData());
}
@Test
public void testGetUserViews() throws CouldntLoadDataException, LoadCancelledException {
m_module.load();
assertNotNull(m_module.getUserViews());
}
@Test
public void testGetViewsWithAddresses() throws CouldntLoadDataException, LoadCancelledException {
final FilledList<UnrelocatedAddress> addresses = new FilledList<UnrelocatedAddress>();
addresses.add(new UnrelocatedAddress(new CAddress(12345678)));
m_module.load();
assertNotNull(m_module.getViewsWithAddresses(addresses, true));
}
@Test
public void testInitialize() throws CouldntSaveDataException {
m_module.setInitialized();
assertTrue(m_module.isInitialized());
m_module.initialize();
final MockModule module = new MockModule();
assertFalse(module.isInitialized());
module.initialize();
}
@Test
public void testInSameDatabase() throws CouldntLoadDataException, LoadCancelledException {
m_module.load();
assertFalse(m_module.inSameDatabase(new MockSqlProvider()));
assertTrue(m_module.inSameDatabase(m_sql));
try {
m_module.inSameDatabase((SQLProvider) null);
fail();
} catch (final NullPointerException e) {
}
final MockDatabase database = new MockDatabase();
assertFalse(m_module.inSameDatabase(database));
try {
m_module.inSameDatabase((IDatabaseObject) null);
fail();
} catch (final NullPointerException e) {
}
}
@Test
public void testIsStared() throws CouldntLoadDataException, LoadCancelledException {
m_module.load();
assertFalse(m_module.isStared());
}
@Test
public void testMiscReaders() throws CouldntLoadDataException, LoadCancelledException {
m_module.load();
m_module.loadData();
m_module.readSetting("foo");
m_module.isLoading();
m_module.isInitialized();
m_module.isInitializing();
m_module.isLoading();
}
@Test
public void testRemoveListener() throws CouldntLoadDataException, LoadCancelledException {
m_module.load();
m_module.removeListener(m_listener);
}
@Test
public void testSaveData() throws CouldntLoadDataException, LoadCancelledException,
CouldntSaveDataException {
m_module.load();
m_module.saveData();
}
@Test
public void testSetData() throws CouldntLoadDataException, LoadCancelledException {
m_module.load();
final byte[] bytes = {(byte) 0xFF};
m_module.setData(bytes);
try {
m_module.setData(null);
fail();
} catch (final NullPointerException e) {
}
}
@Test
public void testSetDescription() throws CouldntSaveDataException {
try {
m_module.getConfiguration().setDescription(null);
fail();
} catch (final NullPointerException exception) {
}
assertEquals("Mock Comment", m_module.getConfiguration().getDescription());
m_module.getConfiguration().setDescription("Test Description");
// Check listener events
assertEquals("changedDescription=Test Description/", m_listener.eventList);
// Check module
assertEquals("Test Description", m_module.getConfiguration().getDescription());
m_module.getConfiguration().setDescription("Imported by ida2sql from BinNavi");
assertEquals(
"changedDescription=Test Description/changedDescription=Imported by ida2sql from BinNavi/",
m_listener.eventList);
m_module.getConfiguration().setDescription("Imported by ida2sql from BinNavi");
assertEquals(
"changedDescription=Test Description/changedDescription=Imported by ida2sql from BinNavi/",
m_listener.eventList);
assertEquals("Imported by ida2sql from BinNavi", m_module.getConfiguration().getDescription());
}
@Test
public void testSetName() throws CouldntSaveDataException {
try {
m_module.getConfiguration().setName(null);
fail();
} catch (final NullPointerException exception) {
}
assertEquals("Mock Name", m_module.getConfiguration().getName());
m_module.getConfiguration().setName("Test Name");
// Check listener events
assertEquals("changedName=Test Name/", m_listener.eventList);
// Check module
assertEquals("Test Name", m_module.getConfiguration().getName());
m_module.getConfiguration().setName("NOTEPAD.EXE");
assertEquals("changedName=Test Name/changedName=NOTEPAD.EXE/", m_listener.eventList);
m_module.getConfiguration().setName("NOTEPAD.EXE");
assertEquals("changedName=Test Name/changedName=NOTEPAD.EXE/", m_listener.eventList);
assertEquals("NOTEPAD.EXE", m_module.getConfiguration().getName());
}
@Test
public void testTags() throws CouldntSaveDataException, CouldntLoadDataException,
LoadCancelledException {
final CTag newTag = MockCreator.createViewTag(m_sql);
m_module.load();
m_module.getContent().getViewContainer().createView("Foo", "Bar");
m_module.getContent().getViewContainer().createView("Foo", "Bar");
m_module.getContent().getViewContainer().getViews().get(0).getConfiguration().tagView(newTag);
m_module.getContent().getViewContainer().getViews().get(1).getConfiguration().tagView(newTag);
assertEquals(m_module.getContent().getViewContainer().getViews().get(0), CViewFilter
.getTaggedViews(m_module.getContent().getViewContainer().getViews()).get(0).first());
assertEquals(m_module.getContent().getViewContainer().getViews().get(1), CViewFilter
.getTaggedViews(m_module.getContent().getViewContainer().getViews()).get(1).first());
assertEquals(2,
CViewFilter.getTaggedViews(m_module.getContent().getViewContainer().getViews(), newTag)
.size());
}
@Test
public void testToString() throws CouldntLoadDataException, LoadCancelledException {
m_module.load();
m_module.toString();
}
@Test
public void testViews() throws CouldntLoadDataException, CouldntDeleteException,
LoadCancelledException {
// ---------------------------------------------- CREATE VIEWS
// -----------------------------------------------
try {
m_module.getContent().getViewContainer().createView(null, "New Trace Description");
fail();
} catch (final NullPointerException exception) {
}
try {
m_module.getContent().getViewContainer().createView("New Trace", null);
fail();
} catch (final NullPointerException exception) {
}
try {
m_module.getContent().getViewContainer().createView("New View", "New Trace Description");
fail();
} catch (final NullPointerException exception) {
}
m_module.load();
final CView newView =
m_module.getContent().getViewContainer().createView("New View", "New View Description");
// Check listener events
assertEquals("addedView/", m_listener.eventList);
assertEquals(newView, m_listener.addedViews.get(0));
// Check module
assertEquals(1, m_module.getCustomViewCount());
assertEquals(1, m_module.getFunctionCount());
assertEquals(3, m_module.getViewCount());
// Check view
assertTrue(newView.isLoaded());
assertEquals("New View", newView.getName());
assertEquals("New View Description", newView.getConfiguration().getDescription());
assertEquals(0, newView.getNodeCount());
assertEquals(0, newView.getEdgeCount());
assertEquals(ViewType.NonNative, newView.getType());
assertEquals(GraphType.MIXED_GRAPH, newView.getGraphType());
// ---------------------------------------------- DELETE VIEWS
// --------------------------------------------------
try {
m_module.getContent().getViewContainer().deleteView(null);
fail();
} catch (final NullPointerException exception) {
}
// Check module
assertEquals(1, m_module.getCustomViewCount());
assertEquals(1, m_module.getFunctionCount());
assertEquals(3, m_module.getViewCount());
m_module.getContent().getViewContainer().deleteView(newView);
// Check listener events
assertEquals("addedView/deletedView/", m_listener.eventList);
assertEquals(newView, m_listener.deletedViews.get(0));
// Check module
assertEquals(0, m_module.getCustomViewCount());
assertEquals(1, m_module.getFunctionCount());
assertEquals(2, m_module.getViewCount());
}
@Test
public void testWriteSettings() throws CouldntLoadDataException, LoadCancelledException,
CouldntSaveDataException {
m_module.load();
m_module.writeSetting("foo", "bar");
}
}