/******************************************************************************* * Copyright (c) 2007, 2010 Ericsson and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Ericsson AB - Initial Implementation *******************************************************************************/ package org.eclipse.cdt.tests.dsf.gdb.tests; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.eclipse.cdt.core.IAddress; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.IExpressions; import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext; import org.eclipse.cdt.dsf.debug.service.IFormattedValues; import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext; import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData; import org.eclipse.cdt.dsf.debug.service.IMemory; import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryChangedEvent; import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext; import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType; import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; import org.eclipse.cdt.dsf.mi.service.MIRunControl; import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent; import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.tests.dsf.gdb.framework.AsyncCompletionWaitor; import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; import org.eclipse.cdt.tests.dsf.gdb.framework.BaseTestCase; import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil; import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin; import org.eclipse.cdt.utils.Addr64; import org.eclipse.debug.core.model.MemoryByte; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; /* * This is the Memory Service test suite. * * It is meant to be a regression suite to be executed automatically against * the DSF nightly builds. * * It is also meant to be augmented with a proper test case(s) every time a * feature is added or in the event (unlikely :-) that a bug is found in the * Memory Service. * * Refer to the JUnit4 documentation for an explanation of the annotations. */ @RunWith(BackgroundRunner.class) public class MIMemoryTest extends BaseTestCase { private final AsyncCompletionWaitor fWait = new AsyncCompletionWaitor(); private DsfSession fSession; private DsfServicesTracker fServicesTracker; private IMemoryDMContext fMemoryDmc; private MIRunControl fRunControl; private IMemory fMemoryService; private IExpressions fExpressionService; // Keeps track of the MemoryChangedEvents private final int BLOCK_SIZE = 256; private IAddress fBaseAddress; private Integer fMemoryChangedEventCount = new Integer(0); private boolean[] fMemoryAddressesChanged = new boolean[BLOCK_SIZE]; // ======================================================================== // Housekeeping stuff // ======================================================================== @BeforeClass public static void testSuiteInitialization() { // Select the binary to run the tests against setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, "data/launch/bin/MemoryTestApp.exe"); } @AfterClass public static void testSuiteCleanup() { } @Before public void testCaseInitialization() throws Throwable { fSession = getGDBLaunch().getSession(); fMemoryDmc = (IMemoryDMContext)SyncUtil.getContainerContext(); assert(fMemoryDmc != null); Runnable runnable = new Runnable() { public void run() { // Get a reference to the memory service fServicesTracker = new DsfServicesTracker(TestsPlugin.getBundleContext(), fSession.getId()); assert(fServicesTracker != null); fRunControl = fServicesTracker.getService(MIRunControl.class); assert(fRunControl != null); fMemoryService = fServicesTracker.getService(IMemory.class); assert(fMemoryService != null); fExpressionService = fServicesTracker.getService(IExpressions.class); assert(fExpressionService != null); fSession.addServiceEventListener(MIMemoryTest.this, null); fBaseAddress = null; clearEventCounters(); } }; fSession.getExecutor().submit(runnable).get(); } @After public void testCaseCleanup() throws Exception { // Clear the references (not strictly necessary) Runnable runnable = new Runnable() { public void run() { fSession.removeServiceEventListener(MIMemoryTest.this); } }; fSession.getExecutor().submit(runnable).get(); fBaseAddress = null; fExpressionService = null; fMemoryService = null; fRunControl = null; fServicesTracker.dispose(); fServicesTracker = null; clearEventCounters(); } // ======================================================================== // Helper Functions // ======================================================================== /* ------------------------------------------------------------------------ * eventDispatched * ------------------------------------------------------------------------ * Processes MemoryChangedEvents. * First checks if the memory block base address was set so the individual * test can control if it wants to verify the event(s). * ------------------------------------------------------------------------ * @param e The MemoryChangedEvent * ------------------------------------------------------------------------ */ @DsfServiceEventHandler public void eventDispatched(IMemoryChangedEvent e) { synchronized(fMemoryChangedEventCount) { fMemoryChangedEventCount++; } IAddress[] addresses = e.getAddresses(); for (int i = 0; i < addresses.length; i++) { int offset = Math.abs(addresses[i].distanceTo(fBaseAddress).intValue()); if (offset < BLOCK_SIZE) synchronized(fMemoryAddressesChanged) { fMemoryAddressesChanged[offset] = true; } } } // Clears the counters private void clearEventCounters() { synchronized(fMemoryChangedEventCount) { fMemoryChangedEventCount = 0; } synchronized(fMemoryAddressesChanged) { for (int i = 0; i < BLOCK_SIZE; i++) fMemoryAddressesChanged[i] = false; } } // Returns the total number of events received private int getEventCount() { int count; synchronized(fMemoryChangedEventCount) { count = fMemoryChangedEventCount; } return count; } // Returns the number of distinct addresses reported private int getAddressCount() { int count = 0; synchronized(fMemoryAddressesChanged) { for (int i = 0; i < BLOCK_SIZE; i++) if (fMemoryAddressesChanged[i]) count++; } return count; } /* ------------------------------------------------------------------------ * evaluateExpression * ------------------------------------------------------------------------ * Invokes the ExpressionService to evaluate an expression. In theory, we * shouldn't rely on another service to test this one but we need a way to * access a variable from the test application in order verify that the * memory operations (read/write) are working properly. * ------------------------------------------------------------------------ * @param expression Expression to resolve * @return Resolved expression * @throws InterruptedException * ------------------------------------------------------------------------ */ private IAddress evaluateExpression(IDMContext ctx, String expression) throws Throwable { // Create the expression and format contexts final IExpressionDMContext expressionDMC = SyncUtil.createExpression(ctx, expression); final FormattedValueDMContext formattedValueDMC = SyncUtil.getFormattedValue(fExpressionService, expressionDMC, IFormattedValues.HEX_FORMAT); // Create the DataRequestMonitor which will store the operation result in the wait object final DataRequestMonitor<FormattedValueDMData> drm = new DataRequestMonitor<FormattedValueDMData>(fSession.getExecutor(), null) { @Override protected void handleCompleted() { if (isSuccess()) { fWait.setReturnInfo(getData()); } fWait.waitFinished(getStatus()); } }; // Evaluate the expression (asynchronously) fSession.getExecutor().submit(new Runnable() { public void run() { fExpressionService.getFormattedExpressionValue(formattedValueDMC, drm); } }); // Wait for completion fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); // Return the string formatted by the back-end String result = ""; Object returnInfo = fWait.getReturnInfo(); if (returnInfo instanceof FormattedValueDMData) result = ((FormattedValueDMData) returnInfo).getFormattedValue(); return new Addr64(result); } /* ------------------------------------------------------------------------ * readMemory * ------------------------------------------------------------------------ * Issues a memory read request. The result is stored in fWait. * ------------------------------------------------------------------------ * Typical usage: * getMemory(dmc, address, offset, count); * fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); * assertTrue(fWait.getMessage(), fWait.isOK()); * ------------------------------------------------------------------------ * @param dmc the data model context * @param address the memory block address * @param offset the offset in the buffer * @param count the number of bytes to read * @throws InterruptedException * ------------------------------------------------------------------------ */ private void readMemory(final IMemoryDMContext dmc, final IAddress address, final long offset, final int word_size, final int count) throws InterruptedException { // Set the Data Request Monitor final DataRequestMonitor<MemoryByte[]> drm = new DataRequestMonitor<MemoryByte[]>(fSession.getExecutor(), null) { @Override protected void handleCompleted() { if (isSuccess()) { fWait.setReturnInfo(getData()); } fWait.waitFinished(getStatus()); } }; // Issue the get memory request fSession.getExecutor().submit(new Runnable() { public void run() { fMemoryService.getMemory(dmc, address, offset, word_size, count, drm); } }); } /* ------------------------------------------------------------------------ * readMemoryByteAtOffset * ------------------------------------------------------------------------ * Issues a memory read request. The result is stored in fWait. * ------------------------------------------------------------------------ * Typical usage: * getMemory(dmc, address, offset, count); * fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); * assertTrue(fWait.getMessage(), fWait.isOK()); * ------------------------------------------------------------------------ * @param dmc the data model context * @param address the memory block address * @param offset the offset in the buffer * @param count the number of bytes to read * @param result the expected byte * @throws InterruptedException * ------------------------------------------------------------------------ */ private void readMemoryByteAtOffset(final IMemoryDMContext dmc, final IAddress address, final long offset, final int word_size, final int count, final MemoryByte[] result) throws InterruptedException { // Set the Data Request Monitor final DataRequestMonitor<MemoryByte[]> drm = new DataRequestMonitor<MemoryByte[]>(fSession.getExecutor(), null) { @Override protected void handleCompleted() { if (isSuccess()) { result[(int) offset] = getData()[0]; } fWait.waitFinished(getStatus()); } }; // Issue the get memory request fSession.getExecutor().submit(new Runnable() { public void run() { fMemoryService.getMemory(dmc, address, offset, word_size, count, drm); } }); } /* ------------------------------------------------------------------------ * writeMemory * ------------------------------------------------------------------------ * Issues a memory write request. * ------------------------------------------------------------------------ * Typical usage: * writeMemory(dmc, address, offset, count, buffer); * fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); * assertTrue(fWait.getMessage(), fWait.isOK()); * ------------------------------------------------------------------------ * @param dmc the data model context * @param address the memory block address (could be an expression) * @param offset the offset from address * @param count the number of bytes to write * @param buffer the byte buffer to write from * @throws InterruptedException * ------------------------------------------------------------------------ */ private void writeMemory(final IMemoryDMContext dmc, final IAddress address, final long offset, final int word_size, final int count, final byte[] buffer) throws InterruptedException { // Set the Data Request Monitor final RequestMonitor rm = new RequestMonitor(fSession.getExecutor(), null) { @Override protected void handleCompleted() { fWait.waitFinished(getStatus()); } }; // Issue the get memory request fSession.getExecutor().submit(new Runnable() { public void run() { fMemoryService.setMemory(dmc, address, offset, word_size, count, buffer, rm); } }); } /* ------------------------------------------------------------------------ * fillMemory * ------------------------------------------------------------------------ * Issues a memory write request. * ------------------------------------------------------------------------ * Typical usage: * writeMemory(dmc, address, offset, count, buffer); * fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); * assertTrue(fWait.getMessage(), fWait.isOK()); * ------------------------------------------------------------------------ * @param dmc the data model context * @param address the memory block address (could be an expression) * @param offset the offset from address * @param count the number of bytes to write * @param pattern the byte pattern to write * @throws InterruptedException * ------------------------------------------------------------------------ */ private void fillMemory(final IMemoryDMContext dmc, final IAddress address, final long offset, final int word_size, final int count, final byte[] pattern) throws InterruptedException { // Set the Data Request Monitor final RequestMonitor rm = new RequestMonitor(fSession.getExecutor(), null) { @Override protected void handleCompleted() { fWait.waitFinished(getStatus()); } }; // Issue the fill memory request fSession.getExecutor().submit(new Runnable() { public void run() { fMemoryService.fillMemory(dmc, address, offset, word_size, count, pattern, rm); } }); } // ======================================================================== // Test Cases // ------------------------------------------------------------------------ // Templates: // ------------------------------------------------------------------------ // @ Test // public void basicTest() { // // First test to run // assertTrue("", true); // } // ------------------------------------------------------------------------ // @ Test(timeout=5000) // public void timeoutTest() { // // Second test to run, which will timeout if not finished on time // assertTrue("", true); // } // ------------------------------------------------------------------------ // @ Test(expected=FileNotFoundException.class) // public void exceptionTest() throws FileNotFoundException { // // Third test to run which expects an exception // throw new FileNotFoundException("Just testing"); // } // ======================================================================== /////////////////////////////////////////////////////////////////////////// // getMemory tests /////////////////////////////////////////////////////////////////////////// // ------------------------------------------------------------------------ // readWithNullContext // Test that a null context is caught and generates an error // ------------------------------------------------------------------------ @Test public void readWithNullContext() throws Throwable { // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters IMemoryDMContext dmc = null; long offset = 0; int word_size = 1; int count = 1; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Perform the test String expected = "Unknown context type"; fWait.waitReset(); readMemory(dmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // readWithInvalidAddress // Test that an invalid address is caught and generates an error // ------------------------------------------------------------------------ @Test public void readWithInvalidAddress() throws Throwable { // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); SyncUtil.step(StepType.STEP_RETURN); // Setup call parameters long offset = 0; int word_size = 1; int count = 1; fBaseAddress = new Addr64("0"); // Perform the test fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); // Ensure that we receive a block of invalid memory bytes assertTrue(fWait.getMessage(), fWait.isOK()); MemoryByte[] buffer = (MemoryByte[]) fWait.getReturnInfo(); assertTrue("Wrong value: expected '-1, 0', received '" + buffer[0].getValue() + ", " + buffer[0].getFlags() + "'", (buffer[0].getValue() == (byte) 0) && (buffer[0].getFlags() == (byte) 0)); // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // readWithInvalidWordSize // Test that an invalid word size is caught and generates an error // ------------------------------------------------------------------------ @Test public void readWithInvalidWordSize() throws Throwable { // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int count = -1; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Perform the test String expected = "Word size not supported (!= 1)"; fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, 0, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, 2, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // readWithInvalidCount // Test that an invalid count is caught and generates an error // ------------------------------------------------------------------------ @Test public void readWithInvalidCount() throws Throwable { // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int word_size = 1; int count = -1; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Perform the test String expected = "Invalid word count (< 0)"; fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // readCharVaryingBaseAddress // Test the reading of individual bytes by varying the base address // ------------------------------------------------------------------------ @Test public void readCharVaryingBaseAddress() throws Throwable { // Run to the point where the variable is zeroed SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int word_size = 1; int count = 1; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Verify that all bytes are '0' for (int i = 0; i < BLOCK_SIZE; i++) { IAddress address = fBaseAddress.add(i); fWait.waitReset(); readMemory(fMemoryDmc, address, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); MemoryByte[] buffer = (MemoryByte[]) fWait.getReturnInfo(); assertTrue("Wrong value read at offset " + i + ": expected '" + 0 + "', received '" + buffer[0].getValue() + "'", (buffer[0].getValue() == (byte) 0)); } // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:setBlocks", true); SyncUtil.resumeUntilStopped(); SyncUtil.step(StepType.STEP_RETURN); // Verify that all bytes are set for (int i = 0; i < BLOCK_SIZE; i++) { IAddress address = fBaseAddress.add(i); fWait.waitReset(); readMemory(fMemoryDmc, address, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); MemoryByte[] buffer = (MemoryByte[]) fWait.getReturnInfo(); assertTrue(fWait.getMessage(), fWait.isOK()); assertTrue("Wrong value read at offset " + i + ": expected '" + i + "', received '" + buffer[0].getValue() + "'", (buffer[0].getValue() == (byte) i)); } // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // readCharVaryingOffset // Test the reading of individual bytes by varying the offset // ------------------------------------------------------------------------ @Test public void readCharVaryingOffset() throws Throwable { // Run to the point where the array is zeroed SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters int word_size = 1; int count = 1; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Verify that all bytes are '0' for (int offset = 0; offset < BLOCK_SIZE; offset++) { fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); MemoryByte[] buffer = (MemoryByte[]) fWait.getReturnInfo(); assertTrue("Wrong value read at offset " + offset + ": expected '" + 0 + "', received '" + buffer[0].getValue() + "'", (buffer[0].getValue() == (byte) 0)); } // Run to the point where the array is set SyncUtil.addBreakpoint("MemoryTestApp.cc:setBlocks", true); SyncUtil.resumeUntilStopped(); SyncUtil.step(StepType.STEP_RETURN); // Verify that all bytes are set for (int offset = 0; offset < BLOCK_SIZE; offset++) { fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); MemoryByte[] buffer = (MemoryByte[]) fWait.getReturnInfo(); assertTrue("Wrong value read at offset " + offset + ": expected '" + offset + "', received '" + buffer[0].getValue() + "'", (buffer[0].getValue() == (byte) offset)); } // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // readCharArray // Test the reading of a byte array // ------------------------------------------------------------------------ @Test public void readCharArray() throws Throwable { // Run to the point where the variable is zeroed SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int word_size = 1; int count = BLOCK_SIZE; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Get the memory block fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); MemoryByte[] buffer = (MemoryByte[]) fWait.getReturnInfo(); // Verify that all bytes are '0' for (int i = 0; i < count; i++) { assertTrue("Wrong value read at offset " + i + ": expected '" + 0 + "', received '" + buffer[i].getValue() + "'", (buffer[i].getValue() == (byte) 0)); } // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:setBlocks", true); SyncUtil.resumeUntilStopped(); SyncUtil.step(StepType.STEP_RETURN); // Get the memory block fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); buffer = (MemoryByte[]) fWait.getReturnInfo(); // Verify that all bytes are '0' for (int i = 0; i < count; i++) { assertTrue("Wrong value read at offset " + i + ": expected '" + i + "', received '" + buffer[i].getValue() + "'", (buffer[i].getValue() == (byte) i)); } // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } /////////////////////////////////////////////////////////////////////////// // setMemory tests /////////////////////////////////////////////////////////////////////////// // ------------------------------------------------------------------------ // writeWithNullContext // Test that a null context is caught and generates an error // ------------------------------------------------------------------------ @Test public void writeWithNullContext() throws Throwable { // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int word_size = 1; int count = 1; byte[] buffer = new byte[count]; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Perform the test String expected = "Unknown context type"; fWait.waitReset(); writeMemory(null, fBaseAddress, offset, word_size, count, buffer); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // writeWithInvalidAddress // Test that an invalid address is caught and generates an error // ------------------------------------------------------------------------ @Test public void writeWithInvalidAddress() throws Throwable { // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); SyncUtil.step(StepType.STEP_RETURN); // Setup call parameters long offset = 0; int word_size = 1; int count = 1; byte[] buffer = new byte[count]; fBaseAddress = new Addr64("0"); // Perform the test fWait.waitReset(); writeMemory(fMemoryDmc, fBaseAddress, offset, word_size, count, buffer); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); String expected = "Cannot access memory at address"; // Error msg returned by gdb assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // writeWithInvalidWordSize // Test that an invalid word size is caught and generates an error // ------------------------------------------------------------------------ @Test public void writeWithInvalidWordSize() throws Throwable { // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int count = -1; byte[] buffer = new byte[1]; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Perform the test String expected = "Word size not supported (!= 1)"; fWait.waitReset(); writeMemory(fMemoryDmc, fBaseAddress, offset, 0, count, buffer); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); fWait.waitReset(); writeMemory(fMemoryDmc, fBaseAddress, offset, 2, count, buffer); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // writeWithInvalidCount // Test that an invalid count is caught and generates an error // ------------------------------------------------------------------------ @Test public void writeWithInvalidCount() throws Throwable { // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int word_size = 1; int count = -1; byte[] buffer = new byte[1]; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Perform the test String expected = "Invalid word count (< 0)"; fWait.waitReset(); writeMemory(fMemoryDmc, fBaseAddress, offset, word_size, count, buffer); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // writeWithInvalidBuffer // Test that the buffer contains at least count bytes // ------------------------------------------------------------------------ @Test public void writeWithInvalidBuffer() throws Throwable { // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int word_size = 1; int count = 10; byte[] buffer = new byte[count - 1]; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Perform the test String expected = "Buffer too short"; fWait.waitReset(); writeMemory(fMemoryDmc, fBaseAddress, offset, word_size, count, buffer); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // writeCharVaryingAddress // Test the writing of individual bytes by varying the base address // ------------------------------------------------------------------------ @Test public void writeCharVaryingAddress() throws Throwable { // Run to the point where the variable is zeroed SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int word_size = 1; int count = BLOCK_SIZE; byte[] buffer = new byte[count]; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Perform the test for (int i = 0; i < count; i++) { // [1] Ensure that the memory byte = 0 fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, i, word_size, 1); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); MemoryByte[] block = (MemoryByte[]) fWait.getReturnInfo(); assertTrue("Wrong value read at offset " + i + ": expected '" + 0 + "', received '" + block[0].getValue() + "'", (block[0].getValue() == (byte) 0)); // [2] Write a byte value (count - i - 1) IAddress address = fBaseAddress.add(i); fWait.waitReset(); byte expected = (byte) (count - i - 1); buffer[0] = expected; writeMemory(fMemoryDmc, address, offset, word_size, 1, buffer); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); // [3] Verify that the correct MemoryChangedEvent was sent // (I hardly believe there are no synchronization problems here...) assertTrue("MemoryChangedEvent problem at offset " + i + ": expected " + (i + 1) + " events, received " + getEventCount(), getEventCount() == (i + 1)); assertTrue("MemoryChangedEvent problem at offset " + i, fMemoryAddressesChanged[i]); // [4] Verify that the memory byte was written correctly fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, i, word_size, 1); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); block = (MemoryByte[]) fWait.getReturnInfo(); assertTrue("Wrong value read at offset " + i + ": expected '" + expected + "', received '" + block[0].getValue() + "'", (block[0].getValue() == expected)); } // Ensure the MemoryChangedEvent events were received assertTrue("MemoryChangedEvent problem: expected " + BLOCK_SIZE + " events, received " + getEventCount(), getEventCount() == BLOCK_SIZE); assertTrue("MemoryChangedEvent problem: expected " + BLOCK_SIZE + " distinct addresses, received " + getAddressCount(), getEventCount() == BLOCK_SIZE); } // ------------------------------------------------------------------------ // writeCharVaryingOffset // Test the writing of individual bytes by varying the base address // ------------------------------------------------------------------------ @Test public void writeCharVaryingOffset() throws Throwable { // Run to the point where the variable is zeroed SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); int word_size = 1; int count = BLOCK_SIZE; byte[] buffer = new byte[count]; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Perform the test for (int offset = 0; offset < count; offset++) { // [1] Ensure that the memory byte = 0 fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, word_size, 1); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); MemoryByte[] block = (MemoryByte[]) fWait.getReturnInfo(); assertTrue("Wrong value read at offset " + offset + ": expected '" + 0 + "', received '" + block[0].getValue() + "'", (block[0].getValue() == (byte) 0)); // [2] Write a byte value (count - offset - 1) fWait.waitReset(); byte expected = (byte) (count - offset - 1); buffer[0] = expected; writeMemory(fMemoryDmc, fBaseAddress, offset, word_size, 1, buffer); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); // [3] Verify that the correct MemoryChangedEvent was sent assertTrue("MemoryChangedEvent problem at offset " + offset + ": expected " + (offset + 1) + " events, received " + getEventCount(), getEventCount() == (offset + 1)); assertTrue("MemoryChangedEvent problem at offset " + offset, fMemoryAddressesChanged[offset]); // [4] Verify that the memory byte was written correctly fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, word_size, 1); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); block = (MemoryByte[]) fWait.getReturnInfo(); assertTrue("Wrong value read at offset " + offset + ": expected '" + expected + "', received '" + block[0].getValue() + "'", (block[0].getValue() == expected)); } // Ensure the MemoryChangedEvent events were received assertTrue("MemoryChangedEvent problem: expected " + BLOCK_SIZE + " events, received " + getEventCount(), getEventCount() == BLOCK_SIZE); assertTrue("MemoryChangedEvent problem: expected " + BLOCK_SIZE + " distinct addresses, received " + getAddressCount(), getAddressCount() == BLOCK_SIZE); } // ------------------------------------------------------------------------ // writeCharArray // Test the writing of a byte array // ------------------------------------------------------------------------ @Test public void writeCharArray() throws Throwable { // Run to the point where the variable is zeroed SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int word_size = 1; int count = BLOCK_SIZE; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Make sure that the memory block is zeroed fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); MemoryByte[] block = (MemoryByte[]) fWait.getReturnInfo(); for (int i = 0; i < count; i++) { assertTrue("Wrong value read at offset " + i + ": expected '" + 0 + "', received '" + block[i].getValue() + "'", (block[i].getValue() == (byte) 0)); } // Write an initialized memory block byte[] buffer = new byte[count]; for (int i = 0; i < count; i++) { buffer[i] = (byte) i; } fWait.waitReset(); writeMemory(fMemoryDmc, fBaseAddress, offset, word_size, count, buffer); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); // Make sure that the memory block is initialized fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); block = (MemoryByte[]) fWait.getReturnInfo(); for (int i = 0; i < count; i++) { assertTrue("Wrong value read at offset " + i + ": expected '" + 0 + "', received '" + block[i].getValue() + "'", (block[i].getValue() == (byte) i)); } // Ensure the MemoryChangedEvent events were received assertTrue("MemoryChangedEvent problem: expected " + 1 + " event, received " + getEventCount(), getEventCount() == 1); assertTrue("MemoryChangedEvent problem: expected " + BLOCK_SIZE + " distinct addresses, received " + getAddressCount(), getAddressCount() == BLOCK_SIZE); } /////////////////////////////////////////////////////////////////////////// // fillMemory tests /////////////////////////////////////////////////////////////////////////// // ------------------------------------------------------------------------ // fillWithNullContext // Test that a null context is caught and generates an error // ------------------------------------------------------------------------ @Test public void fillWithNullContext() throws Throwable { // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int word_size = 1; int count = 1; byte[] pattern = new byte[count]; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Perform the test String expected = "Unknown context type"; fWait.waitReset(); fillMemory(null, fBaseAddress, offset, word_size, count, pattern); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // fillWithInvalidAddress // Test that an invalid address is caught and generates an error // ------------------------------------------------------------------------ @Test public void fillWithInvalidAddress() throws Throwable { // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); SyncUtil.step(StepType.STEP_RETURN); // Setup call parameters long offset = 0; int word_size = 1; int count = 1; byte[] pattern = new byte[count]; fBaseAddress = new Addr64("0"); // Perform the test fWait.waitReset(); fillMemory(fMemoryDmc, fBaseAddress, offset, word_size, count, pattern); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); String expected = "Cannot access memory at address"; // Error msg returned by gdb assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // fillWithInvalidWordSize // Test that an invalid word size is caught and generates an error // ------------------------------------------------------------------------ @Test public void fillWithInvalidWordSize() throws Throwable { // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int count = 1; byte[] pattern = new byte[1]; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Perform the test String expected = "Word size not supported (!= 1)"; fWait.waitReset(); fillMemory(fMemoryDmc, fBaseAddress, offset, 0, count, pattern); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); fWait.waitReset(); fillMemory(fMemoryDmc, fBaseAddress, offset, 2, count, pattern); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // fillWithInvalidCount // Test that an invalid count is caught and generates an error // ------------------------------------------------------------------------ @Test public void fillWithInvalidCount() throws Throwable { // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int word_size = 1; int count = -1; byte[] pattern = new byte[1]; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Perform the test String expected = "Invalid repeat count (< 0)"; fWait.waitReset(); fillMemory(fMemoryDmc, fBaseAddress, offset, word_size, count, pattern); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // fillWithInvalidPattern // Test that an empty pattern is caught and generates an error // ------------------------------------------------------------------------ @Test public void fillWithInvalidPattern() throws Throwable { // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int word_size = 1; int count = 1; byte[] pattern = new byte[0]; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Perform the test String expected = "Empty pattern"; fWait.waitReset(); fillMemory(fMemoryDmc, fBaseAddress, offset, word_size, count, pattern); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertFalse(fWait.getMessage(), fWait.isOK()); assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'", fWait.getMessage().contains(expected)); // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } // ------------------------------------------------------------------------ // writePatternVaryingAddress // Test the writing of the pattern by varying the base address // ------------------------------------------------------------------------ @Test public void writePatternVaryingAddress() throws Throwable { // Run to the point where the variable is zeroed SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int word_size = 1; int count = 1; int length = 4; byte[] pattern = new byte[length]; for (int i = 0; i < length; i++) pattern[i] = (byte) i; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Ensure that the memory is zeroed fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count * length); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); MemoryByte[] block = (MemoryByte[]) fWait.getReturnInfo(); for (int i = 0; i < (count * length); i++) assertTrue("Wrong value read at offset " + i + ": expected '" + 0 + "', received '" + block[i].getValue() + "'", (block[i].getValue() == (byte) 0)); for (int i = 0; i < BLOCK_SIZE; i += length) { IAddress address = fBaseAddress.add(i); fWait.waitReset(); fillMemory(fMemoryDmc, address, offset, word_size, count, pattern); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); } // Verify that the memory is correctly set fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, 0, word_size, count * length); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); block = (MemoryByte[]) fWait.getReturnInfo(); for (int i = 0; i < count; i++) for (int j = 0; j < length; j++) { int index = i * length + j; assertTrue("Wrong value read at offset " + index + ": expected '" + j + "', received '" + block[index].getValue() + "'", (block[index].getValue() == (byte) j)); } // Ensure the MemoryChangedEvent events were received assertTrue("MemoryChangedEvent problem: expected " + (BLOCK_SIZE / length) + " events, received " + getEventCount(), getEventCount() == (BLOCK_SIZE / length)); assertTrue("MemoryChangedEvent problem: expected " + BLOCK_SIZE + " distinct addresses, received " + getAddressCount(), getAddressCount() == BLOCK_SIZE); } // ------------------------------------------------------------------------ // writePatternVaryingOffset // Test the writing of the pattern by varying the base address // ------------------------------------------------------------------------ @Test public void writePatternVaryingOffset() throws Throwable { // Run to the point where the variable is zeroed SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int word_size = 1; int count = 64; int length = 4; byte[] pattern = new byte[length]; for (int i = 0; i < length; i++) pattern[i] = (byte) i; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Ensure that the memory is zeroed fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count * length); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); MemoryByte[] block = (MemoryByte[]) fWait.getReturnInfo(); for (int i = 0; i < (count * length); i++) assertTrue("Wrong value read at offset " + i + ": expected '" + 0 + "', received '" + block[i].getValue() + "'", (block[i].getValue() == (byte) 0)); for (int i = 0; i < (BLOCK_SIZE / length); i++) { offset = i * length; fWait.waitReset(); fillMemory(fMemoryDmc, fBaseAddress, offset, word_size, 1, pattern); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); } // Verify that the memory is correctly set fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, 0, word_size, count * length); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); block = (MemoryByte[]) fWait.getReturnInfo(); for (int i = 0; i < count; i++) for (int j = 0; j < length; j++) { int index = i * length + j; assertTrue("Wrong value read at offset " + index + ": expected '" + j + "', received '" + block[index].getValue() + "'", (block[index].getValue() == (byte) j)); } // Ensure the MemoryChangedEvent events were received assertTrue("MemoryChangedEvent problem: expected " + (BLOCK_SIZE / length) + " events, received " + getEventCount(), getEventCount() == (BLOCK_SIZE / length)); assertTrue("MemoryChangedEvent problem: expected " + BLOCK_SIZE + " distinct addresses, received " + getAddressCount(), getAddressCount() == BLOCK_SIZE); } // ------------------------------------------------------------------------ // writePatternCountTimes // Test the writing of the pattern [count] times // ------------------------------------------------------------------------ @Test public void writePatternCountTimes() throws Throwable { // Run to the point where the variable is zeroed SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int word_size = 1; int count = 64; int length = 4; byte[] pattern = new byte[length]; for (int i = 0; i < length; i++) pattern[i] = (byte) i; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Ensure that the memory is zeroed fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count * length); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); MemoryByte[] block = (MemoryByte[]) fWait.getReturnInfo(); for (int i = 0; i < (count * length); i++) assertTrue("Wrong value read at offset " + i + ": expected '" + 0 + "', received '" + block[i].getValue() + "'", (block[i].getValue() == (byte) 0)); // Write the pattern [count] times fWait.waitReset(); fillMemory(fMemoryDmc, fBaseAddress, offset, word_size, count, pattern); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); // Verify that the memory is correctly set fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count * length); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); block = (MemoryByte[]) fWait.getReturnInfo(); for (int i = 0; i < count; i++) for (int j = 0; j < length; j++) { int index = i * length + j; assertTrue("Wrong value read at offset " + index + ": expected '" + j + "', received '" + block[index].getValue() + "'", (block[index].getValue() == (byte) j)); } // Ensure the MemoryChangedEvent events were received assertTrue("MemoryChangedEvent problem: expected " + 1 + " events, received " + getEventCount(), getEventCount() == 1); assertTrue("MemoryChangedEvent problem: expected " + BLOCK_SIZE + " distinct addresses, received " + getAddressCount(), getAddressCount() == BLOCK_SIZE); } // ------------------------------------------------------------------------ // asynchronousReadWrite // Test the asynchronous reading/writing of individual bytes (varying offset) // ------------------------------------------------------------------------ @Test public void asynchronousReadWrite() throws Throwable { // Run to the point where the array is zeroed SyncUtil.addBreakpoint("MemoryTestApp.cc:zeroBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters int word_size = 1; int count = 1; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Interesting issue. Believe it or not, requests can get serviced // faster than we can queue them. E.g., we queue up five, and before we // queue the sixth, the five are serviced. Before, when that happened // the waitor went into the 'complete' state before we were done queuing // all the requests. To avoid that, we need to add our own tick and then // clear it once we're done queuing all the requests. // Verify asynchronously that all bytes are '0' fWait.waitReset(); fWait.increment(); // see "Interesting issue" comment above MemoryByte[] buffer = new MemoryByte[BLOCK_SIZE]; for (int offset = 0; offset < BLOCK_SIZE; offset++) { fWait.increment(); readMemoryByteAtOffset(fMemoryDmc, fBaseAddress, offset, word_size, count, buffer); } fWait.waitFinished(); // see "Interesting issue" comment above fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); for (int offset = 0; offset < BLOCK_SIZE; offset++) { assertTrue("Wrong value read at offset " + offset + ": expected '" + 0 + "', received '" + buffer[offset].getValue() + "'", (buffer[offset].getValue() == (byte) 0)); } // Write asynchronously fWait.waitReset(); fWait.increment(); // see "Interesting issue" comment above for (int offset = 0; offset < BLOCK_SIZE; offset++) { fWait.increment(); byte[] block = new byte[count]; block[0] = (byte) offset; writeMemory(fMemoryDmc, fBaseAddress, offset, word_size, count, block); } fWait.waitFinished(); // see "Interesting issue" comment above fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); // Ensure the MemoryChangedEvent events were received assertTrue("MemoryChangedEvent problem: expected " + BLOCK_SIZE + " events, received " + getEventCount(), getEventCount() == BLOCK_SIZE); assertTrue("MemoryChangedEvent problem: expected " + BLOCK_SIZE + " distinct addresses, received " + getAddressCount(), getAddressCount() == BLOCK_SIZE); // Verify asynchronously that all bytes are set fWait.waitReset(); fWait.increment(); // see "Interesting issue" comment above for (int offset = 0; offset < BLOCK_SIZE; offset++) { fWait.increment(); readMemoryByteAtOffset(fMemoryDmc, fBaseAddress, offset, word_size, count, buffer); } fWait.waitFinished(); // see "Interesting issue" comment above fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); for (int offset = 0; offset < BLOCK_SIZE; offset++) { assertTrue("Wrong value read at offset " + offset + ": expected '" + offset + "', received '" + buffer[offset].getValue() + "'", (buffer[offset].getValue() == (byte) offset)); } } // ------------------------------------------------------------------------ // memoryCacheRead // Get a bunch of blocks to exercise the memory cache // ------------------------------------------------------------------------ @Test public void memoryCacheRead() throws Throwable { // Run to the point where the variable is initialized SyncUtil.addBreakpoint("MemoryTestApp.cc:setBlocks", true); SyncUtil.resumeUntilStopped(); MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_RETURN); IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); // Setup call parameters long offset = 0; int word_size = 1; int count = BLOCK_SIZE; fBaseAddress = evaluateExpression(frameDmc, "&charBlock"); // Get the 'reference' memory block fWait.waitReset(); readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); MemoryByte[] buffer = (MemoryByte[]) fWait.getReturnInfo(); // Verify that all bytes are set to 'i' for (int i = 0; i < count; i++) { assertTrue("Wrong value read at offset " + i + ": expected '" + i + "', received '" + buffer[i].getValue() + "'", (buffer[i].getValue() == (byte) i)); } // Clear the cache SyncUtil.step(StepType.STEP_OVER); // Get a first block fWait.waitReset(); offset = 0; count = 64; readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); buffer = (MemoryByte[]) fWait.getReturnInfo(); // Verify that all bytes are correctly set for (int i = 0; i < count; i++) { assertTrue("Wrong value read at offset " + i + ": expected '" + offset + i + "', received '" + buffer[i].getValue() + "'", (buffer[i].getValue() == (byte) (offset + i))); } // Get a second block fWait.waitReset(); offset = 128; count = 64; readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); buffer = (MemoryByte[]) fWait.getReturnInfo(); // Verify that all bytes are correctly set for (int i = 0; i < count; i++) { assertTrue("Wrong value read at offset " + i + ": expected '" + offset + i + "', received '" + buffer[i].getValue() + "'", (buffer[i].getValue() == (byte) (offset + i))); } // Get a third block between the first 2 fWait.waitReset(); offset = 80; count = 32; readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); buffer = (MemoryByte[]) fWait.getReturnInfo(); // Verify that all bytes are correctly set for (int i = 0; i < count; i++) { assertTrue("Wrong value read at offset " + i + ": expected '" + offset + i + "', received '" + buffer[i].getValue() + "'", (buffer[i].getValue() == (byte) (offset + i))); } // Get a block that is contiguous to the end of an existing block fWait.waitReset(); offset = 192; count = 32; readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); buffer = (MemoryByte[]) fWait.getReturnInfo(); // Verify that all bytes are correctly set for (int i = 0; i < count; i++) { assertTrue("Wrong value read at offset " + i + ": expected '" + offset + i + "', received '" + buffer[i].getValue() + "'", (buffer[i].getValue() == (byte) (offset + i))); } // Get a block that ends beyond an existing block fWait.waitReset(); offset = 192; count = 64; readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); buffer = (MemoryByte[]) fWait.getReturnInfo(); // Verify that all bytes are correctly set for (int i = 0; i < count; i++) { assertTrue("Wrong value read at offset " + i + ": expected '" + offset + i + "', received '" + buffer[i].getValue() + "'", (buffer[i].getValue() == (byte) (offset + i))); } // Get a block that will require 2 reads (for the gaps between blocks 1-2 and 2-3) fWait.waitReset(); offset = 32; count = 128; readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); buffer = (MemoryByte[]) fWait.getReturnInfo(); // Verify that all bytes are correctly set for (int i = 0; i < count; i++) { assertTrue("Wrong value read at offset " + i + ": expected '" + offset + i + "', received '" + buffer[i].getValue() + "'", (buffer[i].getValue() == (byte) (offset + i))); } // Get a block that involves multiple cached blocks fWait.waitReset(); offset = 48; count = 192; readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); buffer = (MemoryByte[]) fWait.getReturnInfo(); // Verify that all bytes are set to 'i' for (int i = 0; i < count; i++) { assertTrue("Wrong value read at offset " + i + ": expected '" + offset + i + "', received '" + buffer[i].getValue() + "'", (buffer[i].getValue() == (byte) (offset + i))); } // Get the whole block fWait.waitReset(); offset = 0; count = BLOCK_SIZE; readMemory(fMemoryDmc, fBaseAddress, offset, word_size, count); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); assertTrue(fWait.getMessage(), fWait.isOK()); buffer = (MemoryByte[]) fWait.getReturnInfo(); // Verify that all bytes are correctly set for (int i = 0; i < count; i++) { assertTrue("Wrong value read at offset " + i + ": expected '" + offset + i + "', received '" + buffer[i].getValue() + "'", (buffer[i].getValue() == (byte) (offset + i))); } // Ensure no MemoryChangedEvent event was received assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0); } }