/*******************************************************************************
 * Copyright (c) 2007, 2015 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			  - Initial Implementation
 *     Simon Marchi (Ericsson) - Move some tests from AsyncCompletionWaitor to Query
 *******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.tests;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

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.ImmediateDataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Query;
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.IExpressionChangedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMAddress;
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMData;
import org.eclipse.cdt.dsf.debug.service.IExpressions.IIndexedPartitionDMContext;
import org.eclipse.cdt.dsf.debug.service.IExpressions2;
import org.eclipse.cdt.dsf.debug.service.IExpressions2.CastInfo;
import org.eclipse.cdt.dsf.debug.service.IExpressions2.ICastedExpressionDMContext;
import org.eclipse.cdt.dsf.debug.service.IExpressions3.IExpressionDMDataExtension;
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.IRunControl.StepType;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMData;
import org.eclipse.cdt.dsf.mi.service.ClassAccessor.MIExpressionDMCAccessor;
import org.eclipse.cdt.dsf.mi.service.MIExpressions;
import org.eclipse.cdt.dsf.mi.service.MIExpressions.MIExpressionDMC;
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.BaseParametrizedTestCase;
import org.eclipse.cdt.tests.dsf.gdb.framework.ServiceEventWaitor;
import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil;
import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin;
import org.eclipse.cdt.utils.Addr32;
import org.eclipse.cdt.utils.Addr64;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class MIExpressionsTest extends BaseParametrizedTestCase {
	private static final String EXEC_NAME = "ExpressionTestApp.exe";

    private DsfSession fSession;

    private DsfServicesTracker fServicesTracker;

    protected IExpressions fExpService;

    private int fExprChangedEventCount = 0;

    private IExpressionDMContext fExprChangedCtx = null;
    
    private IExpressionDMContext globalExpressionCtx1 = null;
    private IExpressionDMContext globalExpressionCtx2 = null;

    @Override
    protected void setLaunchAttributes() {
    	super.setLaunchAttributes();
    	    	
    	setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, EXEC_PATH + EXEC_NAME);
    }

    @Override
    public void doBeforeTest() throws Exception {
    	super.doBeforeTest();

    	fSession = getGDBLaunch().getSession();
        Runnable runnable = new Runnable() {
            @Override
			public void run() {
           	fServicesTracker = new DsfServicesTracker(TestsPlugin.getBundleContext(), fSession.getId());
            	
            	fExpService = fServicesTracker.getService(IExpressions.class);
            	fSession.addServiceEventListener(MIExpressionsTest.this, null);
            	clearExprChangedData();
            }
        };
        fSession.getExecutor().submit(runnable).get();
    }

    @Override
    public void doAfterTest() throws Exception {
    	super.doAfterTest();
		if (fSession != null) {
			fSession.getExecutor().submit(()->fSession.removeServiceEventListener(MIExpressionsTest.this)).get();
		}
		fExpService = null;
		if (fServicesTracker != null) {    	
			fServicesTracker.dispose();
		}
    }

    // Handles ExpressionChangedEvent
    @DsfServiceEventHandler
    public void eventDispatched(IExpressionChangedDMEvent e) {
        fExprChangedEventCount++;
        fExprChangedCtx = e.getDMContext();
    }

    // Clears the counters
    private void clearExprChangedData() {
        fExprChangedEventCount = 0;
        fExprChangedCtx = null;
    }

    // Returns the total number of events received
    private int getExprChangedCount() {
        return fExprChangedEventCount;
    }

    private IExpressionDMContext getExprChangedContext() {
        return fExprChangedCtx;
    }

    // *********************************************************************
    // Below are the tests for the expression service.
    // *********************************************************************

    /**
     * Test that we can correctly evaluate integer expressions.
     */
    @Test
    public void testLiteralIntegerExpressions() throws Throwable {
        MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("testLocals");

        // Create a map of expressions and their expected values.
        Map<String, String[]> tests = new HashMap<String, String[]>();

        tests.put("0 + 0 - 0", new String[] { "0x0", "0", "0", "0", "0", "0" });
        tests.put("3 + 4", new String[] { "0x7", "07", "111", "7", "7", "7" });
        tests.put("3 + 4 * 5", new String[] { "0x17", "027", "10111", "23", "23", "23" });
        tests.put("5 * 3 + 4", new String[] { "0x13", "023", "10011", "19", "19", "19" });
        tests.put("5 * (3 + 4)", new String[] { "0x23", "043", "100011", "35", "35", "35" });
        tests.put("10 - 15", new String[] { "0xFFFFFFFB", "037777777773", "11111111111111111111111111111011", "-5",
            "-5", "-5" });
        tests.put("10 + -15", new String[] { "0xFFFFFFFB", "037777777773", "11111111111111111111111111111011", "-5",
            "-5", "-5" });

        executeExpressionSubTests(tests, SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0));
    }

    /**
     * Test that we can correctly evaluate floating-point expressions.
     */
    @Test
    public void testLiteralFloatingPointExpressions() throws Throwable {
        MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("testLocals");

        // Create a map of expressions and their expected values.
        Map<String, String[]> tests = new HashMap<String, String[]>();

        tests.put("3.14159 + 1.1111", new String[] { "0x4", "04", "100", "4", "4.2526", "4.2526" });
        tests.put("100.0 / 3.0", new String[] { "0x21", "041", "100001", "33", "33.3333", "33.3333" });
        tests.put("-100.0 / 3.0", new String[] { "0xffffffffffffffdf", "01777777777777777777737",
            "1111111111111111111111111111111111111111111111111111111111011111", "-33", "-33.3333", "-33.3333" });
        tests.put("-100.0 / -3.0", new String[] { "0x21", "041", "100001", "33", "33.3333", "33.3333" });
        executeExpressionSubTests(tests, false, SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0));

        tests.clear();
        tests.put("100.0 / 0.5", new String[] { "0xc8", "0310", "11001000", "200", "200", "200" });
        executeExpressionSubTests(tests, true, SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0));        

    }

    /**
     * Test that we can correctly evaluate C expressions involving local
     * variables.
     */
    @Test
    public void testLocalVariables() throws Throwable {
        // Run to the point where all local variables are initialized
        SyncUtil.runToLocation("testLocals");
        MIStoppedEvent stoppedEvent = SyncUtil.step(16, StepType.STEP_OVER);

        // Create a map of expressions to expected values.
        Map<String, String[]> tests1 = new HashMap<String, String[]>();

        tests1.put("lIntVar", new String[] { "0x3039", "030071", "11000000111001", "12345", "12345", "12345" });
        tests1.put("lDoubleVar", new String[] { "0x3039", "030071", "11000000111001", "12345", "12345.123449999999", "12345.123449999999" });
        tests1.put("lCharVar", new String[] { "0x6d", "0155", "1101101", "109", "109 'm'", "109 'm'" });
        tests1.put("lBoolVar", new String[] { "0x0", "0", "0", "0", "false", "false" });

        tests1.put("lIntArray[1]", new String[] { "0x3039", "030071", "11000000111001", "12345", "12345", "12345" });
        tests1.put("lDoubleArray[1]",  new String[] { "0x3039", "030071", "11000000111001", "12345", "12345.123449999999", "12345.123449999999" });
        tests1.put("lCharArray[1]", new String[] { "0x6d", "0155", "1101101", "109", "109 'm'", "109 'm'" });
        tests1.put("lBoolArray[1]", new String[] { "0x0", "0", "0", "0", "false", "false" });

        tests1.put("*lIntPtr", new String[] { "0x3039", "030071", "11000000111001", "12345", "12345", "12345" });
        tests1.put("*lDoublePtr", new String[] { "0x3039", "030071", "11000000111001", "12345", "12345.123449999999", "12345.123449999999" });
        tests1.put("*lCharPtr", new String[] { "0x6d", "0155", "1101101", "109", "109 'm'", "109 'm'" });
        tests1.put("*lBoolPtr", new String[] { "0x0", "0", "0", "0", "false", "false" });

        tests1.put("lIntPtr2", new String[] { "0x1", "01", "1", "1", "0x1", "0x1" });
        tests1.put("lDoublePtr2", new String[] { "0x2345", "021505", "10001101000101", "9029", "0x2345", "0x2345" });
        // GDB says a char* is out of bounds, but not the other pointers???
        // tests1.put("CharPtr2", new String[] { "0x1234", "011064",
        // "1001000110100", "4660", "0x1234" });
        tests1.put("lBoolPtr2", new String[] { "0x123ABCDE", "02216536336", "10010001110101011110011011110", "305839326", "0x123ABCDE", "0x123ABCDE" });

        executeExpressionSubTests(tests1, SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0));

        // Step into the method and stop until all new local variables are
        // initialized
        SyncUtil.step(StepType.STEP_INTO);
        stoppedEvent = SyncUtil.step(5, StepType.STEP_OVER);

        // Create a map of expressions to expected values.
        Map<String, String[]> tests2 = new HashMap<String, String[]>();

        tests2.put("lIntVar", new String[] { "0x1a85", "015205", "1101010000101", "6789", "6789", "6789" });
        tests2.put("lDoubleArray[1]",
            new String[] { "0x1a85", "015205", "1101010000101", "6789", "6789.6788999999999", "6789.6788999999999" });
        tests2.put("lCharVar", new String[] { "0x69", "0151", "1101001", "105", "105 'i'", "105 'i'" });
        tests2.put("*lCharPtr", new String[] { "0x69", "0151", "1101001", "105", "105 'i'", "105 'i'" });
        tests2.put("lBoolPtr2", new String[] { "0xABCDE123", "025363360443", "10101011110011011110000100100011",
            "2882396451", "0xABCDE123","0xABCDE123" });

        // check variables at current stack frame
        executeExpressionSubTests(tests2, SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0));
        // check previous stack frame
        executeExpressionSubTests(tests1, SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 1));

        // Now return from the method and check that we see the
        // original variables.  We must use the right context to restore the right stack frame
        stoppedEvent = SyncUtil.step(stoppedEvent.getDMContext(), StepType.STEP_RETURN);

        executeExpressionSubTests(tests1, SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0));
    }

    /**
     * This tests verifies that we can deal with variables in a subblock hiding
     * variables with the same name in the outer block.
     */
    @Ignore("Sublocks do not work with GDB")
    @Test
    public void testSubBlock() throws Throwable {
        SyncUtil.runToLocation("testSubblock");
        MIStoppedEvent stoppedEvent = SyncUtil.step(2, StepType.STEP_OVER);
        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        Map<String, String[]> tests = new HashMap<String, String[]>();

        tests.put("a", new String[] { "0x8", "010", "1000", "8", "8", "8" });
        tests.put("b", new String[] { "0x1", "01", "1", "1", "1", "1" });

        executeExpressionSubTests(tests, frameDmc);

        // Now enter a subblock with the same variable names
        SyncUtil.step(2, StepType.STEP_OVER);

        tests = new HashMap<String, String[]>();

        tests.put("a", new String[] { "0xc", "014", "1100", "12", "12", "12" });
        tests.put("b", new String[] { "0x1", "01", "1", "1", "1", "1" });

        executeExpressionSubTests(tests, frameDmc);

        // Now step to change the b variable
        SyncUtil.step(1, StepType.STEP_OVER);

        tests = new HashMap<String, String[]>();

        tests.put("a", new String[] { "0xc", "014", "1100", "12", "12", "12" });
        tests.put("b", new String[] { "0xc", "014", "1100", "12", "12", "12" });

        executeExpressionSubTests(tests, frameDmc);

        // Now exit the sub-block and check that we see the original a but the
        // same b
        SyncUtil.step(1, StepType.STEP_OVER);

        tests = new HashMap<String, String[]>();

        tests.put("a", new String[] { "0x8", "010", "1000", "8", "8", "8" });
        tests.put("b", new String[] { "0xc", "014", "1100", "12", "12", "12" });

        executeExpressionSubTests(tests, frameDmc);
    }

    /**
     * This tests verifies that we can obtain children properly.
     */
    @Test
    public void testChildren() throws Throwable {
      	assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_6_7);

    	// Get the children of some variables
        MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("testChildren");
        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
        IExpressionDMContext exprDMC = SyncUtil.createExpression(frameDmc, "f");
        doTestChildren(exprDMC);
        
        // Now do a step and get the children again, to test the internal cache
        SyncUtil.step(1, StepType.STEP_OVER);
        doTestChildren(exprDMC);
    }
    
    /**
     * This test makes sure we get the right number of children.
     */
    @Test
    public void testChildrenCount() throws Throwable {
        // Next we test that we can retrieve children count while reading the
        // value and vice-versa

        SyncUtil.runToLocation("testChildren");
        MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);

        final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

    	// First we get the expected value of the array pointer.
        final IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "f");

        assertChildrenCount(exprDmc, 5);
    }

	/**
	 * This test makes sure we get can tell if an expression has children based
	 * on the expression data.
	 */
	@Test
	public void testHasChildrenInExpressionData() throws Throwable {
		SyncUtil.runToLocation("testChildren");
		MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);

		final IFrameDMContext frameDmc = SyncUtil.getStackFrame(
				stoppedEvent.getDMContext(), 0);

		// First we get the expected value of the array pointer.
		final IExpressionDMContext exprDmc = SyncUtil.createExpression(
				frameDmc, "f");

		Query<IExpressionDMData> query = new Query<IExpressionDMData>() {
			@Override
			protected void execute(DataRequestMonitor<IExpressionDMData> rm) {
				fExpService.getExpressionData(exprDmc, rm);
			}
		};

		fExpService.getExecutor().submit(query);

		IExpressionDMData data = query.get();
		IExpressionDMDataExtension dataExtension = (IExpressionDMDataExtension) data;

		assertThat("expression has children", dataExtension.hasChildren());

	}

    /**
     * This test makes sure we properly deal with a GDB display bug.
     * See bug 320277
     * 
     * The following code causes a bug in GDB:
     * 
     * class Base {};
     * class BaseTest: public Base {
     *   public:
     *     BaseTest() {} // Removing this lines removes GDB's bug
     *     void test() { return; }
     * };
     * 
     * We see the bug with the following commands:
     * -var-create - * this
     * -var-list-children var1
     * -var-info-path-expression var1.BaseTest
     * -data-evaluate-expression "(*(Base*) this)"
     * 
     * which we can reproduce by creating the children of this
     * and asking for the DETAILS_FORMAT of the var1.BaseTest child.
     */
	@Test
	public void testBaseChildrenBug() throws Throwable {

		MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("BaseTest::test");

		final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

		// First we get 'this' and its children
		final IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "this");
		final IExpressionDMContext[] children = getChildren(exprDmc, new String[] { "Base", "Base" });

		Query<FormattedValueDMData> query = new Query<FormattedValueDMData>() {
			@Override
			protected void execute(DataRequestMonitor<FormattedValueDMData> rm) {
				FormattedValueDMContext dmc = fExpService.getFormattedValueContext(children[0], MIExpressions.DETAILS_FORMAT);
				fExpService.getFormattedExpressionValue(dmc, rm);
			}
		};

		fExpService.getExecutor().submit(query);

		query.get();

		// This second child is testing the fact that we could have the child named
		// the same as its type and we still want to be able to get the details without error.
		query = new Query<FormattedValueDMData>() {
			@Override
			protected void execute(DataRequestMonitor<FormattedValueDMData> rm) {
				FormattedValueDMContext dmc = fExpService.getFormattedValueContext(children[1], MIExpressions.DETAILS_FORMAT);
				fExpService.getFormattedExpressionValue(dmc, rm);
			}
		};

		fExpService.getExecutor().submit(query);

		query.get();
	}

	/**
	 * This test makes sure we properly deal with a GDB display bug and nested
	 * children. See bug 320277.
	 */
	@Test
	public void testNestedBaseChildrenBug() throws Throwable {

		MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("BaseTest::test");

		final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

		// First we get 'this' and its children
		final IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "this");
		IExpressionDMContext[] children1 = getChildren(exprDmc, new String[] { "Base", "Base" });
		final IExpressionDMContext[] children = getChildren(children1[0], new String[] { "nested", "pNested" });
		final IExpressionDMContext[] childOfPointer = getChildren(children[1], new String[] { "*pNested" });

		Query<FormattedValueDMData> query = new Query<FormattedValueDMData>() {

			@Override
			protected void execute(DataRequestMonitor<FormattedValueDMData> rm) {
				FormattedValueDMContext dmc = fExpService.getFormattedValueContext(children[0],
						MIExpressions.DETAILS_FORMAT);
				fExpService.getFormattedExpressionValue(dmc, rm);
			}
		};

		fExpService.getExecutor().submit(query);
		query.get();

		query = new Query<FormattedValueDMData>() {

			@Override
			protected void execute(DataRequestMonitor<FormattedValueDMData> rm) {
				FormattedValueDMContext dmc = fExpService.getFormattedValueContext(children[1],
						MIExpressions.DETAILS_FORMAT);
				fExpService.getFormattedExpressionValue(dmc, rm);
			}
		};

		fExpService.getExecutor().submit(query);
		query.get();

		query = new Query<FormattedValueDMData>() {

			@Override
			protected void execute(DataRequestMonitor<FormattedValueDMData> rm) {
				FormattedValueDMContext dmc = fExpService.getFormattedValueContext(childOfPointer[0],
						MIExpressions.DETAILS_FORMAT);
				fExpService.getFormattedExpressionValue(dmc, rm);
			}
		};

		fExpService.getExecutor().submit(query);
		query.get();
	}

	/**
	 * This test verifies that the ExpressionService can write to a variable.
	 */
	@Test
	public void testWriteVariable() throws Throwable {
		SyncUtil.runToLocation("testWrite");
		MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);

		final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
		final IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "a[1]");

		writeAndCheck(exprDmc, "987", IFormattedValues.DECIMAL_FORMAT, "987");
		writeAndCheck(exprDmc, "16", IFormattedValues.HEX_FORMAT, "22");
		writeAndCheck(exprDmc, "0x2e", IFormattedValues.HEX_FORMAT, "46");
		writeAndCheck(exprDmc, "16", IFormattedValues.OCTAL_FORMAT, "14");
		writeAndCheck(exprDmc, "022", IFormattedValues.OCTAL_FORMAT, "18");
		writeAndCheck(exprDmc, "1011", IFormattedValues.BINARY_FORMAT, "11");
		writeAndCheck(exprDmc, "0b1001", IFormattedValues.BINARY_FORMAT, "9");
		writeAndCheck(exprDmc, "456", IFormattedValues.NATURAL_FORMAT, "456");

	}

	/*
	 * This method does a write and then a read to make sure the new value was
	 * properly written.
	 */
	private void writeAndCheck(final IExpressionDMContext exprDmc, final String newValueFormatted, final String format,
			final String newValueInDecimal) throws Throwable {
		ServiceEventWaitor<IExpressionChangedDMEvent> eventWaitor = new ServiceEventWaitor<>(
				fSession, IExpressionChangedDMEvent.class);
		// Write the new value using its formatted value
		Query<Void> writeQuery = new Query<Void>() {

			@Override
			protected void execute(DataRequestMonitor<Void> rm) {
				fExpService.writeExpression(exprDmc, newValueFormatted, format, rm);
			}
		};

		fExpService.getExecutor().submit(writeQuery);
		writeQuery.get();

		IExpressionChangedDMEvent event = eventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000));
		assertThat(event.getDMContext(), is(exprDmc));

		// Read the new value in decimal and check that it is what we expected
		Query<FormattedValueDMData> readQuery = new Query<FormattedValueDMData>() {

			@Override
			protected void execute(DataRequestMonitor<FormattedValueDMData> rm) {
				FormattedValueDMContext dmc = fExpService.getFormattedValueContext(exprDmc,
						IFormattedValues.DECIMAL_FORMAT);
				fExpService.getFormattedExpressionValue(dmc, rm);
			}
		};

		fExpService.getExecutor().submit(readQuery);
		String actualDecimalValue = readQuery.get().getFormattedValue();

		assertThat(actualDecimalValue.toLowerCase(), is(newValueInDecimal.toLowerCase()));
	}

    /**
     * This tests verifies that we handle invalid formats properly for a write.
     */
    @Test
    public void testWriteErrorFormat() throws Throwable {
        SyncUtil.runToLocation("testWrite");
        MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);

        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
        IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "a[1]");

        writeAndCheckError(exprDmc, "goodbye", IFormattedValues.DECIMAL_FORMAT);
        writeAndCheckError(exprDmc, "abggg", IFormattedValues.HEX_FORMAT);
        writeAndCheckError(exprDmc, "99", IFormattedValues.OCTAL_FORMAT);
        writeAndCheckError(exprDmc, "234", IFormattedValues.BINARY_FORMAT);
        writeAndCheckError(exprDmc, "hello", IFormattedValues.NATURAL_FORMAT);
        writeAndCheckError(exprDmc, "1", "ThisFormatDoesNotExist");

        IExpressionDMContext notWritableExprDmc = SyncUtil.createExpression(frameDmc, "10+5");
        writeAndCheckError(notWritableExprDmc, "1", IFormattedValues.NATURAL_FORMAT);
    }

    /*
     * This method does a write that should use an invalid value or format, and
     * verifies that the operation fails
     */
    private void writeAndCheckError(final IExpressionDMContext exprDmc, final String invalidValueFormatted,
        final String format) throws Throwable {

        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

        // Write the new value using its formatted value
        fExpService.getExecutor().submit(new Runnable() {
            @Override
			public void run() {
                fExpService.writeExpression(exprDmc, invalidValueFormatted, format, new RequestMonitor(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        wait.waitFinished(getStatus());
                    }
                });
            }
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue("Got an OK status for an error test case.  Should not be able to write value "
            + invalidValueFormatted + " in " + format, !wait.isOK());

        assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
            getExprChangedCount() == 0);
    }

    /**
     * This test tries multiple format reads during the same executor cycle, to
     * make sure the internal MI commands are sequenced properly.
     */
    @Test
    public void testConcurrentReads() throws Throwable {
        // Next we test that we can read the value more than once
        // of the same variable object at the exact same time

        SyncUtil.runToLocation("testConcurrent");
        MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);

        final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);


        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

        fExpService.getExecutor().submit(new Runnable() {
            @Override
			public void run() {
                IExpressionDMContext exprDmc = fExpService.createExpression(frameDmc, "a[0]");
                
                wait.increment();
                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
                    IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().getFormattedValue().equals("28")) {
                                wait.waitFinished();
                            } else {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed evaluating natural format", null));
                            }
                        }
                    }
                });

                wait.increment();
                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
                    IFormattedValues.HEX_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().getFormattedValue().equalsIgnoreCase("0x1c")) {
                                wait.waitFinished();
                            } else {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed evaluating hex format", null));
                            }
                        }
                    }
                });
            }
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());

        assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
            getExprChangedCount() == 0);

    }

    /**
     * This test tries reads and listChildren during the same executor cycle, to
     * make sure the internal MI commands are sequenced properly.
     */
    @Test
    public void testConcurrentReadChildren() throws Throwable {
        // Next we test that we can retrieve children while reading the value
        // and vice-versa

        SyncUtil.runToLocation("testConcurrent");
        MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);

        final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

    	// First we get the expected value of the array pointer.
        final IExpressionDMContext addrDmc = SyncUtil.createExpression(frameDmc, "&a");

        fExpService.getExecutor().submit(new Runnable() {
            @Override
			public void run() {
                fExpService.getFormattedExpressionValue(
                		fExpService.getFormattedValueContext(addrDmc, IFormattedValues.NATURAL_FORMAT), 
                		new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
                			@Override
                			protected void handleCompleted() {
                				if (isSuccess()) {
                					wait.setReturnInfo(getData());
                				}

                				wait.waitFinished(getStatus());
                			}
                		});
            }
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());

        final String actualAddrStr = ((FormattedValueDMData) wait.getReturnInfo()).getFormattedValue();

        wait.waitReset();

        // Now perform the test
        fExpService.getExecutor().submit(new Runnable() {
            @Override
			public void run() {
                IExpressionDMContext exprDmc = fExpService.createExpression(frameDmc, "a");
                
                wait.increment();
                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
                    IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().getFormattedValue().equals(actualAddrStr)) {
                                wait.waitFinished();
                            } else {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed evaluating natural format", null));
                            }
                        }
                    }
                });

                wait.increment();
                fExpService.getSubExpressions(exprDmc, new DataRequestMonitor<IExpressionDMContext[]>(
                    fExpService.getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            IExpressionDMContext[] children = getData();
                            int failedIndex = -1;
                            for (int i = 0; i < 2; i++) {
                                if (!children[i].getExpression().equals("a[" + i + "]")) {
                                    failedIndex = i;
                                }
                            }

                            if (failedIndex != -1) {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed getting child number: " + failedIndex, null));
                            } else {
                                wait.waitFinished();
                            }
                        }
                    }
                });

                // Use different format to avoid triggering the cache
                wait.increment();
                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
                    IFormattedValues.HEX_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().getFormattedValue().equals(actualAddrStr)) {
                                wait.waitFinished();
                            } else {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed evaluating hex format", null));
                            }
                        }
                    }
                });
            }
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());

        assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
            getExprChangedCount() == 0);
    }

    /**
     * This test tries reads and getChildrenCount during the same executor
     * cycle, to make sure the internal MI commands are sequenced properly.
     */
    @Test
    public void testConcurrentReadChildrenCount() throws Throwable {
        // Next we test that we can retrieve children count while reading the
        // value and vice-versa

        SyncUtil.runToLocation("testConcurrent");
        MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);

        final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
        
    	// First we get the expected value of the array pointer.
        final IExpressionDMContext addrDmc = SyncUtil.createExpression(frameDmc, "&a");

        fExpService.getExecutor().submit(new Runnable() {
            @Override
			public void run() {
                fExpService.getFormattedExpressionValue(
                		fExpService.getFormattedValueContext(addrDmc, IFormattedValues.NATURAL_FORMAT), 
                		new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
                			@Override
                			protected void handleCompleted() {
                				if (isSuccess()) {
                					wait.setReturnInfo(getData());
                				}

                				wait.waitFinished(getStatus());
                			}
                		});
            }
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());

        final String actualAddrStr = ((FormattedValueDMData) wait.getReturnInfo()).getFormattedValue();

        wait.waitReset();

        fExpService.getExecutor().submit(new Runnable() {
            @Override
			public void run() {
                wait.increment();
                IExpressionDMContext exprDmc = fExpService.createExpression(frameDmc, "a");

                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
                    IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().getFormattedValue().equals(actualAddrStr)) {
                                wait.waitFinished();
                            } else {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed evaluating natural format", null));
                            }
                        }
                    }
                });

                wait.increment();
                fExpService.getSubExpressionCount(exprDmc, new DataRequestMonitor<Integer>(fExpService.getExecutor(),
                    null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            int count = getData();
                            if (count != 2) {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed getting count for children.  Got" + count + "instead of 2", null));
                            } else {
                                wait.waitFinished();
                            }
                        }
                    }
                });

                // Use different format to avoid triggering the cache
                wait.increment();
                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
                    IFormattedValues.HEX_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().getFormattedValue().equals(actualAddrStr)) {
                                wait.waitFinished();
                            } else {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed evaluating hex format", null));
                            }
                        }
                    }
                });
            }
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());

        assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
            getExprChangedCount() == 0);
    }

    /**
     * This test tries reads and writes during the same executor cycle, to make
     * sure the internal MI commands are sequenced properly.
     */
    @Test
    public void testConcurrentReadWrite() throws Throwable {
        // Next we test that we can deal with a write request and read request
        // at
        // the same time and vice-versa

        SyncUtil.runToLocation("testConcurrent");
        MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);

        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        final IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "a[1]");

        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

        fExpService.getExecutor().submit(new Runnable() {
            @Override
			public void run() {

                wait.increment();
                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
                    IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().getFormattedValue().equals("32")) {
                                wait.waitFinished();
                            } else {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed evaluating natural format, got " + getData().getFormattedValue()
                                        + " instead of 32", null));
                            }
                        }
                    }
                });

                wait.increment();
                fExpService.writeExpression(exprDmc, "56", IFormattedValues.NATURAL_FORMAT, new RequestMonitor(
                    fExpService.getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            wait.waitFinished();
                        }
                    }
                });

                // Use different format to avoid triggering the cache
                wait.increment();
                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
                    IFormattedValues.HEX_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().getFormattedValue().equals("0x38")) {
                                wait.waitFinished();
                            } else {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed evaluating hex format, got " + getData().getFormattedValue()
                                        + " instead of 0x38", null));
                            }
                        }
                    }
                });
            }
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());

        assertTrue("ExprChangedEvent problem: expected 1, received " + getExprChangedCount(),
            getExprChangedCount() == 1);
        exprDmc.equals(getExprChangedContext());
        clearExprChangedData();
    }

    /**
     * This test tries many different operations during the same executor cycle,
     * to make sure the internal MI commands are sequenced properly.
     */
    @Test
    public void testConcurrentReadWriteChildren() throws Throwable {
        // Finally, we go nuts and request two reads, while requesting
        // a get children and get children count.
    	// Note that we don't request a write, because a write is allowed to
    	// go through at any time and we don't exactly know when it will
    	// change the value we are reading.

        SyncUtil.runToLocation("testConcurrent");
        MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);

        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        final IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "a[1]");

        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

        fExpService.getExecutor().submit(new Runnable() {
            @Override
			public void run() {

                wait.increment();
                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
                    IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().getFormattedValue().equals("32")) {
                                wait.waitFinished();
                            } else {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed evaluating natural format, got " + getData().getFormattedValue()
                                        + " instead of 32", null));
                            }
                        }
                    }
                });

                wait.increment();
                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
                    IFormattedValues.HEX_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().getFormattedValue().equals("0x20")) {
                                wait.waitFinished();
                            } else {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed evaluating hex format, got " + getData().getFormattedValue()
                                        + " instead of 0x20", null));
                            }
                        }
                    }
                });

                wait.increment();
                fExpService.getSubExpressionCount(exprDmc, new DataRequestMonitor<Integer>(fExpService.getExecutor(),
                    null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData() != 0) {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed getting child count; expecting 0 got " + getData(), null));
                            } else {
                                wait.waitFinished();
                            }
                        }
                    }
                });

                wait.increment();
                fExpService.getSubExpressions(exprDmc, new DataRequestMonitor<IExpressionDMContext[]>(
                    fExpService.getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().length != 0) {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed getting children; expecting 0 got " + getData().length, null));
                            } else {
                                wait.waitFinished();
                            }
                        }
                    }
                });

                // Must use a different format or else the cache will be triggered
                wait.increment();
                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
                    IFormattedValues.OCTAL_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().getFormattedValue().equals("040")) {
                                wait.waitFinished();
                            } else {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed evaluating hex format, got " + getData().getFormattedValue()
                                        + " instead of 040", null));
                            }
                        }
                    }
                });
            }
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());

        assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
            getExprChangedCount() == 0);
        exprDmc.equals(getExprChangedContext());
        clearExprChangedData();
    }

    /**
     * This test verifies that the ExpressionService caches the evaluation of an
     * expression in a specific format. It verifies this by: 1- reading a
     * variable 2- writing to that variable 3- reading the variable in a new
     * format and seeing the new value 4- reading the variable in the same
     * format as step 1 and seeing the old value cached Note that all above
     * steps must be done within the same Runnable submitted to the executor.
     * This allows the cache to be triggered before it is invalidated by a write
     * command, since the write command will need an new executor cycle to send
     * an MI command to the back-end
     */
    @Test
    public void testWriteCache() throws Throwable {
        // Test the cache by changing a value but triggering a read before the
        // write clears the cache

        SyncUtil.runToLocation("testConcurrent");
        MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);

        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        final IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "a[1]");

        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

        fExpService.getExecutor().submit(new Runnable() {
            @Override
			public void run() {

                wait.increment();
                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
                    IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().getFormattedValue().equals("32")) {
                                wait.waitFinished();
                            } else {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed evaluating natural format, got " + getData().getFormattedValue()
                                        + " instead of 32", null));
                            }
                        }
                    }
                });

                wait.increment();
                fExpService.writeExpression(exprDmc, "56", IFormattedValues.NATURAL_FORMAT, new RequestMonitor(
                    fExpService.getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            wait.waitFinished();
                        }
                    }
                });

                // Must use a different format or else the cache will be
                // triggered
                // This will prove that the write has changed the backend
                wait.increment();
                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
                    IFormattedValues.OCTAL_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().getFormattedValue().equals("070")) {
                                wait.waitFinished();
                            } else {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed evaluating hex format, got " + getData().getFormattedValue()
                                        + " instead of 070", null));
                            }
                        }
                    }
                });

                // Test that the cache is triggered, giving us the old value
                // This happens because we are calling this operation on the
                // same executor run call.
                // NOTE that this is not a problem, because the writeExpression
                // will eventually
                // reset the cache (we'll test this below).
                wait.increment();
                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
                    IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().getFormattedValue().equals("32")) {
                                wait.waitFinished();
                            } else {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed evaluating natural format, got " + getData().getFormattedValue()
                                        + " instead of 32", null));
                            }
                        }
                    }
                });
            }
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());

        // Now that we know the writeExpressions completed and the cache was
        // reset, do a similar
        // request as above to see that the cache has indeed been reset
        wait.waitReset();
        fExpService.getExecutor().submit(new Runnable() {
            @Override
			public void run() {

                wait.increment();
                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
                    IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (!isSuccess()) {
                            wait.waitFinished(getStatus());
                        } else {
                            if (getData().getFormattedValue().equals("56")) {
                                wait.waitFinished();
                            } else {
                                wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                    "Failed evaluating natural format, got " + getData().getFormattedValue()
                                        + " instead of 56", null));
                            }
                        }
                    }
                });
            }
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());

        assertTrue("ExprChangedEvent problem: expected 1, received " + getExprChangedCount(),
            getExprChangedCount() == 1);
        exprDmc.equals(getExprChangedContext());
        clearExprChangedData();
    }

    /**
     * Test that we can correctly retrieve the address and type size of an
     * expression
     */
    @Test
    public void testExprAddress() throws Throwable {

        SyncUtil.runToLocation("testAddress");
        MIStoppedEvent stoppedEvent = SyncUtil.step(2, StepType.STEP_OVER);

        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        final IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "a");

        final IExpressionDMContext exprDmc2 = SyncUtil.createExpression(frameDmc, "a_ptr");

        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

        // First get the address of 'a' through 'a_ptr'
        fExpService.getExecutor().submit(new Runnable() {
            @Override
			public void run() {
                fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc2,
                    IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor<FormattedValueDMData>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (isSuccess()) {
                            wait.setReturnInfo(getData());
                        }

                        wait.waitFinished(getStatus());
                    }
                });
            }
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());

        String actualAddrStr = ((FormattedValueDMData) wait.getReturnInfo()).getFormattedValue();
        wait.waitReset();

        // Now check the address through our getAddressData
        checkAddressData(exprDmc, actualAddrStr, 4);

        assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
            getExprChangedCount() == 0);
    }

    
    /**
     * Test that we can correctly evaluate C expressions involving global
     * variables.
     * 
     * @return void
     */
    @Test
    public void testGlobalVariables() throws Throwable {

        // Step to a stack level of 2 to be able to test differen stack frames
        MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("locals2");

        // Create a map of expressions to expected values.
        Map<String, String[]> tests = new HashMap<String, String[]>();

        // Global variables
        tests.put("gIntVar", new String[] { "0x21F", "01037", "1000011111", "543", "543", "543" });
        tests.put("gDoubleVar", new String[] { "0x21F", "01037", "1000011111", "543", "543.54300000000001", "543.54300000000001" });
        tests.put("gCharVar", new String[] { "0x67", "0147", "1100111", "103", "103 'g'", "103 'g'" });
        tests.put("gBoolVar", new String[] { "0x0", "0", "0", "0", "false", "false" });

        tests.put("gIntArray[1]", new String[] { "0x28E", "01216", "1010001110", "654", "654", "654" });
        tests.put("gDoubleArray[1]", new String[] { "0x28E", "01216", "1010001110", "654", "654.32100000000003", "654.32100000000003" });
        tests.put("gCharArray[1]", new String[] { "0x64", "0144", "1100100", "100", "100 'd'", "100 'd'" });
        tests.put("gBoolArray[1]", new String[] { "0x0", "0", "0", "0", "false", "false" });

        tests.put("*gIntPtr", new String[] { "0x21F", "01037", "1000011111", "543", "543", "543" });
        tests.put("*gDoublePtr", new String[] { "0x21F", "01037", "1000011111", "543", "543.54300000000001", "543.54300000000001" });
        tests.put("*gCharPtr", new String[] { "0x67", "0147", "1100111", "103", "103 'g'", "103 'g'" });
        tests.put("*gBoolPtr", new String[] { "0x0", "0", "0", "0", "false", "false" });

        tests.put("gIntPtr2", new String[] { "0x8", "010", "1000", "8", "0x8" , "0x8" });
        tests.put("gDoublePtr2", new String[] { "0x5432", "052062", "101010000110010", "21554", "0x5432", "0x5432" });
        // GDB says a char* is out of bounds, but not the other pointers???
        // tests.put("gCharPtr2", new String[] { "0x4321", "041441",
        // "100001100100001", "17185", "0x4321" });
        tests.put("gBoolPtr2", new String[] { "0x12ABCDEF", "02252746757", "10010101010111100110111101111",
            "313249263", "0x12ABCDEF", "0x12ABCDEF" });

        // Try different stack frames
        executeExpressionSubTests(tests, SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0));
        executeExpressionSubTests(tests, SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 1));
        executeExpressionSubTests(tests, SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 2));
    }

    /**
     * This test verifies that the ExpressionService can handle having a
     * variable with the same name in two different methods but at the same
     * stack depth.
     */
    @Test
    public void testNamingSameDepth() throws Throwable {
    	SyncUtil.runToLocation("testName1");
    	MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);
    	IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

    	Map<String, String[]> tests = new HashMap<String, String[]>();
    	tests.put("a", new String[] { "0x1", "01", "1", "1", "1", "1" });
    	executeExpressionSubTests(tests, frameDmc);

    	SyncUtil.runToLocation("testName2");
    	stoppedEvent = SyncUtil.step(1, StepType.STEP_INTO);
    	frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
    	tests = new HashMap<String, String[]>();
    	tests.put("a", new String[] { "0x2", "02", "10", "2", "2", "2" });
    	executeExpressionSubTests(tests, frameDmc);

    	SyncUtil.runToLocation("testName1");
    	stoppedEvent = SyncUtil.step(1, StepType.STEP_INTO);
    	frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
    	tests = new HashMap<String, String[]>();
    	tests.put("a", new String[] { "0x3", "03", "11", "3", "3", "3" });
    	executeExpressionSubTests(tests, frameDmc);
    }
    
    /**
     * This test verifies that the ExpressionService can handle having a
     * variable with the same name in two methods that also have the same name
     */
    @Test
    public void testNamingSameMethod() throws Throwable {
    	SyncUtil.runToLocation("testSameName");
    	MIStoppedEvent stoppedEvent = SyncUtil.step(2, StepType.STEP_INTO);
    	IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

    	Map<String, String[]> tests = new HashMap<String, String[]>();
    	tests.put("a", new String[] { "0x1", "01", "1", "1", "1" , "1" });
    	executeExpressionSubTests(tests, frameDmc);

    	SyncUtil.step(StepType.STEP_RETURN);
    	stoppedEvent = SyncUtil.step(2, StepType.STEP_INTO);
    	frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
    	tests = new HashMap<String, String[]>();
    	tests.put("a", new String[] { "0x2", "02", "10", "2", "2", "2"  });
    	executeExpressionSubTests(tests, frameDmc);

    	SyncUtil.step(StepType.STEP_RETURN);
    	stoppedEvent = SyncUtil.step(2, StepType.STEP_INTO);
    	frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
    	tests = new HashMap<String, String[]>();
    	tests.put("a", new String[] { "0x3", "03", "11", "3", "3", "3"  });
    	executeExpressionSubTests(tests, frameDmc);
    }

    /**
     * This test makes sure that if a request for expression values are made with
     * a thread selected, the top-most stack frame is used for evaluation
     */
    @Test
    public void testThreadContext() throws Throwable {

        // Step to a stack level of 2 to be able to test differen stack frames
         SyncUtil.runToLocation("locals2");
         MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_OVER);

        // Create a map of expressions to expected values.
        Map<String, String[]> tests = new HashMap<String, String[]>();

        // First make sure we have a different value on the other stack frame and that we select
        // a frame that is not the top frame
        tests.put("lIntVar", new String[] { "0x3039", "030071", "11000000111001", "12345", "12345", "12345" });
        executeExpressionSubTests(tests, SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 1));
        
        // Now check that we get the same values as the top stack when selecting the thread only
        tests = new HashMap<String, String[]>();
        tests.put("lIntVar", new String[] { "0x1a85", "015205", "1101010000101", "6789", "6789" , "6789" });
        executeExpressionSubTests(tests, stoppedEvent.getDMContext());
    }

    /**
     * This test verifies that the ExpressionService can handle having a
     * child variable with the same name in two methods that also have the same name
     */
    @Test
    public void testChildNamingSameMethod() throws Throwable {
    	SyncUtil.runToLocation("testSameName");
    	MIStoppedEvent stoppedEvent = SyncUtil.step(4, StepType.STEP_INTO);
    	final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

    	final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

    	fExpService.getExecutor().submit(new Runnable() {
    		@Override
			public void run() {

    			// First create the var object and all its children
    			IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc, "z");

    			fExpService.getSubExpressions(
    					parentDmc, 
    					new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
    						@Override
    						protected void handleCompleted() {
    							if (!isSuccess()) {
    								wait.waitFinished(getStatus());
    							} else if (getData().length != 2) {
    								wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    										"Failed getting children; expecting 2 got " + getData().length, null));
    							} else {
									// now get the value of the child
    								final String valueStr = "1";
    								final IExpressionDMContext child = getData()[0];
    								fExpService.getFormattedExpressionValue(
    										fExpService.getFormattedValueContext(child, IFormattedValues.NATURAL_FORMAT), 
    										new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
    											@Override
    											protected void handleCompleted() {
    												if (!isSuccess()) {
    													wait.waitFinished(getStatus());
    												} else if (getData().getFormattedValue().equals(valueStr)) {
    													wait.waitFinished();
    												} else {
    													wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    															"Failed evaluating " + child.getExpression() + ", got " + getData().getFormattedValue()
    															+ " instead of " + valueStr, null));
    												}
    											}

    										});
    							}


    						}	
    					});
    		}
    	});

    	wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
    	assertTrue(wait.getMessage(), wait.isOK());
    	wait.waitReset();

    	SyncUtil.step(StepType.STEP_RETURN);
    	stoppedEvent = SyncUtil.step(4, StepType.STEP_INTO);
    	final IFrameDMContext frameDmc2 = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
    	fExpService.getExecutor().submit(new Runnable() {
    		@Override
			public void run() {

    			// First create the var object and all its children
    			IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc2, "z");

    			fExpService.getSubExpressions(
    					parentDmc, 
    					new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
    						@Override
    						protected void handleCompleted() {
    							if (!isSuccess()) {
    								wait.waitFinished(getStatus());
    							} else if (getData().length != 2) {
    								wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    										"Failed getting children; expecting 2 got " + getData().length, null));
    							} else {
									// now get the value of the child
    								final String valueStr = "2";
    								final IExpressionDMContext child = getData()[0];
    								fExpService.getFormattedExpressionValue(
    										fExpService.getFormattedValueContext(child, IFormattedValues.NATURAL_FORMAT), 
    										new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
    											@Override
    											protected void handleCompleted() {
    												if (!isSuccess()) {
    													wait.waitFinished(getStatus());
    												} else if (getData().getFormattedValue().equals(valueStr)) {
    													wait.waitFinished();
    												} else {
    													wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    															"Failed evaluating " + child.getExpression() + ", got " + getData().getFormattedValue()
    															+ " instead of " + valueStr, null));
    												}
    											}

    										});
    							}


    						}	
    					});
    		}
    	});
    	
       	wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
    	assertTrue(wait.getMessage(), wait.isOK());
    	wait.waitReset();

    	SyncUtil.step(StepType.STEP_RETURN);
    	stoppedEvent = SyncUtil.step(4, StepType.STEP_INTO);
    	final IFrameDMContext frameDmc3 = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
    	fExpService.getExecutor().submit(new Runnable() {
    		@Override
			public void run() {

    			// First create the var object and all its children
    			IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc3, "z");

    			fExpService.getSubExpressions(
    					parentDmc, 
    					new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
    						@Override
    						protected void handleCompleted() {
    							if (!isSuccess()) {
    								wait.waitFinished(getStatus());
    							} else if (getData().length != 2) {
    								wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    										"Failed getting children; expecting 2 got " + getData().length, null));
    							} else {
									// now get the value of the child
    								final String valueStr = "3";
    								final IExpressionDMContext child = getData()[0];
    								fExpService.getFormattedExpressionValue(
    										fExpService.getFormattedValueContext(child, IFormattedValues.NATURAL_FORMAT), 
    										new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
    											@Override
    											protected void handleCompleted() {
    												if (!isSuccess()) {
    													wait.waitFinished(getStatus());
    												} else if (getData().getFormattedValue().equals(valueStr)) {
    													wait.waitFinished();
    												} else {
    													wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    															"Failed evaluating " + child.getExpression() + ", got " + getData().getFormattedValue()
    															+ " instead of " + valueStr, null));
    												}
    											}

    										});
    							}


    						}	
    					});
    		}
    	});
    	
       	wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
    	assertTrue(wait.getMessage(), wait.isOK());
    	wait.waitReset();

    }

    /**
     * This test verifies that the ExpressionService properly updates
     * children variables, when we do not update the parent explicitly
     */
    @Test
    public void testUpdatingChildren() throws Throwable {
    	SyncUtil.runToLocation("testUpdateChildren");
    	MIStoppedEvent stoppedEvent = SyncUtil.step(2, StepType.STEP_OVER);
    	final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
    	doUpdateTest(frameDmc, 0);
    	
    	// Re-run the test to test out-of-scope update again
    	SyncUtil.step(StepType.STEP_RETURN);
    	stoppedEvent = SyncUtil.step(3, StepType.STEP_INTO);
    	final IFrameDMContext frameDmc2 = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
    	doUpdateTest(frameDmc2, 100);
    	
    	// Re-run the test within a different method test out-of-scope updates
    	SyncUtil.step(StepType.STEP_RETURN);
    	stoppedEvent = SyncUtil.step(3, StepType.STEP_INTO);
    	final IFrameDMContext frameDmc3 = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
    	doUpdateTest(frameDmc3, 200);

    }
    

    public void doUpdateTest(final IFrameDMContext frameDmc, final int baseValue) throws Throwable {
    	final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

    	fExpService.getExecutor().submit(new Runnable() {
    		@Override
			public void run() {

    			// First create the var object and all its children
    			IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc, "a");

    			fExpService.getSubExpressions(
    					parentDmc, 
    					new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
    						@Override
    						protected void handleCompleted() {
    							if (!isSuccess()) {
    								wait.waitFinished(getStatus());
    							} else if (getData().length != 1) {
    								wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    										"Failed getting children; expecting 1 got " + getData().length, null));
    							} else {
    								// Now list the children of this child
    								fExpService.getSubExpressions(
    										getData()[0], 
    										new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
    											@Override
    											protected void handleCompleted() {
    												final IExpressionDMContext[] childDmcs = getData();

    												if (!isSuccess()) {
    													wait.waitFinished(getStatus());
    												} else if (childDmcs.length != 2) {
    													wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    															"Failed getting children; expecting 2 got " + childDmcs.length, null));
    												} else {
    													// now get the value of the two children
    													for (int i =0; i<2; i++) {
    														final String valueStr = Integer.toString(baseValue + i + 10);
    														final int finali = i;

    														wait.increment();
    														fExpService.getFormattedExpressionValue(
    																fExpService.getFormattedValueContext(childDmcs[i], IFormattedValues.NATURAL_FORMAT), 
    																new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
    																	@Override
    																	protected void handleCompleted() {
    																		if (!isSuccess()) {
    																			wait.waitFinished(getStatus());
    																		} else if (getData().getFormattedValue().equals(valueStr)) {
    																			wait.waitFinished();
    																		} else {
    																			wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    																					"Failed evaluating " + childDmcs[finali].getExpression() + ", got " + getData().getFormattedValue()
    																					+ " instead of " + valueStr, null));
    																		}
    																	}

    																});
    													}
    												}
    											}
    										});
    							}


    						}	
    					});
    		}
    	});

    	wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
    	assertTrue(wait.getMessage(), wait.isOK());
    	wait.waitReset();

    	// Now step to change the value of a.z.x and a.z.y and verify the changed values.
    	// This will confirm that the parent "a" will have been properly updated
    	// It is a better test to do it for two children because it tests concurrent update requests
    	MIStoppedEvent stoppedEvent = SyncUtil.step(2, StepType.STEP_OVER);
    	final IFrameDMContext frameDmc2 = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

    	fExpService.getExecutor().submit(new Runnable() {
    		@Override
			public void run() {

    			// First create the var object and all its children
    			IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc2, "a");

    			fExpService.getSubExpressions(
    					parentDmc, 
    					new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
    						@Override
    						protected void handleCompleted() {
    							if (!isSuccess()) {
    								wait.waitFinished(getStatus());
    							} else if (getData().length != 1) {
    								wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    										"Failed getting children; expecting 1 got " + getData().length, null));
    							} else {
    								// Now list the children of this child
    								fExpService.getSubExpressions(
    										getData()[0], 
    										new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
    											@Override
    											protected void handleCompleted() {
    												final IExpressionDMContext[] childDmcs = getData();

    												if (!isSuccess()) {
    													wait.waitFinished(getStatus());
    												} else if (childDmcs.length != 2) {
    													wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    															"Failed getting children; expecting 2 got " + childDmcs.length, null));
    												} else {
    													// now get the value of the two children
    													for (int i =0; i<2; i++) {
    														final String valueStr = Integer.toString(baseValue + i + 20);
    														final int finali = i;

    														wait.increment();
    														fExpService.getFormattedExpressionValue(
    																fExpService.getFormattedValueContext(childDmcs[i], IFormattedValues.NATURAL_FORMAT), 
    																new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
    																	@Override
    																	protected void handleCompleted() {
    																		if (!isSuccess()) {
    																			wait.waitFinished(getStatus());
    																		} else if (getData().getFormattedValue().equals(valueStr)) {
    																			wait.waitFinished();
    																		} else {
    																			wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    																					"Failed evaluating " + childDmcs[finali].getExpression() + ", got " + getData().getFormattedValue()
    																					+ " instead of " + valueStr, null));
    																		}
    																	}

    																});
    													}
    												}
    											}
    										});
    							}


    						}	
    					});
    		}
    	});

    	wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
    	assertTrue(wait.getMessage(), wait.isOK());
    	wait.waitReset();
    }
    
    /**
     * This test creates a variable object with children (not an array) and then gets these children
     * to be deleted because of a large number of other variable objects being created.
     * We then check that the expression service can handle a request for one of those deleted children,
     * which has a complex path.
     */
    @Test
    public void testDeleteChildren() throws Throwable {
    	assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_6_7);
    	assumeGdbVersionLowerThen(ITestConstants.SUFFIX_GDB_7_3);
    	
        SyncUtil.runToLocation("testDeleteChildren");
        MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);
        final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
        
        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {

        		// First create the var object and all its children
        		IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc, "f");

        		fExpService.getSubExpressions(
        				parentDmc, 
        				new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
        					@Override
        					protected void handleCompleted() {
        						if (!isSuccess()) {
        							wait.waitFinished(getStatus());
        						} else {
        							if (getData().length != 5) {
        								wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
        										"Failed getting children; expecting 5 got " + getData().length, null));
        							} else {
        								String childStr = "((bar) f)";
        								if (!getData()[0].getExpression().equals(childStr)) {
        									wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
        											"Got child " + getData()[0].getExpression() + " instead of " + childStr, null));
        								} else {
        									// Now list the children of the first element
        									fExpService.getSubExpressions(
        											getData()[0], 
        											new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
        												@Override
        												protected void handleCompleted() {
        													if (!isSuccess()) {
        														wait.waitFinished(getStatus());
        													} else {
        														if (getData().length != 2) {
        															wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
        																	"Failed getting children; expecting 2 got " + getData().length, null));
        														} else {
        					        								String childStr = "((((bar) f)).d)";
        					        								if (!getData()[0].getExpression().equals(childStr)) {
        					        									wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
        					        											"Got child " + getData()[0].getExpression() + " instead of " + childStr, null));
        					        								} else {
        					        									wait.setReturnInfo(getData()[0]);
        								        						wait.waitFinished();
        					        								}
        														}
        													}
        												}
        											});
        								}
        							}
        						}
        					}	
        				});
        	}
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        final IExpressionDMContext deletedChildDmc = (IExpressionDMContext)wait.getReturnInfo();

        wait.waitReset();
        
        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {

        		// Now create more than 1000 expressions to trigger the deletion of the children
        		// that were created above
        		for (int i=0; i<1100; i++) {
        			IExpressionDMContext dmc = fExpService.createExpression(frameDmc, "a[" + i + "]");

        			wait.increment();
        			fExpService.getExpressionData(
        					dmc, 
        					new DataRequestMonitor<IExpressionDMData>(fExpService.getExecutor(), null) {
        						@Override
        						protected void handleCompleted() {
        							if (!isSuccess()) {
        								wait.waitFinished(getStatus());
        							} else {
        								wait.waitFinished();
        							}
        						}	
        					});
        		}
        	}
        });
        
        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();
        
        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {

        		// Evaluate the expression of a child that we know is deleted to make sure
        		// the expression service can handle that
        		fExpService.getExpressionData(
        				deletedChildDmc, 
        				new DataRequestMonitor<IExpressionDMData>(fExpService.getExecutor(), null) {
        					@Override
        					protected void handleCompleted() {
        						if (!isSuccess()) {
        							wait.waitFinished(getStatus());
        						} else {
        							wait.waitFinished();
        						}
        					}	
        				});
        	}
        });
        
        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();
        
    }
    
    /**
	 * GDB 6.7 has a bug which will cause var-update not to show
	 * the new value of 'a' if we switch the format to binary,
	 * since binary of 3 is 11 which is the same as the old value
	 * in natural format.  Our expression service should work around this.
	 * 
	 * int main() {
	 *    int a = 11;
	 *    a = 3;
	 *    return 0;
	 * }
     */
    @Test
    public void testUpdateGDBBug() throws Throwable {
        SyncUtil.runToLocation("testUpdateGDBBug");
        MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);
        final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
        
        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {
        		// First create the var object and all its children
        		IExpressionDMContext exprDmc = fExpService.createExpression(frameDmc, "a");

        		// This call will create the variable object in natural format and then change
        		// it to binary to fetch the value
                fExpService.getFormattedExpressionValue(
                		fExpService.getFormattedValueContext(exprDmc, IFormattedValues.BINARY_FORMAT), 
                		new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
                        @Override
                        protected void handleCompleted() {
                            if (!isSuccess()) {
                                wait.waitFinished(getStatus());
                            } else {
                                if (getData().getFormattedValue().equals("1011")) {
                                    wait.waitFinished();
                                } else {
                                    wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                        "Failed evaluating binary format, expected 1011 but got " +
                                        getData().getFormattedValue(), null));
                                }
                            }
                        }
                    });
        	}
        });
        
        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();
        
        // Now step to change the value of "a" and ask for it again
        stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);
        final IFrameDMContext frameDmc2 = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {
        		// First create the var object and all its children
        		IExpressionDMContext exprDmc = fExpService.createExpression(frameDmc2, "a");

        		// This call will create the variable object in natural format and then change
        		// it to binary to fetch the value
                fExpService.getFormattedExpressionValue(
                		fExpService.getFormattedValueContext(exprDmc, IFormattedValues.BINARY_FORMAT), 
                		new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
                        @Override
                        protected void handleCompleted() {
                            if (!isSuccess()) {
                                wait.waitFinished(getStatus());
                            } else {
                                if (getData().getFormattedValue().equals("11")) {
                                    wait.waitFinished();
                                } else {
                                    wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                        "Failed evaluating binary format, expected 11 but got " +
                                        getData().getFormattedValue(), null));
                                }
                            }
                        }
                    });
        	}
        });
        
        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();
    }

    /**
	 * var-update will not show a change if eval-expression is the same
	 * in the current format.  This is a problem for us because we don't
	 * know if another format changed:
	 * 
	 * int main() {
	 *    double a = 1.99;
	 *    a = 1.11;
	 * }
	 * 
	 * If a is displayed in anything but natural, both values of a are the same
	 * and we won't know it changed in the natural format.
	 * 
	 * The test below is in case GDB fixes var-update to keep track of the last
	 * printed value through eval-expression.  Until they do that, we do not have
	 * a problem because of our caching: where, if we change formats since the last
	 * var-update, it is impossible for us to set the format back
	 * to the one of the last -var-update, since we already have that value in our cache.
	 * So, the -var-update will show a change because of the new current format.
	 * But if GDB has eval-expression reset their stored printed_value, this test
	 * will fail and we'll know we have to fix something.
     */
    @Test
    public void testUpdateIssue() throws Throwable {
        SyncUtil.runToLocation("testUpdateIssue");
        MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);
        final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
        
        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {
        		// First create the var object and all its children
        		IExpressionDMContext exprDmc = fExpService.createExpression(frameDmc, "a");

        		// check that we have the proper value
        		wait.increment();
        		fExpService.getFormattedExpressionValue(
                		fExpService.getFormattedValueContext(exprDmc, IFormattedValues.NATURAL_FORMAT), 
                		new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
                        @Override
                        protected void handleCompleted() {
                            if (!isSuccess()) {
                                wait.waitFinished(getStatus());
                            } else {
                                if (getData().getFormattedValue().equals("1.99")) {
                                    wait.waitFinished();
                                } else {
                                    wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                        "Failed evaluating a, expected 1.99 but got " +
                                        getData().getFormattedValue(), null));
                                }
                            }
                        }
                    });
        		
        		// ask for hex to set the format to hex
        		wait.increment();
                fExpService.getFormattedExpressionValue(
                		fExpService.getFormattedValueContext(exprDmc, IFormattedValues.HEX_FORMAT), 
                		new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
                        @Override
                        protected void handleCompleted() {
                            if (!isSuccess()) {
                                wait.waitFinished(getStatus());
                            } else {
                                if (getData().getFormattedValue().equals("0x1")) {
                                    wait.waitFinished();
                                } else {
                                    wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                        "Failed evaluating a, expected 0x1 but got " +
                                        getData().getFormattedValue(), null));
                                }
                            }
                        }
                    });
        	}
        });
        
        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();
        
        // Now step to change the value of "a" and ask for it again but in the natural format
        stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);
        final IFrameDMContext frameDmc2 = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {
        		// First create the var object and all its children
        		IExpressionDMContext exprDmc = fExpService.createExpression(frameDmc2, "a");

        		// trigger the var-update in the last format (hex)
        		// then request the actual value in natural which should not be taken from the cache 
           		wait.increment();
                fExpService.getFormattedExpressionValue(
                		fExpService.getFormattedValueContext(exprDmc, IFormattedValues.NATURAL_FORMAT), 
                		new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
                        @Override
                        protected void handleCompleted() {
                            if (!isSuccess()) {
                                wait.waitFinished(getStatus());
                            } else {
                                if (getData().getFormattedValue().equals("1.22")) {
                                    wait.waitFinished();
                                } else {
                                    wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                        "Failed evaluating natural format, expected 1.22 but got " +
                                        getData().getFormattedValue(), null));
                                }
                            }
                        }
                    });
        	}
        });
        
        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();
    }

    /**
	 * var-update will not show a change if eval-expression is the same
	 * in the current format.  This is a problem for us because we don't
	 * know if another format changed:
	 * 
	 * int main() {
	 * 	 struct {
	 *    	double d;
	 * 	 } z;
	 * 
	 *   z.d = 1.0;
	 *   z.d = 1.22;
	 * }
	 * 
	 * If a is displayed in anything but natural, both values of a are the same
	 * and we won't know it changed in the natural format.
	 * This test uses a child to increase the value of the test.
	 * Also, it avoids the cache saving us since we start with the 1.0 value
	 * which is the same in natural and decimal
     */
    @Test
    public void testUpdateIssue2() throws Throwable {
        SyncUtil.runToLocation("testUpdateIssue2");
        MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);
        final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
        
        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {
        		
        		IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc, "z");

    			fExpService.getSubExpressions(
    					parentDmc, 
    					new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
    						@Override
    						protected void handleCompleted() {
    							if (!isSuccess()) {
    								wait.waitFinished(getStatus());
    							} else if (getData().length != 1) {
    								wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    										"Failed getting children; expecting 1 got " + getData().length, null));
    							} else {
    				        		// check that we have the proper value
    				        		// This will cache the value 1 in the natural format cache
    								final String valueStr = "1";
    								globalExpressionCtx1 = getData()[0];
    				        		
    								wait.increment();
    								fExpService.getFormattedExpressionValue(
    										fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.NATURAL_FORMAT), 
    										new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
    											@Override
    											protected void handleCompleted() {
    												if (!isSuccess()) {
    													wait.waitFinished(getStatus());
    												} else if (getData().getFormattedValue().equals(valueStr)) {
														wait.waitFinished();
    												} else {
    													wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    															"Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
    															+ " instead of " + valueStr, null));
    												}
    											}
    										});
    								
						       		// ask for decimal to set the format to decimal
    				        		wait.increment();
									fExpService.getFormattedExpressionValue(
											fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.DECIMAL_FORMAT), 
											new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
												@Override
												protected void handleCompleted() {
													if (!isSuccess()) {
														wait.waitFinished(getStatus());
													} else {
														if (getData().getFormattedValue().equals(valueStr)) {
															wait.waitFinished();
														} else {
	    													wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
	    															"Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
	    															+ " instead of " + valueStr, null));
														}
													}
												}
											});

    							}
    						}
    					});
        	}
        });
        
        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();
        
        // Now step to change the value of "a" in natural but it remains the same in decimal
        SyncUtil.step(1, StepType.STEP_OVER);

        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {

        		// trigger the var-update in the last format (decimal)
        		// then request the actual value in natural which should not be taken from the cache 
           		wait.increment();
                fExpService.getFormattedExpressionValue(
                		fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.NATURAL_FORMAT), 
                		new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
                        @Override
                        protected void handleCompleted() {
                            if (!isSuccess()) {
                                wait.waitFinished(getStatus());
                            } else {
                                if (getData().getFormattedValue().equals("1.22")) {
                                    wait.waitFinished();
                                } else {
                                    wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
                                        "Failed evaluating natural format, expected 1.22 but got " +
                                        getData().getFormattedValue(), null));
                                }
                            }
                        }
                    });
        	}
        });
        
        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();
    }

    /**
     * This test verifies the state handling of a child variable object
     * to make sure that our locking scheme works even though we must deal
     * with an update call, internally
     */
    @Test
    public void testConcurrentReadAndUpdateChild() throws Throwable {
        SyncUtil.runToLocation("testConcurrentReadAndUpdateChild");
        MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);
        final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
        
        // Ask for one value to create the var object
        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {
        		// First create the var object and all its children
        		IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc, "z");

        		wait.increment();
    			fExpService.getSubExpressions(
    					parentDmc, 
    					new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
    						@Override
    						protected void handleCompleted() {
    							if (!isSuccess()) {
    								wait.waitFinished(getStatus());
    							} else if (getData().length != 1) {
    								wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    										"Failed getting children; expecting 1 got " + getData().length, null));
    							} else {
									// now get the value of the child
    								final String valueStr = "01";
    								globalExpressionCtx1 = getData()[0];
    								fExpService.getFormattedExpressionValue(
    										fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.OCTAL_FORMAT), 
    										new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
    											@Override
    											protected void handleCompleted() {
    												if (!isSuccess()) {
    													wait.waitFinished(getStatus());
    												} else if (getData().getFormattedValue().equals(valueStr)) {
    													wait.waitFinished();
    												} else {
    													wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    															"Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
    															+ " instead of " + valueStr, null));
    												}
    											}
    										});
    							}
    						}
    					}); 
        	}
        });
        
        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();

        // Now do two reads in two different formats
        // We need to make sure that the locking properly works although we are calling
        // the internal update method, which does affect the state of the object
        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {
        		wait.increment();
        		fExpService.getFormattedExpressionValue(
        				fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.BINARY_FORMAT), 
        				new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
        					@Override
        					protected void handleCompleted() {
								final String valueStr = "1";
        						if (!isSuccess()) {
        							wait.waitFinished(getStatus());
        						} else if (getData().getFormattedValue().equals(valueStr)) {
        							wait.waitFinished();
        						} else {
        							wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
        									"Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
        									+ " instead of " + valueStr, null));
        						}
        					}
        				});

        		wait.increment();
        		fExpService.getFormattedExpressionValue(
        				fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.HEX_FORMAT), 
        				new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
        					@Override
        					protected void handleCompleted() {
								final String valueStr = "0x1";
        						if (!isSuccess()) {
        							wait.waitFinished(getStatus());
        						} else if (getData().getFormattedValue().equals(valueStr)) {
        							wait.waitFinished();
        						} else {
        							wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
        									"Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
        									+ " instead of " + valueStr, null));
        						}
        					}

        				});
        	}
        });
        
        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();
    }
    
    /**
     * This test verifies some of the logic of dealing with out-of-scope variables.
     * This particular scenario is that we create a parent with a child and then
     * have them go out of scope.  Then we request the child which will update the parent
     * and mark it as out-of-scope and recreate the child.  The parent is not re-created.
     * We then ask twice for the parent which is already known to be out-of-scope and we need
     * to make sure that the parent is re-created once and only once.
     * We had a bug where we would enter an infinite loop in this case.
     */
    @Test
    public void testConcurrentUpdateOutOfScopeChildThenParent() throws Throwable {
        SyncUtil.runToLocation("testConcurrentUpdateOutOfScopeChildThenParent");
        MIStoppedEvent stoppedEvent = SyncUtil.step(2, StepType.STEP_INTO);
        
        final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
        
        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {
        		// First create the var object and its child
        		globalExpressionCtx1 = fExpService.createExpression(frameDmc, "z");

        		wait.increment();
    			fExpService.getSubExpressions(
    					globalExpressionCtx1, 
    					new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
    						@Override
    						protected void handleCompleted() {
    							if (!isSuccess()) {
    								wait.waitFinished(getStatus());
    							} else if (getData().length != 1) {
    								wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    										"Failed getting children; expecting 1 got " + getData().length, null));
    							} else {
									// now get the value of the child
    								final String valueStr = "1";
    								globalExpressionCtx2 = getData()[0];
    								fExpService.getFormattedExpressionValue(
    										fExpService.getFormattedValueContext(globalExpressionCtx2, IFormattedValues.NATURAL_FORMAT), 
    										new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
    											@Override
    											protected void handleCompleted() {
    												if (!isSuccess()) {
    													wait.waitFinished(getStatus());
    												} else if (getData().getFormattedValue().equals(valueStr)) {
    													wait.waitFinished();
    												} else {
    													wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    															"Failed evaluating " + globalExpressionCtx2.getExpression() + ", got " + getData().getFormattedValue()
    															+ " instead of " + valueStr, null));
    												}
    											}
    										});
    							}
    						}
    					}); 
        	}
        });
        
        wait.waitUntilDone(TestsPlugin.massageTimeout(5000));
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();

        SyncUtil.step(StepType.STEP_RETURN);
        stoppedEvent = SyncUtil.step(2, StepType.STEP_INTO);
        
        // Now step to another method to make the previous variable objects out-of-scope
        // then first request the child and then the parent.  We want to test this order
        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {
        		wait.increment();
        		fExpService.getFormattedExpressionValue(
        				fExpService.getFormattedValueContext(globalExpressionCtx2, IFormattedValues.NATURAL_FORMAT), 
        				new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
        					@Override
        					protected void handleCompleted() {
								final String valueStr = "2";
        						if (!isSuccess()) {
        							wait.waitFinished(getStatus());
        						} else if (getData().getFormattedValue().equals(valueStr)) {
        							wait.waitFinished();
        						} else {
        							wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
        									"Failed evaluating " + globalExpressionCtx2.getExpression() + ", got " + getData().getFormattedValue()
        									+ " instead of " + valueStr, null));
        						}
        					}
        				});
        	}
        });
        
        wait.waitUntilDone(TestsPlugin.massageTimeout(5000));
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();

        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {
        		wait.increment();
        		fExpService.getFormattedExpressionValue(
        				fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.NATURAL_FORMAT), 
        				new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
        					@Override
        					protected void handleCompleted() {
								final String valueStr = "{...}";
        						if (!isSuccess()) {
        							wait.waitFinished(getStatus());
        						} else if (getData().getFormattedValue().equals(valueStr)) {
        							wait.waitFinished();
        						} else {
        							wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
        									"Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
        									+ " instead of " + valueStr, null));
        						}
        					}
        				});
        		
        		// Ask a second time but in a different format, to avoid the cache
        		wait.increment();
        		fExpService.getFormattedExpressionValue(
        				fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.DECIMAL_FORMAT), 
        				new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
        					@Override
        					protected void handleCompleted() {
								final String valueStr = "{...}";
        						if (!isSuccess()) {
        							wait.waitFinished(getStatus());
        						} else if (getData().getFormattedValue().equals(valueStr)) {
        							wait.waitFinished();
        						} else {
        							wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
        									"Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
        									+ " instead of " + valueStr, null));
        						}
        					}
        				});

        	}
        });
        
        wait.waitUntilDone(TestsPlugin.massageTimeout(5000));
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();
        
        //TODO although this test passes, the variable z is created twice, without being
        // deleted in GDB.  We should fix this
    }

    /**
     * This test verifies that we properly update a pointer and its child since they can both
     * change and be reported by var-update
     */
    @Test
    public void testUpdateOfPointer() throws Throwable {
        SyncUtil.runToLocation("testUpdateOfPointer");
        MIStoppedEvent stoppedEvent = SyncUtil.step(3, StepType.STEP_OVER);
        final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

        final String firstValue = "1";
        final String secondValue = "2";
        final String thirdValue = "3"; 
        
        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
        
        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {
        		
        		IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc, "z");

    			fExpService.getSubExpressions(
    					parentDmc, 
    					new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
    						@Override
    						protected void handleCompleted() {
    							if (!isSuccess()) {
    								wait.waitFinished(getStatus());
    							} else if (getData().length != 2) {
    								wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    										"Failed getting children; expecting 2 got " + getData().length, null));
    							} else {
    				        		// check that we have the proper value for both children
    								globalExpressionCtx1 = getData()[0];
    								globalExpressionCtx2 = getData()[1];

    								// Get the value of the first child
    								wait.increment();
    								fExpService.getFormattedExpressionValue(
    										fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.NATURAL_FORMAT), 
    										new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
    											@Override
    											protected void handleCompleted() {
    												if (!isSuccess()) {
    													wait.waitFinished(getStatus());
    												} else if (getData().getFormattedValue().equals(firstValue)) {
    													wait.waitFinished();
    												} else {
    													wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    															"Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
    															+ " instead of " + firstValue, null));
    												}
    											}
    										});
    								
    								// Get the value of the second child
    								wait.increment();
    								fExpService.getFormattedExpressionValue(
    										fExpService.getFormattedValueContext(globalExpressionCtx2, IFormattedValues.NATURAL_FORMAT), 
    										new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
    											@Override
    											protected void handleCompleted() {
    												if (!isSuccess()) {
    													wait.waitFinished(getStatus());
    												} else {
    													wait.setReturnInfo(getData().getFormattedValue());
    													wait.waitFinished();
    												}
    											}
    										});
    							}
    						}
    					});
        	}
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        final String pointerValue = (String)wait.getReturnInfo();
        wait.waitReset();

        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {

        		// also get the child of the pointer
        		fExpService.getSubExpressions(
        				globalExpressionCtx2, 
        				new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
        					@Override
        					protected void handleCompleted() {
        						if (!isSuccess()) {
        							wait.waitFinished(getStatus());
        						} else if (getData().length != 1) {
        							wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
        									"Failed getting children; expecting 1 got " + getData().length, null));
        						} else {
        							// Get the value of the child of the pointer
        							globalExpressionCtx2 = getData()[0];
        							fExpService.getFormattedExpressionValue(
        									fExpService.getFormattedValueContext(globalExpressionCtx2, IFormattedValues.NATURAL_FORMAT), 
        									new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
        										@Override
        										protected void handleCompleted() {
        											if (!isSuccess()) {
        												wait.waitFinished(getStatus());
        											} else if (getData().getFormattedValue().equals(firstValue)) {
        												wait.waitFinished();
        											} else {
        												wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
        														"Failed evaluating " + globalExpressionCtx2.getExpression() + ", got " + getData().getFormattedValue()
        														+ " instead of " + firstValue, null));
        											}
        										}
        									});
        						}
        					}
        				});
        	}
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();
        
        // Now step to change the values of all the children
        stoppedEvent = SyncUtil.step(2, StepType.STEP_OVER);
        final IFrameDMContext frameDmc2 = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
        
        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {
        		
        		IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc2, "z");

    			fExpService.getSubExpressions(
    					parentDmc, 
    					new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
    						@Override
    						protected void handleCompleted() {
    							if (!isSuccess()) {
    								wait.waitFinished(getStatus());
    							} else if (getData().length != 2) {
    								wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    										"Failed getting children; expecting 2 got " + getData().length, null));
    							} else {
    				        		// check that we have the proper value for both children
    								globalExpressionCtx1 = getData()[0];
    								globalExpressionCtx2 = getData()[1];

    								// Get the value of the first child
    								wait.increment();
    								fExpService.getFormattedExpressionValue(
    										fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.NATURAL_FORMAT), 
    										new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
    											@Override
    											protected void handleCompleted() {
    												if (!isSuccess()) {
    													wait.waitFinished(getStatus());
    												} else if (getData().getFormattedValue().equals(secondValue)) {
    													wait.waitFinished();
    												} else {
    													wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    															"Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
    															+ " instead of " + secondValue, null));
    												}
    											}
    										});
    								
    								// Get the value of the second child
    								wait.increment();
    								fExpService.getFormattedExpressionValue(
    										fExpService.getFormattedValueContext(globalExpressionCtx2, IFormattedValues.NATURAL_FORMAT), 
    										new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
    											@Override
    											protected void handleCompleted() {
    												if (!isSuccess()) {
    													wait.waitFinished(getStatus());
    												} else if (!getData().getFormattedValue().equals(pointerValue)) {
    													// The value should have changed
    													wait.waitFinished();
    												} else {
    													wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
    															"Failed evaluating " + globalExpressionCtx2.getExpression() + ", got " + getData().getFormattedValue()
    															+ " instead of some other value", null));												
    												}
    											}
    										});
    							}
    						}
    					});
        	}
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();

        fExpService.getExecutor().submit(new Runnable() {
        	@Override
			public void run() {

        		// also get the child of the pointer
        		fExpService.getSubExpressions(
        				globalExpressionCtx2, 
        				new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
        					@Override
        					protected void handleCompleted() {
        						if (!isSuccess()) {
        							wait.waitFinished(getStatus());
        						} else if (getData().length != 1) {
        							wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
        									"Failed getting children; expecting 1 got " + getData().length, null));
        						} else {
        							// Get the value of the child of the pointer
        							globalExpressionCtx2 = getData()[0];
        							fExpService.getFormattedExpressionValue(
        									fExpService.getFormattedValueContext(globalExpressionCtx2, IFormattedValues.NATURAL_FORMAT), 
        									new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
        										@Override
        										protected void handleCompleted() {
        											if (!isSuccess()) {
        												wait.waitFinished(getStatus());
        											} else if (getData().getFormattedValue().equals(thirdValue)) {
        												wait.waitFinished();
        											} else {
        												wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
        														"Failed evaluating " + globalExpressionCtx2.getExpression() + ", got " + getData().getFormattedValue()
        														+ " instead of " + thirdValue, null));
        											}
        										}
        									});
        						}
        					}
        				});
        	}
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        wait.waitReset();
    }
    
    /**
     * This test verifies that we properly return if we can write to different expressions
     */
    @Test
    public void testCanWrite() throws Throwable {
    	MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("testCanWrite");
    	final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

    	final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

    	fExpService.getExecutor().submit(new Runnable() {
    		@Override
			public void run() {

    			final int exprCount = 5;
    			final IExpressionDMContext dmcs[] = new IExpressionDMContext[exprCount];
    			final boolean expectedValues[] = new boolean[exprCount];

    			int exprIndex = 0;
    			dmcs[exprIndex] = fExpService.createExpression(frameDmc, "a");
    			expectedValues[exprIndex] = true;
    			exprIndex++;
    			dmcs[exprIndex] = fExpService.createExpression(frameDmc, "b");
    			expectedValues[exprIndex] = true;
    			exprIndex++;
    			dmcs[exprIndex] = fExpService.createExpression(frameDmc, "c");
    			expectedValues[exprIndex] = false;
    			exprIndex++;
    			dmcs[exprIndex] = fExpService.createExpression(frameDmc, "d");
    			expectedValues[exprIndex] = false;
    			exprIndex++;
    			dmcs[exprIndex] = fExpService.createExpression(frameDmc, "d[1]");
    			expectedValues[exprIndex] = true;
    			exprIndex++;

    			for (int index = 0; index < exprCount; index++) {
    				final int finalIndex = index;
    				wait.increment();
    				fExpService.canWriteExpression(
    						dmcs[finalIndex], 
    						new DataRequestMonitor<Boolean>(fExpService.getExecutor(), null) {
    							@Override
    							protected void handleCompleted() {
    								if (!isSuccess()) {
    									wait.waitFinished(getStatus());
    								} else if (getData() == expectedValues[finalIndex]) {
										wait.waitFinished();
									} else {
										wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
												"Failed establishing proper canWrite for  " + dmcs[finalIndex].getExpression() + 
												", got " + getData() + " instead of " + expectedValues[finalIndex], null));
									}


    							}
    						});
    			}
    		}
    	});

    	wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
    	assertTrue(wait.getMessage(), wait.isOK());
    	wait.waitReset();
    }

    /**
     * This test verifies that we properly return if we can write to an expression
     * that is an L-Value or a Constant
     */
    @Test
    public void testCanWriteLValue() throws Throwable {
    	assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_6_8);
    	MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("testCanWrite");  // Re-use test
    	final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

    	final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

    	fExpService.getExecutor().submit(new Runnable() {
    		@Override
			public void run() {

    			final int exprCount = 2;
    			final IExpressionDMContext dmcs[] = new IExpressionDMContext[exprCount];
    			final boolean expectedValues[] = new boolean[exprCount];

    			int exprIndex = 0;
    			dmcs[exprIndex] = fExpService.createExpression(frameDmc, "&a");
    			expectedValues[exprIndex] = false;
    			exprIndex++;
    			dmcs[exprIndex] = fExpService.createExpression(frameDmc, "1");
    			expectedValues[exprIndex] = false;
    			exprIndex++;

    			for (int index = 0; index < exprCount; index++) {
    				final int finalIndex = index;
    				wait.increment();
    				fExpService.canWriteExpression(
    						dmcs[finalIndex], 
    						new DataRequestMonitor<Boolean>(fExpService.getExecutor(), null) {
    							@Override
    							protected void handleCompleted() {
    								if (!isSuccess()) {
    									wait.waitFinished(getStatus());
    								} else if (getData() == expectedValues[finalIndex]) {
										wait.waitFinished();
									} else {
										wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
												"Failed establishing proper canWrite for  " + dmcs[finalIndex].getExpression() + 
												", got " + getData() + " instead of " + expectedValues[finalIndex], null));
									}


    							}
    						});
    			}
    		}
    	});

    	wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
    	assertTrue(wait.getMessage(), wait.isOK());
    	wait.waitReset();
    }

	/**
	 * Executes a group of sub-tests.
	 * 
	 * @param tests
	 *            A Map in which the key is an expression to evaluate and the
	 *            value is an array of expected values, one for each of the
	 *            formats supported by the Expressions service (hex, octal,
	 *            binary, decimal, natural, details).
	 * @param exact
	 *            Indicates whether the natural and details format should
	 *            require an exact match to the expected value, or whether the
	 *            comparison should match only up to the number of characters
	 *            provided in the expected value. Where this is used is in
	 *            expressions that involve floating point calculation. Such
	 *            calculations are not exact (even when you'd think they should
	 *            be) and these tests cannot predict what exactly the result
	 *            will be. When this param is false, then we consider it a match
	 *            if, e.g., the gdb expression resolves to "1.23456789", but the
	 *            caller only supplied "1.2345".
	 */
    private void executeExpressionSubTests(final Map<String, String[]> tests, final boolean exact, IDMContext dmc)
        throws Throwable 
    {

        // Now evaluate each of the above expressions and compare the actual
        // value against
        // the expected value.
        for (final String expressionToEvaluate : tests.keySet()) {

            // Get an IExpressionDMContext object representing the expression to
            // be evaluated.
            final IExpressionDMContext exprDMC = SyncUtil.createExpression(dmc, expressionToEvaluate);

            final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

            // Get the list of available format IDs for this expression and for
            // each one,
            // get the value of the expression
            fExpService.getExecutor().submit(new Runnable() {
                @Override
				public void run() {
                    fExpService.getAvailableFormats(exprDMC, new DataRequestMonitor<String[]>(
                        fExpService.getExecutor(), null) {
                        @Override
                        protected void handleCompleted() {
                            if (!isSuccess()) {
                                wait.waitFinished(getStatus());
                            } else {
                                final String[] formatIds = getData();

                                // Now run the current sub-test using each of
                                // the formats available for the type of
                                // the expression in the sub-test.

                                for (final String formatId : formatIds) {
                                    // Get a FormattedValueCMContext object for
                                    // the expression-formatID pair.
                                    final FormattedValueDMContext valueDmc = fExpService.getFormattedValueContext(
                                        exprDMC, formatId);

                                    // Increment the number of completed
                                    // requests to wait for, since we will send
                                    // multiple concurrent requests
                                    wait.increment();

                                    // Evaluate the expression represented by
                                    // the FormattedValueDMContext object
                                    // This actually evaluates the expression.
                                    fExpService.getFormattedExpressionValue(valueDmc,
                                        new DataRequestMonitor<FormattedValueDMData>(fExpService.getExecutor(), null) {
                                            @Override
                                            protected void handleCompleted() {
                                                if (!isSuccess()) {
                                                    wait.waitFinished(getStatus());
                                                } else {

                                                    // Get the
                                                    // FormattedValueDMData
                                                    // object from the waiter.
                                                    FormattedValueDMData exprValueDMData = getData();

                                                    final String[] expectedValues = tests.get(expressionToEvaluate);

                                                    // Check the value of the expression for correctness.
                                                    String actualValue = exprValueDMData.getFormattedValue();
                                                    String expectedValue;

                                                    if (formatId.equals(IFormattedValues.HEX_FORMAT))
                                                        expectedValue = expectedValues[0];
                                                    else if (formatId.equals(IFormattedValues.OCTAL_FORMAT))
                                                        expectedValue = expectedValues[1];
                                                    else if (formatId.equals(IFormattedValues.BINARY_FORMAT))
                                                        expectedValue = expectedValues[2];
                                                    else if (formatId.equals(IFormattedValues.DECIMAL_FORMAT))
                                                        expectedValue = expectedValues[3];
                                                    else if (formatId.equals(IFormattedValues.NATURAL_FORMAT))
                                                        expectedValue = expectedValues[4];
                                                    else if (formatId.equals(MIExpressions.DETAILS_FORMAT))
                                                    	expectedValue = expectedValues[5];
                                                    else
                                                        expectedValue = "[Unrecognized format ID: " + formatId + "]";

                                                    if ((exact == false) && 
                                                    		(formatId.equals(IFormattedValues.NATURAL_FORMAT) || formatId.equals(MIExpressions.DETAILS_FORMAT)) &&
                                                    		(expectedValue.length() < actualValue.length())) {
                                                    	actualValue = actualValue.substring(0, expectedValue.length());
                                                    }
                                                    
                                                    if (actualValue.equalsIgnoreCase(expectedValue)) {
                                                        wait.waitFinished();
                                                    } else {
                                                        String errorMsg = "Failed to correctly evalutate '"
                                                            + expressionToEvaluate + "': expected '" + expectedValue
                                                            + "', got '" + actualValue + "'";
                                                        wait.waitFinished(new Status(IStatus.ERROR,
                                                            TestsPlugin.PLUGIN_ID, errorMsg, null));
                                                    }
                                                }
                                            }
                                        });
                                }
                            }
                        }
                    });
                }
            });
            wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
            assertTrue(wait.getMessage(), wait.isOK());
            assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
                getExprChangedCount() == 0);
        }
    }
    
    private void executeExpressionSubTests(final Map<String, String[]> tests, IDMContext dmc) throws Throwable {
    	executeExpressionSubTests(tests, true, dmc);
    }
    
    private boolean addressesEqual(IExpressionDMAddress addrToTest, String addrStr, int size) {
        IAddress addr;
        if (addrStr.length() <= 10) {
            addr = new Addr32(addrStr);
        } else {
            addr = new Addr64(addrStr);
        }
        return addrToTest.getAddress().equals(addr) && addrToTest.getSize() == size;
    }
    
    private void checkAddressData(final IExpressionDMContext dmc, String actualAddrStr, int actualAddrSize) throws Throwable {
    	
        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

        fExpService.getExecutor().submit(new Runnable() {
            @Override
			public void run() {
                fExpService.getExpressionAddressData(dmc, new DataRequestMonitor<IExpressionDMAddress>(fExpService
                    .getExecutor(), null) {
                    @Override
                    protected void handleCompleted() {
                        if (isSuccess()) {
                            wait.setReturnInfo(getData());
                        }

                        wait.waitFinished(getStatus());
                    }
                });
            }
        });
        
        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());
        
       IExpressionDMAddress addr = (IExpressionDMAddress)wait.getReturnInfo();

        assertTrue("Unable to get address", addr != null);
        if (addr != null) {
        	assertTrue("Received wrong address of " + addr.toString() + " instead of (" + 
        			actualAddrStr + ", " + actualAddrSize + ")", 
        			addressesEqual(addr, actualAddrStr, actualAddrSize));
        }
    }
    
    private void doTestChildren(IExpressionDMContext exprDMC) throws Throwable 
    {
	    IExpressionDMContext[] children =
	    	getChildren(exprDMC, new String[] {"bar", "bar2", "a", "b", "c"});
	    
	    // f.bar
	    IExpressionDMContext[] children1 = 
	    	getChildren(children[0], new String[] {"d", "e"});
	    // f.bar.d
	    getChildren(children1[0], new String[0]);
	    // f.bar.e
	    IExpressionDMContext[] children2 = 
	    	getChildren(children1[1], new String[] {"e[0]", "e[1]"});
	    // f.bar.e[0]
	    getChildren(children2[0], new String[0]);
	    // f.bar.e[1]
	    getChildren(children2[1], new String[0]);
	
	    // f.bar2
	    children1 =	getChildren(children[1], new String[] {"f", "g"});
	    // f.bar2.f
	    getChildren(children1[0], new String[0]);
	    // f.bar2.g
	    children2 =	getChildren(children1[1], new String[] {"g[0]", "g[1]"});
	    // f.bar2.g[0]
	    getChildren(children2[0], new String[0]);
	    // f.bar2.g[1]
	    getChildren(children2[1], new String[0]);
	
	    // f.a
	    children1 =	getChildren(children[2], new String[] {"a[0]", "a[1]"});
	    // f.a[0]
	    getChildren(children1[0], new String[0]);
	    // f.a[1]
	    getChildren(children1[1], new String[0]);
	
	    // f.b
	    children1 =	getChildren(children[3], new String[] {"d", "e"});
	    // f.b.d
	    getChildren(children1[0], new String[0]);
	    // f.b.e
	    children2 =	getChildren(children1[1], new String[] {"e[0]", "e[1]"});
	    // f.b.e[0]
	    getChildren(children2[0], new String[0]);
	    // f.b.e[1]
	    getChildren(children2[1], new String[0]);
	
	    // f.c
	    getChildren(children[4], new String[0]);
	
	    assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
	        getExprChangedCount() == 0);
	}

    // This method tests IExspressions.getSubExpressions(IExpressionDMC, DRM);
    protected IExpressionDMContext[] getChildren(
    		final IExpressionDMContext parentDmc, 
    		String[] expectedValues) throws Throwable {

        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

        fExpService.getExecutor().submit(new Runnable() {
            @Override
			public void run() {

                fExpService.getSubExpressions(parentDmc,
                    new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
                        @Override
                        protected void handleCompleted() {
                            if (isSuccess()) {
                            	wait.setReturnInfo(getData());
                            }
                            wait.waitFinished(getStatus());
                        }
                    });
            }
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());

        IExpressionDMContext[] childDmcs = 
        	(IExpressionDMContext[]) wait.getReturnInfo();

        String[] childExpressions = new String[childDmcs.length];
        MIExpressionDMCAccessor[] childDmcsAccessor = new MIExpressionDMCAccessor[childDmcs.length];
        
        // Convert to a MIExpressionDMCAccessor to be able to call getRelativeExpression
        // Also convert to String[] to be able to use Arrays.toString()
        for (int i = 0; i < childExpressions.length; i++) {
        	childDmcsAccessor[i] = new MIExpressionDMCAccessor(childDmcs[i]);
        	childExpressions[i] = childDmcsAccessor[i].getRelativeExpression();
        }        
        assertTrue("Expected " + Arrays.toString(expectedValues) + " but got " + Arrays.toString(childExpressions),
        		expectedValues.length == childExpressions.length);

        for (int i = 0; i < childDmcsAccessor.length; i++) {
            assertEquals(expectedValues[i], childDmcsAccessor[i].getRelativeExpression());
        }
        
        return childDmcs;
    }

    // This method tests IExpressions.getSubExpressions(IExpressionDMC, int, int, DRM);
    protected IExpressionDMContext[] getChildren(
    		final IExpressionDMContext parentDmc,
    		final int startIndex,
    		final int length,
    		String[] expectedValues) throws Throwable {

        final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

        fExpService.getExecutor().submit(new Runnable() {
            @Override
			public void run() {

                fExpService.getSubExpressions(
                	parentDmc,
                	startIndex,
                	length,
                    new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
                        @Override
                        protected void handleCompleted() {
                            if (isSuccess()) {
                            	wait.setReturnInfo(getData());
                            }
                            wait.waitFinished(getStatus());
                        }
                    });
            }
        });

        wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
        assertTrue(wait.getMessage(), wait.isOK());

        IExpressionDMContext[] childDmcs = 
        	(IExpressionDMContext[]) wait.getReturnInfo();

        String[] childExpressions = new String[childDmcs.length];
        MIExpressionDMCAccessor[] childDmcsAccessor = new MIExpressionDMCAccessor[childDmcs.length];
        
        // Convert to a MIExpressionDMCAccessor to be able to call getRelativeExpression
        // Also convert to String[] to be able to use Arrays.toString()
        for (int i = 0; i < childExpressions.length; i++) {
        	childDmcsAccessor[i] = new MIExpressionDMCAccessor(childDmcs[i]);
        	childExpressions[i] = childDmcsAccessor[i].getRelativeExpression();
        }        
        assertTrue("Expected " + Arrays.toString(expectedValues) + " but got " + Arrays.toString(childExpressions),
        		expectedValues.length == childExpressions.length);

        for (int i = 0; i < childDmcsAccessor.length; i++) {
            assertTrue("Expected: " + expectedValues[i] + " got: " + childDmcsAccessor[i].getRelativeExpression(),
            		childDmcsAccessor[i].getRelativeExpression().equals(expectedValues[i]));
        }
        
        return childDmcs;
    }

    /**
     * This test verifies that large arrays are properly partitioned and 
     * the handling of "small" arrays is not affected.
     */
    @Test
    public void testArrays() throws Throwable {
    	MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("testArrays");

        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
	    
        // int array_simple[10];
	    IExpressionDMContext arraySimpleExprDMC = SyncUtil.createExpression(frameDmc, "array_simple");
	    
	    assertChildrenCount(arraySimpleExprDMC, 10);

	    // get all children
	    String[] expectedValues = new String[10];
	    for (int i = 0; i < expectedValues.length; ++i) {
	    	expectedValues[i] = String.format("array_simple[%d]", i);
	    }
	    IExpressionDMContext[] arraySimpleChildren = getChildren(arraySimpleExprDMC, expectedValues);
	    for (IExpressionDMContext ctx : arraySimpleChildren)
	    	getChildren(ctx, new String[0]);
	    
	    // get some parts of the children array
	    getChildren(arraySimpleExprDMC, 3, 2, new String[] { "array_simple[3]", "array_simple[4]" });
	    getChildren(arraySimpleExprDMC, 9, 3, new String[] { "array_simple[9]" });

	    // int array_int[24321];
	    IExpressionDMContext arrayIntExprDMC = SyncUtil.createExpression(frameDmc, "array_int");
	    assertChildrenCount(arrayIntExprDMC, 3);
	    
	    // get top level partitions: [0-9999], [10000-19999], [20000-24321]
	    IExpressionDMContext[] arrayIntPartitions =
		    	getChildren(arrayIntExprDMC, new String[] {"*((array_int)+0)@10000", "*((array_int)+10000)@10000", "*((array_int)+20000)@4321"});
	    assertTrue(String.format("Invalid number of partition: expected 3 got %d", arrayIntPartitions.length), arrayIntPartitions.length == 3);

	    // get children of the last partition: [20000-24321] 
	    expectedValues = new String[44];
	    for(int i = 0; i < expectedValues.length - 1; ++i) {
	    	expectedValues[i] = String.format("*((array_int)+%d)@100", 20000 + i*100);
	    }
	    expectedValues[expectedValues.length - 1] = "*((array_int)+24300)@21";
	    IExpressionDMContext[] arrayIntPartitions1 = getChildren(arrayIntPartitions[2], expectedValues);
	    expectedValues = new String[21];
	    for(int i = 0; i < expectedValues.length; ++i) {
	    	expectedValues[i] = String.format("array_int[%d]", 24300 + i);
	    }
	    getChildren(arrayIntPartitions1[arrayIntPartitions1.length - 1], expectedValues);

	    // foo array_foo[1200];
	    IExpressionDMContext arrayFooExprDMC = SyncUtil.createExpression(frameDmc, "array_foo");	    
	    assertChildrenCount(arrayFooExprDMC, 12);
	    expectedValues = new String[12];
	    for (int i = 0; i < expectedValues.length; ++i) {
	    	expectedValues[i] = String.format("*((array_foo)+%d)@%d", i*100, 100);
	    }
	    IExpressionDMContext[] arrayFooPartitions =	getChildren(arrayFooExprDMC, expectedValues);
	    for (int i = 0; i < arrayFooPartitions.length; ++i) {
	    	IExpressionDMContext ctx = arrayFooPartitions[i];
	    	assertTrue(String.format("Invalid DM context type: expected '%s' got '%s'", 
	    			IIndexedPartitionDMContext.class.getName(), ctx.getClass().getName()), 
	    			ctx instanceof IIndexedPartitionDMContext);
		    expectedValues = new String[100];
		    for (int j = 0; j < expectedValues.length; ++j) {
		    	expectedValues[j] = String.format("array_foo[%d]", i*100 + j);
		    }
		    IExpressionDMContext[] arrayFooChildren = getChildren(ctx, expectedValues);
		    // check the children of a couple of children
	    	getChildren(arrayFooChildren[0], new String[] {"bar", "bar2", "a", "b", "c"});
	    	getChildren(arrayFooChildren[80], new String[] {"bar", "bar2", "a", "b", "c"});
		    
		    // get parts of the children array
		    expectedValues = new String[] { String.format("array_foo[%d]", i*100 + 3), String.format("array_foo[%d]", i*100 + 4) };
		    getChildren(ctx, 3, 2, expectedValues);
		    getChildren(ctx, 99, 3, new String[] { String.format("array_foo[%d]", i*100 + 99) });
	    }
    }

    /**
     * This test verifies that large double arrays are properly partitioned
     */
    @Test
    public void testLargeDoubleArray() throws Throwable {
    	MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("testArrays");
    	
        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
        
        // char array_double_large[111][210]
	    IExpressionDMContext arrayDoubleLargeExprDMC = SyncUtil.createExpression(frameDmc, "array_double_large");
	    
	    assertChildrenCount(arrayDoubleLargeExprDMC, 2);

	    // get top level partitions: [0-99], [100-110]
	    IExpressionDMContext[] arrayTopPartitions =
		    	getChildren(arrayDoubleLargeExprDMC, new String[] {"*((array_double_large)+0)@100", "*((array_double_large)+100)@11"});
	    assertTrue(String.format("Invalid number of partition: expected 2 got %d", arrayTopPartitions.length), arrayTopPartitions.length == 2);

	    // get children child array_double_large[100-110]
	    IExpressionDMContext arrayDoubleLargeChildExprDMC = arrayTopPartitions[1];
	    
	    assertChildrenCount(arrayDoubleLargeChildExprDMC, 11);

	    String[] expectedValues = new String[11];
	    for(int i = 0; i < expectedValues.length; ++i) {
	    	expectedValues[i] = String.format("array_double_large[%d]", 100 +i);
	    }
	    IExpressionDMContext[] arrayChild = getChildren(arrayDoubleLargeChildExprDMC, expectedValues);

	    // get second level partitions: array_double_large[101][0-99], [100-199], [200-209]
	    IExpressionDMContext arrayDoubleLargeChildExprDMC2 = arrayChild[1];

	    assertChildrenCount(arrayDoubleLargeChildExprDMC2, 3);

	    IExpressionDMContext[] arraySecondLevelPartitions =
		    	getChildren(arrayDoubleLargeChildExprDMC2, new String[] {"*((array_double_large[101])+0)@100", 
		    			                                           "*((array_double_large[101])+100)@100",
		    			                                           "*((array_double_large[101])+200)@10"});
	    assertTrue(String.format("Invalid number of partition: expected 3 got %d", arraySecondLevelPartitions.length), arraySecondLevelPartitions.length == 3);

	    // get children of array_double_large[101][0-99]
	    IExpressionDMContext arrayDoubleLargeChildExprDMC3 = arraySecondLevelPartitions[0];
	    
	    assertChildrenCount(arrayDoubleLargeChildExprDMC3, 100);

	    expectedValues = new String[100];
	    for(int i = 0; i < expectedValues.length; ++i) {
	    	expectedValues[i] = String.format("array_double_large[101][%d]", i);
	    }
	    IExpressionDMContext[] arrayChild2 = getChildren(arrayDoubleLargeChildExprDMC3, expectedValues);

	    // No more children for array_double_large[101][*]	    
	    for (IExpressionDMContext ctx : arrayChild2)
	    	getChildren(ctx, new String[0]);
	    
	    // get some parts of the children array
	    getChildren(arrayDoubleLargeChildExprDMC3, 3, 2, new String[] { "array_double_large[101][3]", "array_double_large[101][4]" });
	    getChildren(arrayDoubleLargeChildExprDMC3, 98, 3, new String[] { "array_double_large[101][98]","array_double_large[101][99]" });
    }

    /**
     * This test verifies that "small" double arrays is not affected by partitions.
     */
    @Test
    public void testSmallDoubleArray() throws Throwable {
    	MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("testArrays");
    	
        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
        
        // int array_double_small[11][21];
	    IExpressionDMContext arrayDoubleSmallExprDMC = SyncUtil.createExpression(frameDmc, "array_double_small");
	    
	    assertChildrenCount(arrayDoubleSmallExprDMC, 11);

	    // get all children of array_double_small
	    String[] expectedValues = new String[11];
	    for (int i = 0; i < expectedValues.length; ++i) {
	    	expectedValues[i] = String.format("array_double_small[%d]", i);
	    }
	    IExpressionDMContext[] arrayDoubleSmallChildren = getChildren(arrayDoubleSmallExprDMC, expectedValues);
	    
	    // get all children of array_double_small[3]
	    IExpressionDMContext arrayDoubleSmallChildExprDMC = arrayDoubleSmallChildren[3];
	    
	    assertChildrenCount(arrayDoubleSmallChildExprDMC, 21);

	    expectedValues = new String[21];
	    for (int i = 0; i < expectedValues.length; ++i) {
	    	expectedValues[i] = arrayDoubleSmallChildExprDMC.getExpression() + "[" + i +"]";
	    }
	    IExpressionDMContext[] arrayDoubleSmallGrandChildren = getChildren(arrayDoubleSmallChildExprDMC, expectedValues);

	    // No more children for array_double_small[3][*]	    
	    for (IExpressionDMContext ctx : arrayDoubleSmallGrandChildren)
	    	getChildren(ctx, new String[0]);
	    
	    // get some parts of the children array
	    getChildren(arrayDoubleSmallChildExprDMC, 3, 2, new String[] { "array_double_small[3][3]", "array_double_small[3][4]" });
	    getChildren(arrayDoubleSmallChildExprDMC, 19, 3, new String[] { "array_double_small[3][19]","array_double_small[3][20]" });
    }
    
    /**
     * This test verifies that there is no RTTI support before GDB 7.5.
     */
    @Test
    public void testRTTI() throws Throwable {
    	assumeGdbVersionNot(ITestConstants.SUFFIX_GDB_6_7); // crashing
    	assumeGdbVersionLowerThen(ITestConstants.SUFFIX_GDB_7_5);
    	SyncUtil.runToLocation("testRTTI");    	
    	MIStoppedEvent stoppedEvent = SyncUtil.step(3, StepType.STEP_OVER);    	
        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
        
        // The expression we will follow as it changes types: derived.ptr
	    IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "derived.ptr");
	    
	    // Now, the expression should be type VirtualBase
	    getExpressionType(exprDmc, "VirtualBase *");
	    assertChildrenCount(exprDmc, 2);
	    // get all children
	    String[] expectedValues = new String[2];
	    expectedValues[0] = "a";
	    expectedValues[1] = "b";
	    getChildren(exprDmc, expectedValues);
	    
	    // Make the type of our expression change
	    SyncUtil.step(1, StepType.STEP_OVER);
	    // Now, the expression should be type Derived, but GDB < 7.5 does not tell us
	    // so we should still get the base type.
	    getExpressionType(exprDmc, "VirtualBase *");
	    assertChildrenCount(exprDmc, 2);
	    // The children are also the same as before
	    getChildren(exprDmc, expectedValues);
	    
	    // Make the type of our expression change
	    SyncUtil.step(1, StepType.STEP_OVER);
	    // Now, the expression should be type OtherDerived, but GDB < 7.5 does not tell us
	    // so we should still get the base type.
	    getExpressionType(exprDmc, "VirtualBase *");
	    assertChildrenCount(exprDmc, 2);
	    // The children are also the same as before
	    getChildren(exprDmc, expectedValues);
	}

    /**
     * This test verifies that we can cast to a type and then revert.
     */
    @Test
    public void testCastToType() throws Throwable {
    	SyncUtil.runToLocation("testCasting");    	
    	MIStoppedEvent stoppedEvent = SyncUtil.step(3, StepType.STEP_OVER);    	
        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
        
	    IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "int_ptr");
	    
	    assertTrue("Expression service does not support casting", fExpService instanceof IExpressions2);
	    
	    ICastedExpressionDMContext castExprDmc = 
	    		((IExpressions2)fExpService).createCastedExpression(exprDmc, new CastInfo("char*"));
	    
	    // Check type of original expression and new casted one
	    getExpressionType(exprDmc, "int *");
	    getExpressionType(castExprDmc, "char *");
	    
	    assertChildrenCount(castExprDmc, 1);
	    // get child and its value
	    final IExpressionDMContext[] children = getChildren(exprDmc, new String[] {"*int_ptr"});
	    
    	Query<String> query = new Query<String>() {
			@Override
			protected void execute(final DataRequestMonitor<String> rm) {
				fExpService.getFormattedExpressionValue(
						fExpService.getFormattedValueContext(children[0], IFormattedValues.NATURAL_FORMAT), 
						new ImmediateDataRequestMonitor<FormattedValueDMData>(rm) {
							@Override
							protected void handleCompleted() {
								rm.done(getData().getFormattedValue());
							}	
						});
			}
    	};
    	
        fSession.getExecutor().execute(query);
        String value = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
		assertEquals("65", value);
	    
		final IExpressionDMContext[] castChildren = getChildren(castExprDmc, new String[] {"*((char*)(int_ptr))"});
    	query = new Query<String>() {
			@Override
			protected void execute(final DataRequestMonitor<String> rm) {
				fExpService.getFormattedExpressionValue(
						fExpService.getFormattedValueContext(castChildren[0], IFormattedValues.NATURAL_FORMAT), 
						new ImmediateDataRequestMonitor<FormattedValueDMData>(rm) {
							@Override
							protected void handleCompleted() {
								rm.done(getData().getFormattedValue());
							}	
						});
			}
    	};        
    	fSession.getExecutor().execute(query);
        value = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
		assertEquals("65 'A'", value);
		
		// Now check that the casted type still remembers what its original type is
		assertEquals(castExprDmc.getParents()[0], exprDmc);
    }

    /**
     * This test verifies that we can display as array and then revert.
     */
    @Test
    public void testDisplayAsArray() throws Throwable {
    	SyncUtil.runToLocation("testCasting");    	
    	MIStoppedEvent stoppedEvent = SyncUtil.step(3, StepType.STEP_OVER);    	
        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
        
	    IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "int_ptr");
	    
	    assertTrue("Expression service does not support casting", fExpService instanceof IExpressions2);
	    
	    // Display as an array of 2 elements, starting at index 1
	    ICastedExpressionDMContext castExprDmc = 
	    		((IExpressions2)fExpService).createCastedExpression(exprDmc, new CastInfo(1,2));
	    
	    // Check type of original expression and new casted one
	    getExpressionType(exprDmc, "int *");
	    getExpressionType(castExprDmc, "int [2]");
	    
	    assertChildrenCount(castExprDmc, 2);
	    // get children and their values
	    final IExpressionDMContext[] children = getChildren(castExprDmc, new String[] {"int_ptr[1]", "int_ptr[2]"});
	    String[] expectedValues = new String[] {"1094861636", "1162233672"};
	    for (int i = 0; i<children.length;i++) {
	    	final IExpressionDMContext child = children[i];
	    	Query<String> query = new Query<String>() {
	    		@Override
	    		protected void execute(final DataRequestMonitor<String> rm) {
	    			fExpService.getFormattedExpressionValue(
	    					fExpService.getFormattedValueContext(child, IFormattedValues.NATURAL_FORMAT), 
	    					new ImmediateDataRequestMonitor<FormattedValueDMData>(rm) {
	    						@Override
	    						protected void handleCompleted() {
	    							rm.done(getData().getFormattedValue());
	    						}	
	    					});
	    		}
	    	};

	    	fSession.getExecutor().execute(query);
	    	String value = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
	    	assertEquals(expectedValues[i], value);
	    }
	    
		
		// Now check that the casted type still remembers what its original type is
		assertEquals(castExprDmc.getParents()[0], exprDmc);
    }

    /**
     * This test verifies that we can display as array and cast to a type together
     *  and then revert.
     */
    @Test
    public void testDisplayAsArrayAndCastToType() throws Throwable {
    	SyncUtil.runToLocation("testCasting");    	
    	MIStoppedEvent stoppedEvent = SyncUtil.step(3, StepType.STEP_OVER);    	
        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
        
	    IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "int_ptr");
	    
	    assertTrue("Expression service does not support casting", fExpService instanceof IExpressions2);

	    // We create the casted type and the displaying as an array in a single request.  This is because
	    // that is the way the UI does it.  Furthermore, the service handles the cast first, then the
	    // array, which is why our array of 2 ints becomes 8 chars, and then we only look at 4 of them
	    // starting at index 4.
	    ICastedExpressionDMContext castExprDmc = 
	    		((IExpressions2)fExpService).createCastedExpression(exprDmc, new CastInfo("char*", 4,4));
	    
	    getExpressionType(castExprDmc, "char [4]");
	    
	    assertChildrenCount(castExprDmc, 4);
	    // get children and their values
	    // The array index starts at 0 again because the cast to char[] creates a new array
	    final IExpressionDMContext[] children = 
	    		getChildren(castExprDmc, new String[] {"int_ptr[4]", "int_ptr[5]", "int_ptr[6]", "int_ptr[7]"});
	    String[] expectedValues = new String[] { "68 'D'", "67 'C'", "66 'B'", "65 'A'"};
	    for (int i = 0; i<children.length;i++) {
	    	final IExpressionDMContext child = children[i];
	    	
	    	getExpressionType(child, "char");
	    	
	    	Query<String> query = new Query<String>() {
	    		@Override
	    		protected void execute(final DataRequestMonitor<String> rm) {
	    			fExpService.getFormattedExpressionValue(
	    					fExpService.getFormattedValueContext(child, IFormattedValues.NATURAL_FORMAT), 
	    					new ImmediateDataRequestMonitor<FormattedValueDMData>(rm) {
	    						@Override
	    						protected void handleCompleted() {
	    							rm.done(getData().getFormattedValue());
	    						}	
	    					});
	    		}
	    	};

	    	fSession.getExecutor().execute(query);
	    	String value = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
	    	assertEquals(expectedValues[i], value);
	    }
	    
		
		// Now check that the casted type still remembers what its original type is
		assertEquals(castExprDmc.getParents()[0], exprDmc);
    }

    /**
     * This test verifies that we can cast an array to a different type and then revert.
     */
    @Test
    public void testCastToTypeOfArray() throws Throwable {
    	SyncUtil.runToLocation("testCasting");    	
    	MIStoppedEvent stoppedEvent = SyncUtil.step(3, StepType.STEP_OVER);    	
        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
        
	    IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "array_small");
	    
	    assertTrue("Expression service does not support casting", fExpService instanceof IExpressions2);

	    ICastedExpressionDMContext castExprDmc = 
	    		((IExpressions2)fExpService).createCastedExpression(exprDmc, new CastInfo("char[]"));
	    
	    getExpressionType(exprDmc, "int [4]");
	    getExpressionType(castExprDmc, "char [16]");
	    
	    assertChildrenCount(castExprDmc, 16);
	    // get children and their values
	    // The array index starts at 0 again because the cast to char[] creates a new array
	    final IExpressionDMContext[] children = 
	    		getChildren(castExprDmc, new String[] {"array_small[0]", "array_small[1]", "array_small[2]", "array_small[3]",
	    											   "array_small[4]", "array_small[5]", "array_small[6]", "array_small[7]",
	    											   "array_small[8]", "array_small[9]", "array_small[10]", "array_small[11]",
	    											   "array_small[12]", "array_small[13]", "array_small[14]", "array_small[15]"});
	    // Only check elements 4 through 7 for simplicity
	    String[] expectedValues = new String[] { "68 'D'", "67 'C'", "66 'B'", "65 'A'"};
	    for (int i = 4; i<8;i++) {
	    	final IExpressionDMContext child = children[i];
	    	
	    	getExpressionType(child, "char");
	    	
	    	Query<String> query = new Query<String>() {
	    		@Override
	    		protected void execute(final DataRequestMonitor<String> rm) {
	    			fExpService.getFormattedExpressionValue(
	    					fExpService.getFormattedValueContext(child, IFormattedValues.NATURAL_FORMAT), 
	    					new ImmediateDataRequestMonitor<FormattedValueDMData>(rm) {
	    						@Override
	    						protected void handleCompleted() {
	    							rm.done(getData().getFormattedValue());
	    						}	
	    					});
	    		}
	    	};

	    	fSession.getExecutor().execute(query);
	    	String value = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
	    	assertEquals(expectedValues[i-4], value);
	    }
	    
		
		// Now check that the casted type still remembers what its original type is
		assertEquals(castExprDmc.getParents()[0], exprDmc);
    }
    
    /**
     * This test verifies that we can cast to a type and then revert
     * when dealing with an array with partitions.
     */
    @Test
    public void testCastToTypeWithPartition() throws Throwable {
    	SyncUtil.runToLocation("testCasting");    	
    	MIStoppedEvent stoppedEvent = SyncUtil.step(3, StepType.STEP_OVER);    	
        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
        
	    IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "array_large");
	    
	    assertTrue("Expression service does not support casting", fExpService instanceof IExpressions2);
	    
	    ICastedExpressionDMContext castExprDmc = 
	    		((IExpressions2)fExpService).createCastedExpression(exprDmc, new CastInfo("char[]"));
	    
	    // Check type of original expression and new casted one
	    getExpressionType(exprDmc, "int [111]");
	    getExpressionType(castExprDmc, "char [444]");
	    
	    // get the 5 partition children
	    assertChildrenCount(castExprDmc, 5);
	    IExpressionDMContext[] children = getChildren(castExprDmc, new String[] {"*((((char[])(array_large)))+0)@100", "*((((char[])(array_large)))+100)@100",
	    																	     "*((((char[])(array_large)))+200)@100", "*((((char[])(array_large)))+300)@100",
	    																		 "*((((char[])(array_large)))+400)@44" });

	    // Now make sure the children of the partitions have the proper casting
	    final String[] expectedChildren = new String[100];
	    for (int i=0; i < expectedChildren.length; i++) {
	    	expectedChildren[i] = String.format("array_large[%d]", i);
	    }
	    IExpressionDMContext[] castedChildren = getChildren(children[0], expectedChildren);
	    assertEquals(100, castedChildren.length);
	    
	    // Check the type and value of a few of the first children
	    final String[] expectedValues = new String[] { "65 'A'", "0 '\\0'", "0 '\\0'", "0 '\\0'", "68 'D'", "67 'C'", "66 'B'", "65 'A'" };
	    for (int i = 0; i < expectedValues.length; i++) {
	    	final IExpressionDMContext child = castedChildren[i];
		    getExpressionType(child, "char");

	    	Query<String> query = new Query<String>() {
	    		@Override
	    		protected void execute(final DataRequestMonitor<String> rm) {
	    			fExpService.getFormattedExpressionValue(
	    					fExpService.getFormattedValueContext(child, IFormattedValues.NATURAL_FORMAT), 
	    					new ImmediateDataRequestMonitor<FormattedValueDMData>(rm) {
	    						@Override
	    						protected void handleCompleted() {
	    							rm.done(getData().getFormattedValue());
	    						}	
	    					});
	    		}
	    	};

	    	fSession.getExecutor().execute(query);
	    	String value = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
	    	assertEquals(expectedValues[i], value);
	    }	    
		
		// Now check that the casted type still remembers what its original type is
		assertEquals(castExprDmc.getParents()[0], exprDmc);
    }

    /**
     * This test verifies that we can display as array and then revert
     * when dealing with an array with partitions.
     */
    @Test
    public void testDisplayAsArrayWithPartition() throws Throwable {
    	SyncUtil.runToLocation("testCasting");    	
    	MIStoppedEvent stoppedEvent = SyncUtil.step(3, StepType.STEP_OVER);    	
        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
        
        // The expression we will cast from int to char
	    IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "array_large");
	    
	    assertTrue("Expression service does not support casting", fExpService instanceof IExpressions2);
	    
	    // Display as an array of 101 elements, starting at index 1 (we need at least 101 elements to get partitions)
	    ICastedExpressionDMContext castExprDmc = 
	    		((IExpressions2)fExpService).createCastedExpression(exprDmc, new CastInfo(1, 101));
	    
	    // Check type of original expression and new casted one
	    getExpressionType(exprDmc, "int [111]");
	    getExpressionType(castExprDmc, "int [101]");
	    
	    // Two partitions as children
	    assertChildrenCount(castExprDmc, 2);
	    IExpressionDMContext[] children = getChildren(castExprDmc, new String[] {"*(((*((array_large)+1)@101))+0)@100", "*(((*((array_large)+1)@101))+100)@1" });

	    assertTrue("Should have seen the child as a partition", children[0] instanceof IIndexedPartitionDMContext);
	    assertEquals("Wrong start index for partition", 0, ((IIndexedPartitionDMContext)children[0]).getIndex());
	    assertEquals("Wrong partition length", 100, ((IIndexedPartitionDMContext)children[0]).getLength());
	    assertTrue("Should have seen the child as a partition", children[1] instanceof IIndexedPartitionDMContext);
	    assertEquals("Wrong start index for partition", 100, ((IIndexedPartitionDMContext)children[1]).getIndex());
	    assertEquals("Wrong partition length", 1, ((IIndexedPartitionDMContext)children[1]).getLength());
	    
	    // Now make sure the children of the partitions have the proper casting and start at the proper index
	    final String[] expectedChildren = new String[100];
	    for (int i=0; i < expectedChildren.length; i++) {
	    	expectedChildren[i] = String.format("array_large[%d]", i+1);
	    }
	    IExpressionDMContext[] castedChildren = getChildren(children[0], expectedChildren);
	    assertEquals(100, castedChildren.length);
	    
	    // Check the type and value of a few of the first children
	    final String[] expectedValues = new String[] { "1094861636", "1162233672" };
	    for (int i = 0; i < expectedValues.length; i++) {
	    	final IExpressionDMContext child = castedChildren[i];
		    getExpressionType(child, "int");

	    	Query<String> query = new Query<String>() {
	    		@Override
	    		protected void execute(final DataRequestMonitor<String> rm) {
	    			fExpService.getFormattedExpressionValue(
	    					fExpService.getFormattedValueContext(child, IFormattedValues.NATURAL_FORMAT), 
	    					new ImmediateDataRequestMonitor<FormattedValueDMData>(rm) {
	    						@Override
	    						protected void handleCompleted() {
	    							rm.done(getData().getFormattedValue());
	    						}	
	    					});
	    		}
	    	};

	    	fSession.getExecutor().execute(query);
	    	String value = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
	    	assertEquals(expectedValues[i], value);
	    }	    
		
		// Now check that the casted type still remembers what its original type is
		assertEquals(castExprDmc.getParents()[0], exprDmc);
    }

    /**
     * This test verifies that we can display as array and cast to a type together
     * and then revert when dealing with an array with partitions.
     */
    @Test
    public void testDisplayAsArrayAndCastToTypeWithPartition() throws Throwable {
    	SyncUtil.runToLocation("testCasting");    	
    	MIStoppedEvent stoppedEvent = SyncUtil.step(3, StepType.STEP_OVER);    	
        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
        
	    IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "array_large");
	    
	    assertTrue("Expression service does not support casting", fExpService instanceof IExpressions2);
	    
	    ICastedExpressionDMContext castExprDmc = 
	    		((IExpressions2)fExpService).createCastedExpression(exprDmc, new CastInfo("char[]", 4, 101));
	    
	    // Check type of original expression and new casted one
	    getExpressionType(exprDmc, "int [111]");
	    getExpressionType(castExprDmc, "char [101]");
	    
	    // get the 5 partition children
	    assertChildrenCount(castExprDmc, 2);
	    IExpressionDMContext[] children = getChildren(castExprDmc, new String[] {"*(((*(((char[])(array_large))+4)@101))+0)@100", "*(((*(((char[])(array_large))+4)@101))+100)@1"});

	    assertTrue("Should have seen the child as a partition", children[0] instanceof IIndexedPartitionDMContext);
	    assertEquals("Wrong start index for partition", 0, ((IIndexedPartitionDMContext)children[0]).getIndex());
	    assertEquals("Wrong partition length", 100, ((IIndexedPartitionDMContext)children[0]).getLength());
	    assertTrue("Should have seen the child as a partition", children[1] instanceof IIndexedPartitionDMContext);
	    assertEquals("Wrong start index for partition", 100, ((IIndexedPartitionDMContext)children[1]).getIndex());
	    assertEquals("Wrong partition length", 1, ((IIndexedPartitionDMContext)children[1]).getLength());

	    // Now make sure the children of the partitions have the proper casting
	    final String[] expectedChildren = new String[100];
	    for (int i=0; i < expectedChildren.length; i++) {
	    	expectedChildren[i] = String.format("array_large[%d]", i+4);
	    }
	    IExpressionDMContext[] castedChildren = getChildren(children[0], expectedChildren);
	    assertEquals(100, castedChildren.length);
	    
	    // Check the type and value of a few of the first children
	    final String[] expectedValues = new String[] { "68 'D'", "67 'C'", "66 'B'", "65 'A'" };
	    for (int i = 0; i < expectedValues.length; i++) {
	    	final IExpressionDMContext child = castedChildren[i];
		    getExpressionType(child, "char");

	    	Query<String> query = new Query<String>() {
	    		@Override
	    		protected void execute(final DataRequestMonitor<String> rm) {
	    			fExpService.getFormattedExpressionValue(
	    					fExpService.getFormattedValueContext(child, IFormattedValues.NATURAL_FORMAT), 
	    					new ImmediateDataRequestMonitor<FormattedValueDMData>(rm) {
	    						@Override
	    						protected void handleCompleted() {
	    							rm.done(getData().getFormattedValue());
	    						}	
	    					});
	    		}
	    	};

	    	fSession.getExecutor().execute(query);
	    	String value = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
	    	assertEquals(expectedValues[i], value);
	    }	    
		
		// Now check that the casted type still remembers what its original type is
		assertEquals(castExprDmc.getParents()[0], exprDmc);		
    }
    
    /**
     * This test verifies that we display the simple return value of a method after
     * a step-return operation, but only for the first stack frame.
     */
    @Test
    public void testDisplaySimpleReturnValueForStepReturn() throws Throwable {
    	SyncUtil.runToLocation("testSimpleReturn");    	
    	MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_RETURN);
    	
    	// Check the return value is shown when looking at the first frame
        final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
    	IVariableDMData[] result = SyncUtil.getLocals(frameDmc);
    	
    	assertEquals(3, result.length);  // Two variables and one return value

    	// Return value
    	assertEquals("$2", result[0].getName());
    	assertEquals("6", result[0].getValue());
    	// first variable
    	assertEquals("a",  result[1].getName());
    	assertEquals("10", result[1].getValue());
    	// Second variable
    	assertEquals("b", result[2].getName());
    	assertEquals("false", result[2].getValue());
    	
    	// Now check how the return value will be displayed to the user
    	final IExpressionDMContext returnExprDmc = SyncUtil.createExpression(frameDmc, "$2");
		Query<IExpressionDMData> query = new Query<IExpressionDMData>() {
			@Override
			protected void execute(final DataRequestMonitor<IExpressionDMData> rm) {
				fExpService.getExpressionData(returnExprDmc, rm);
			}
		};
		fSession.getExecutor().execute(query);
		IExpressionDMData data = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
		assertEquals("testSimpleReturn() returned", data.getName());

		// Now check the actual value using the expression service
		String value = SyncUtil.getExpressionValue(returnExprDmc, IFormattedValues.DECIMAL_FORMAT);
		assertEquals("6", value);
		
    	// Now make sure we don't show the return value for another frame
		final IFrameDMContext frameDmc2 = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 1);
    	result = SyncUtil.getLocals(frameDmc2);

    	// only one variable
    	assertEquals(1, result.length);
    	assertEquals("b",  result[0].getName());
    }
    
    /**
     * This test verifies that we display the complex return value of a method after
     * a step-return operation, but only for the first stack frame.
     */
    @Test
    public void testDisplayComplexReturnValueForStepReturn() throws Throwable {
    	SyncUtil.runToLocation("testComplexReturn");    	
    	MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_RETURN);
    	
    	// Check the return value is show when looking at the first frame
        final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
    	IVariableDMData[] result = SyncUtil.getLocals(frameDmc);
    	
    	assertEquals(3, result.length);  // Two variables and one return value

    	// Return value
    	assertEquals("$2", result[0].getName());

    	// first variable
    	assertEquals("a",  result[1].getName());
    	assertEquals("10", result[1].getValue());
    	// Second variable
    	assertEquals("b", result[2].getName());
    	assertEquals("false", result[2].getValue());

    	// Now check how the return value will be displayed to the user
    	final IExpressionDMContext returnExprDmc = SyncUtil.createExpression(frameDmc, "$2");
    	Query<IExpressionDMData> query = new Query<IExpressionDMData>() {
			@Override
			protected void execute(final DataRequestMonitor<IExpressionDMData> rm) {
				fExpService.getExpressionData(returnExprDmc, rm);
			}
		};
		fSession.getExecutor().execute(query);
		IExpressionDMData data = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
		assertEquals("testComplexReturn() returned", data.getName());

		// Now check the content of the complex return expression
		doTestChildren(returnExprDmc);

    	// Now make sure we don't show the return value for another frame
		IFrameDMContext frameDmc2 = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 1);
    	result = SyncUtil.getLocals(frameDmc2);

    	// only one variable
    	assertEquals(1, result.length);
    	assertEquals("b",  result[0].getName());
    }

    /**
     * This test verifies that we properly display variables after a step-return operation
     * from a method returning void.
     */
    @Test
    public void testNoReturnValueForEmptyStepReturn() throws Throwable {
    	SyncUtil.runToLocation("noReturnValue");    	
    	MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_RETURN);
    	
    	// Check no return value is shown when looking at the first frame
        final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
    	IVariableDMData[] result = SyncUtil.getLocals(frameDmc);
    	
    	assertEquals(2, result.length);  // Two variables and one return value

    	// first variable
    	assertEquals("a",  result[0].getName());
    	assertEquals("10", result[0].getValue());
    	// Second variable
    	assertEquals("b", result[1].getName());
    	assertEquals("false", result[1].getValue());
    }

    /**
     * This tests verifies that we can obtain a child even though
     * is was already created directly.
     */
    @Test
    public void testExistingChild() throws Throwable {
        SyncUtil.runToLocation("testExistingChild");
    	MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);
        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
        
        final String PARENT_EXPR = "b";
        final String CHILD_EXPR = "((b).d)";
        final String CHILD__REL_EXPR = "d";

    	// Fetch the child directly
        final IExpressionDMContext childDmc = SyncUtil.createExpression(frameDmc, CHILD_EXPR);
    	Query<String> query = new Query<String>() {
			@Override
			protected void execute(final DataRequestMonitor<String> rm) {
				fExpService.getFormattedExpressionValue(
						fExpService.getFormattedValueContext(childDmc, IFormattedValues.NATURAL_FORMAT), 
						new ImmediateDataRequestMonitor<FormattedValueDMData>(rm) {
							@Override
							protected void handleSuccess() {
								rm.done(getData().getFormattedValue());
							}	
						});
			}
    	};
    	
        fSession.getExecutor().execute(query);
        String value = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
		assertEquals("8", value);

    	// Now fetch the child through its parent
        final IExpressionDMContext parentDmc = SyncUtil.createExpression(frameDmc, PARENT_EXPR);
    	query = new Query<String>() {
			@Override
			protected void execute(final DataRequestMonitor<String> rm) {
    			fExpService.getSubExpressions(
    					parentDmc, 
    					new ImmediateDataRequestMonitor<IExpressionDMContext[]>(rm) {
    						@Override
    						protected void handleSuccess() {
    							if (getData().length != 2) {
    					            rm.done(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, 
    					            		"Wrong number for children.  Expecting 2 but got " + getData().length, null));
    								return;
    							}
    							
    							MIExpressionDMC firstChildContext = (MIExpressionDMC)getData()[0];
    							if (firstChildContext.getExpression().equals(CHILD_EXPR) == false) {
    					            rm.done(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, 
    					            		"Got wrong first child. Expected " + CHILD_EXPR + " but got " +  firstChildContext.getExpression(), null));
    								return;
    							}

    							if (firstChildContext.getRelativeExpression().equals(CHILD__REL_EXPR) == false) {
    					            rm.done(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, 
    					            		"Got wrong relative expression. Expected " + CHILD__REL_EXPR + " but got " +  firstChildContext.getRelativeExpression(), null));
    								return;
    							}
    							
    							fExpService.getFormattedExpressionValue(
    									fExpService.getFormattedValueContext(firstChildContext, IFormattedValues.NATURAL_FORMAT), 
    									new ImmediateDataRequestMonitor<FormattedValueDMData>(rm) {
    										@Override
    										protected void handleSuccess() {
    											rm.done(getData().getFormattedValue());
    										}	
    									});

    						}
    					});
			}
    	};
    	
        fSession.getExecutor().execute(query);
        value = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
		assertEquals("8", value);
    }

    /**
     * This tests verifies that we can manually create a child of an expression
     * after that child was automatically created through the parent.
     * This case happens when selecting a child of an expression and using "Watch"
     * to create an expression automatically.
     */
    @Test
    public void testExplicitChildCreation() throws Throwable {
        SyncUtil.runToLocation("testExistingChild");
    	MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);
        IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
        
        final String PARENT_EXPR = "b";
        final String CHILD_EXPR = "((b).d)";
        final String CHILD__REL_EXPR = "d";

    	// First fetch the child through its parent
        final IExpressionDMContext parentDmc = SyncUtil.createExpression(frameDmc, PARENT_EXPR);
    	Query<String> query = new Query<String>() {
			@Override
			protected void execute(final DataRequestMonitor<String> rm) {
    			fExpService.getSubExpressions(
    					parentDmc, 
    					new ImmediateDataRequestMonitor<IExpressionDMContext[]>(rm) {
    						@Override
    						protected void handleSuccess() {
    							if (getData().length != 2) {
    					            rm.done(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, 
    					            		"Wrong number for children.  Expecting 2 but got " + getData().length, null));
    								return;
    							}
    							
    							MIExpressionDMC firstChildContext = (MIExpressionDMC)getData()[0];
    							if (firstChildContext.getExpression().equals(CHILD_EXPR) == false) {
    					            rm.done(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, 
    					            		"Got wrong first child. Expected " + CHILD_EXPR + " but got " +  firstChildContext.getExpression(), null));
    								return;
    							}

    							if (firstChildContext.getRelativeExpression().equals(CHILD__REL_EXPR) == false) {
    					            rm.done(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, 
    					            		"Got wrong relative expression. Expected " + CHILD__REL_EXPR + " but got " +  firstChildContext.getRelativeExpression(), null));
    								return;
    							}

    							fExpService.getFormattedExpressionValue(
    									fExpService.getFormattedValueContext(firstChildContext, IFormattedValues.NATURAL_FORMAT), 
    									new ImmediateDataRequestMonitor<FormattedValueDMData>(rm) {
    										@Override
    										protected void handleSuccess() {
    											rm.done(getData().getFormattedValue());
    										}	
    									});

    						}
    					});
			}
    	};
    	
        fSession.getExecutor().execute(query);
        String value = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
		assertEquals("8", value);

    	// Now access the child directly
        final IExpressionDMContext childDmc = SyncUtil.createExpression(frameDmc, CHILD_EXPR);
    	query = new Query<String>() {
			@Override
			protected void execute(final DataRequestMonitor<String> rm) {
				fExpService.getFormattedExpressionValue(
						fExpService.getFormattedValueContext(childDmc, IFormattedValues.NATURAL_FORMAT), 
						new ImmediateDataRequestMonitor<FormattedValueDMData>(rm) {
							@Override
							protected void handleSuccess() {
								rm.done(getData().getFormattedValue());
							}	
						});
			}
    	};
    	
        fSession.getExecutor().execute(query);
        value = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
		assertEquals("8", value);
    }

	protected void assertChildrenCount(final IExpressionDMContext parentDmc,
			final int expectedCount) throws Throwable {
		Query<Integer> query = new Query<Integer>() {

			@Override
			protected void execute(DataRequestMonitor<Integer> rm) {
				fExpService.getSubExpressionCount(parentDmc, rm);
			}
		};

		fExpService.getExecutor().submit(query);

		int count = query.get().intValue();

		assertThat(count, is(expectedCount));
	}

    protected String getExpressionType(final IExpressionDMContext exprDmc, final String expectedType) throws Throwable {
    	
    	Query<String> query = new Query<String>() {
			@Override
			protected void execute(final DataRequestMonitor<String> rm) {
				fExpService.getExpressionData(
						exprDmc, 
						new ImmediateDataRequestMonitor<IExpressionDMData>(rm) {
							@Override
							protected void handleCompleted() {
								rm.done(getData().getTypeName());
							}	
						});
			}
    	};
    	
        fSession.getExecutor().execute(query);
        String type = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
		assertEquals(expectedType, type);
		return type;
    }
    
	// Slight change in GDB output to fix a bug, so we must change the test a
	// little
	// Bug 320277
	@Test
	public void testDeleteChildren_7_3() throws Throwable {
		assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_3);
		SyncUtil.runToLocation("testDeleteChildren");
		MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);
		final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

		final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();

		fExpService.getExecutor().submit(new Runnable() {
			@Override
			public void run() {

				// First create the var object and all its children
				IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc, "f");

				fExpService.getSubExpressions(parentDmc,
						new DataRequestMonitor<IExpressionDMContext[]>(fExpService.getExecutor(), null) {
							@Override
							protected void handleCompleted() {
								if (!isSuccess()) {
									wait.waitFinished(getStatus());
								} else {
									if (getData().length != 5) {
										wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
												"Failed getting children; expecting 5 got " + getData().length, null));
									} else {
										String childStr = "((class bar) f)";
										if (!getData()[0].getExpression().equals(childStr)) {
											wait.waitFinished(new Status(
													IStatus.ERROR, TestsPlugin.PLUGIN_ID, "Got child "
															+ getData()[0].getExpression() + " instead of " + childStr,
													null));
										} else {
											// Now list the children of the
											// first element
											fExpService.getSubExpressions(getData()[0],
													new DataRequestMonitor<IExpressionDMContext[]>(
															fExpService.getExecutor(), null) {
														@Override
														protected void handleCompleted() {
															if (!isSuccess()) {
																wait.waitFinished(getStatus());
															} else {
																if (getData().length != 2) {
																	wait.waitFinished(new Status(IStatus.ERROR,
																			TestsPlugin.PLUGIN_ID,
																			"Failed getting children; expecting 2 got "
																					+ getData().length,
																			null));
																} else {
																	String childStr = "((((class bar) f)).d)";
																	if (!getData()[0].getExpression()
																			.equals(childStr)) {
																		wait.waitFinished(new Status(IStatus.ERROR,
																				TestsPlugin.PLUGIN_ID,
																				"Got child "
																						+ getData()[0].getExpression()
																						+ " instead of " + childStr,
																				null));
																	} else {
																		wait.setReturnInfo(getData()[0]);
																		wait.waitFinished();
																	}
																}
															}
														}
													});
										}
									}
								}
							}
						});
			}
		});

		wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
		assertTrue(wait.getMessage(), wait.isOK());
		final IExpressionDMContext deletedChildDmc = (IExpressionDMContext) wait.getReturnInfo();

		wait.waitReset();

		fExpService.getExecutor().submit(new Runnable() {
			@Override
			public void run() {

				// Now create more than 1000 expressions to trigger the deletion
				// of the children
				// that were created above
				for (int i = 0; i < 1100; i++) {
					IExpressionDMContext dmc = fExpService.createExpression(frameDmc, "a[" + i + "]");

					wait.increment();
					fExpService.getExpressionData(dmc,
							new DataRequestMonitor<IExpressionDMData>(fExpService.getExecutor(), null) {
								@Override
								protected void handleCompleted() {
									if (!isSuccess()) {
										wait.waitFinished(getStatus());
									} else {
										wait.waitFinished();
									}
								}
							});
				}
			}
		});

		wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
		assertTrue(wait.getMessage(), wait.isOK());
		wait.waitReset();

		fExpService.getExecutor().submit(new Runnable() {
			@Override
			public void run() {

				// Evaluate the expression of a child that we know is deleted to
				// make sure
				// the expression service can handle that
				fExpService.getExpressionData(deletedChildDmc,
						new DataRequestMonitor<IExpressionDMData>(fExpService.getExecutor(), null) {
							@Override
							protected void handleCompleted() {
								if (!isSuccess()) {
									wait.waitFinished(getStatus());
								} else {
									wait.waitFinished();
								}
							}
						});
			}
		});

		wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
		assertTrue(wait.getMessage(), wait.isOK());
		wait.waitReset();

	}

	/**
	 * This test verifies that there is proper RTTI support starting with GDB
	 * 7.5.
	 */
	@Test
	public void testRTTI_7_5() throws Throwable {
		assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_5);
		SyncUtil.runToLocation("testRTTI");
		MIStoppedEvent stoppedEvent = SyncUtil.step(3, StepType.STEP_OVER);
		IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);

		// The expression we will follow as it changes types: derived.ptr
		IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "derived.ptr");

		// Now, the expression should be type VirtualBase
		getExpressionType(exprDmc, "VirtualBase *");
		assertChildrenCount(exprDmc, 2);
		// get all children
		String[] expectedValues = new String[2];
		expectedValues[0] = "a";
		expectedValues[1] = "b";
		getChildren(exprDmc, expectedValues);

		// Make the type of our expression change
		SyncUtil.step(1, StepType.STEP_OVER);
		// Now, the expression should be type Derived
		getExpressionType(exprDmc, "Derived *");
		assertChildrenCount(exprDmc, 5);
		// get all children
		expectedValues = new String[5];
		expectedValues[0] = "VirtualBase";
		expectedValues[1] = "c";
		expectedValues[2] = "ptr";
		expectedValues[3] = "d";
		expectedValues[4] = "e";
		getChildren(exprDmc, expectedValues);

		// Make the type of our expression change
		SyncUtil.step(1, StepType.STEP_OVER);
		// Now, the expression should be type OtherDerived
		getExpressionType(exprDmc, "OtherDerived *");
		assertChildrenCount(exprDmc, 4);
		// get all children
		expectedValues = new String[4];
		expectedValues[0] = "VirtualBase";
		expectedValues[1] = "d";
		expectedValues[2] = "c";
		expectedValues[3] = "f";
		getChildren(exprDmc, expectedValues);
	}

}
