/*************************************************************************
 * Copyright (c) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * This component and the accompanying materials are made available
 * under the terms of the License "Eclipse Public License v1.0"
 * which accompanies this distribution, and is available
 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
 *
 * Initial Contributors:
 * Nokia Corporation - initial contribution.
 *
 * Contributors:
 * Broadcom - use newly created top-level ForwardReference type
 *
 * Description: 
 *
 *************************************************************************/

package org.eclipse.cdt.debug.edc.tests;


import java.math.BigInteger;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.debug.edc.arm.IARMSymbol;
import org.eclipse.cdt.debug.edc.debugger.tests.SimpleDebuggerTest;
import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
import org.eclipse.cdt.debug.edc.internal.PathUtils;
import org.eclipse.cdt.debug.edc.internal.services.dsf.EDCSymbolReader;
import org.eclipse.cdt.debug.edc.internal.services.dsf.Symbols;
import org.eclipse.cdt.debug.edc.internal.symbols.ArrayType;
import org.eclipse.cdt.debug.edc.internal.symbols.ConstType;
import org.eclipse.cdt.debug.edc.internal.symbols.FieldType;
import org.eclipse.cdt.debug.edc.internal.symbols.IArrayBoundType;
import org.eclipse.cdt.debug.edc.internal.symbols.IArrayType;
import org.eclipse.cdt.debug.edc.internal.symbols.IBasicType;
import org.eclipse.cdt.debug.edc.internal.symbols.ICPPBasicType;
import org.eclipse.cdt.debug.edc.internal.symbols.ICompositeType;
import org.eclipse.cdt.debug.edc.internal.symbols.IEnumeration;
import org.eclipse.cdt.debug.edc.internal.symbols.IField;
import org.eclipse.cdt.debug.edc.internal.symbols.IForwardTypeReference;
import org.eclipse.cdt.debug.edc.internal.symbols.IInheritance;
import org.eclipse.cdt.debug.edc.internal.symbols.ILexicalBlockScope;
import org.eclipse.cdt.debug.edc.internal.symbols.IMayBeQualifedType;
import org.eclipse.cdt.debug.edc.internal.symbols.IPointerType;
import org.eclipse.cdt.debug.edc.internal.symbols.IQualifierType;
import org.eclipse.cdt.debug.edc.internal.symbols.ITemplateParam;
import org.eclipse.cdt.debug.edc.internal.symbols.ITypedef;
import org.eclipse.cdt.debug.edc.internal.symbols.InheritanceType;
import org.eclipse.cdt.debug.edc.internal.symbols.SubroutineType;
import org.eclipse.cdt.debug.edc.internal.symbols.TypedefType;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfCompileUnit;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfDebugInfoProvider;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfDebugInfoProvider.AttributeList;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfDebugInfoProvider.PublicNameInfo;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfFrameRegisterProvider.DefCFAExpressionInstruction;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfFrameRegisterProvider.DefCFAInstruction;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfFrameRegisterProvider.ExpressionInstruction;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfFrameRegisterProvider.FrameDescriptionEntry;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfFrameRegisterProvider.InstructionState;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfFrameRegisterProvider.NopInstruction;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfFrameRegisterProvider.RegisterInstruction;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfFrameRegisterProvider.RememberStateInstruction;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfFrameRegisterProvider.RestoreInstruction;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfFrameRegisterProvider.RestoreStateInstruction;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfFrameRegisterProvider.SameValueInstruction;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfFrameRegisterProvider.UndefinedInstruction;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfFrameRegisterProvider.ValueExpressionInstruction;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfFrameRegisterProvider.ValueOffsetInstruction;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfInfoReader;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfMessages;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfVariable;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.ForwardTypeReference;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.LocationEntry;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.LocationExpression;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.LocationList;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.RangeList;
import org.eclipse.cdt.debug.edc.internal.symbols.files.ExecutableSymbolicsReaderFactory;
import org.eclipse.cdt.debug.edc.internal.symbols.files.FileStatistics;
import org.eclipse.cdt.debug.edc.launch.EDCLaunch;
import org.eclipse.cdt.debug.edc.services.EDCServicesTracker;
import org.eclipse.cdt.debug.edc.symbols.ICompileUnitScope;
import org.eclipse.cdt.debug.edc.symbols.IEDCSymbolReader;
import org.eclipse.cdt.debug.edc.symbols.IEnumerator;
import org.eclipse.cdt.debug.edc.symbols.IExecutableSection;
import org.eclipse.cdt.debug.edc.symbols.IExecutableSymbolicsReader;
import org.eclipse.cdt.debug.edc.symbols.IFunctionScope;
import org.eclipse.cdt.debug.edc.symbols.ILocationProvider;
import org.eclipse.cdt.debug.edc.symbols.IModuleScope;
import org.eclipse.cdt.debug.edc.symbols.IScope;
import org.eclipse.cdt.debug.edc.symbols.ISymbol;
import org.eclipse.cdt.debug.edc.symbols.IType;
import org.eclipse.cdt.debug.edc.symbols.IVariable;
import org.eclipse.cdt.debug.edc.symbols.TypeUtils;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.utils.Addr32;
import org.eclipse.cdt.utils.Addr64;
import org.eclipse.core.runtime.IPath;
import org.junit.Assert;
import org.junit.Test;

/**
 * 
 */
public class TestDwarfReader extends AbstractDwarfReaderTest {

	private static class DwarfFrameRegisterAlbum extends SimpleDebuggerTest {
		/* (non-Javadoc)
		 * @see org.eclipse.cdt.debug.edc.debugger.tests.SimpleDebuggerTest#getRequiredLaunchConfigurationType()
		 */
		@Override
		protected String getRequiredLaunchConfigurationType() {
			return "com.nokia.cdt.debug.launch.systemTRKLaunch";
		}
		@Override
		public String getAlbumName() {
			return "RegisterFrameTestsBlackFlagRVCT.dsa";
		}
		
		public EDCLaunch getLaunch() {
			return launch;
		}
		
		public  DsfSession getSession() {
			return session;
		}

		static DwarfFrameRegisterAlbum openAlbum() {
			return new DwarfFrameRegisterAlbum();
		}
	}
	
	private DwarfFrameRegisterAlbum dwarfAlbum;

	@Test
	public void testSymFromExeDetect() throws Exception {
		for (TestInfo info : testInfos.values()) {
			if (info.exeFile == null) continue;
			IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.exeFile);
			assertNotNull(symbolReader);
			System.out.println("Sym for exe " + info.exeFile + " is " + symbolReader.getSymbolFile());
			assertEquals(info.symFile, symbolReader.getSymbolFile());
			assertNotNull(symbolReader.getExecutableSections());
			IExecutableSection dsect = symbolReader.findExecutableSection(DwarfInfoReader.DWARF_DEBUG_INFO);
			assertNotNull(dsect);
			assertEquals(".debug_info", dsect.getName());
			System.out.println("  Dwarf section: " + dsect.toString());
			dsect.dispose();
		}
	}

	/**
	 * This should be a quick check, not a slow one
	 * @throws Exception
	 */
	@Test
	public void testSymDetect() throws Exception {
		long time = System.currentTimeMillis();
		_testSymDetect();
		long span = System.currentTimeMillis() - time;
		System.out.println(span + " ms (testSymDetect)");
	}

	private void _testSymDetect() {
		for (TestInfo info : testInfos.values()) {
			System.out.println("Checking sym for " + info.symFile);
			IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.symFile);
			assertNotNull(info.symFile.lastSegment(), symbolReader);
			assertTrue(info.symFile.lastSegment(), symbolReader.hasRecognizedDebugInformation());
		}
	}

	@Test
	public void testSourceFiles() throws Exception {
		long time = System.currentTimeMillis();
		_testSourceFiles();
		long span = System.currentTimeMillis() - time;
		System.out.println(span + " ms (testSourceFiles)");
	}

	private void _testSourceFiles() {
		for (TestInfo info : testInfos.values()) {
			if (info.numberOfSources == 0) continue;
			IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.symFile);
			String[] sources=  symbolReader.getSourceFiles();
			assertNotNull(sources);
			//System.out.println(info.symFile.lastSegment() + " : " + sources.length);
			assertEquals(info.symFile.lastSegment(), info.numberOfSources, sources.length);
		}
	}

	@Test
	public void testCompileUnits() throws Exception {
		long time = System.currentTimeMillis();
		_testCompileUnits();
		long span = System.currentTimeMillis() - time;
		System.out.println(span + " ms (testCompileUnits)");
		
		// This is for information. 
		new FileStatistics();	// nothing but for code coverage.
		FileStatistics.dump();
	}

	private void _testCompileUnits() {
		for (TestInfo info : testInfos.values()) {
			if (info.numberOfModuleScopeChildren == 0) continue;
			IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.symFile);
			Collection<IScope> scopes=  symbolReader.getModuleScope().getChildren();
			assertNotNull(scopes);
			//System.out.println(info.symFile.lastSegment() + ": " + scopes.size());
			//for (IScope kid : scopes)
			//	System.out.println("\t" + kid.getName());
			assertEquals(info.symFile.lastSegment(), info.numberOfModuleScopeChildren, scopes.size());
		}
	}

	@Test
	public void testGlobalVariables() throws Exception {
		long time = System.currentTimeMillis();
		_testGlobalVariables();
		long span = System.currentTimeMillis() - time;
		System.out.println(span + " ms (testGlobalVariables)");
	}

	private void _testGlobalVariables() {
		for (TestInfo info : testInfos.values()) {
			if (info.numberOfVariables == 0) continue;
			IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.symFile);
			Collection<IVariable> variables = symbolReader.getModuleScope().getVariables();
			assertNotNull(variables);
			//System.out.println(info.symFile.lastSegment() + ": " + variables.size());
			assertEquals(info.symFile.lastSegment(), info.numberOfVariables, variables.size());
		}
	}

	/**
	 * Test that we can find and get types for globals in compilation units
	 * @throws Exception
	 */
 	@Test
	public void testPerCUGlobals() throws Exception {
		long time = System.currentTimeMillis();
		_testPerCUGlobals();
		long span = System.currentTimeMillis() - time;
		System.out.println(span + " ms (testPerCUGlobals)");
	}

	private void _testPerCUGlobals() {
		// check all globals
		for (TestInfo info : testInfos.values()) {
			IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.symFile);
			
			boolean discover = false;
			
			if (discover) {
				// DISCOVERY (rerun if reader gets better and paste into static block at top) 
				//System.out.println(info.symFile);
				boolean any = false;
				for (String srcFile : symbolReader.getSourceFiles()) {
					List<ICompileUnitScope> cusList = symbolReader.getModuleScope().getCompileUnitsForFile(PathUtils.createPath(srcFile));
					any = true;
					for (ICompileUnitScope cus : cusList) {
						Collection<IVariable> vars = cus.getVariables();
						if (!vars.isEmpty()) {
							//System.out.println(srcFile +" : # vars = " + vars.size());
							for (IVariable var : vars) {
								//System.out.println(var.getName() + " : " + getTypeName(var.getType()));
								System.out.println(MessageFormat.format(
										"setCUVariableInfo(\"{0}\", \"{1}\", \"{2}\", \"{3}\");",
										info.symFile.lastSegment(),
										srcFile,
										var.getName(),
										getTypeName(var.getType())));
							}
						}
					}
				}
				assertTrue("Any CUs in " + info.symFile, any);
			} else {
				if (info.cuVarMap == null)
					continue;

				for (Map.Entry<String, Map<String, VariableInfo>> entry : info.cuVarMap.entrySet()) {
					String cu = entry.getKey();
					List<ICompileUnitScope> cusList = symbolReader.getModuleScope().getCompileUnitsForFile(PathUtils.createPath(cu));
					assertNotNull(info.symFile + " : " + cu, cusList);
					for (Map.Entry<String, VariableInfo> varEntry : entry.getValue().entrySet()) {
						// TODO: getter by name
						boolean found = false;
						for (ICompileUnitScope cus : cusList) {
							for (IVariable var : cus.getVariables()) {
								if (var.getName().equals(varEntry.getKey())) {
									found = true;
									VariableInfo varInfo = varEntry.getValue();
									assertNotNull(var.getType());
									String theTypeName = getTypeName(var.getType());
									System.out.println(info.symFile + " : " + cu + " : " + var.getName() + " = " + theTypeName); 
									assertEquals(info.symFile + " : " + cu + " : " + var.getName(),
											varInfo.typeName, theTypeName);
								}
							}
						}
						assertTrue(info.symFile + " : " + cu + " : " + entry.getKey(), found);
					}
				}
			}
		}
	}

	/**
	 * Test that we can find and resolve all types.  The lazy type evaluator only
	 * is lazy as far as dereferenced types go, so we don't check anything but names
	 * and type trees here.
	 * 
	 * This test isn't exhaustive; it just ferrets out assertion errors and null pointer references.
	 * @throws Exception
	 */
	@Test
	public void testTypes() throws Exception {
		for (TestInfo info : testInfos.values()) {
			if (info.numberOfTypes == 0) continue;
			IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.symFile);
			
			boolean discover = false;
			
			if (discover) {
				// DISCOVERY 
				//System.out.println(info.symFile);
				int cnt = symbolReader.getModuleScope().getTypes().size();
				//for (IType type : symbolReader.getModuleScope().getTypes()) {
				//	System.out.println(getTypeName(type));
				//}
				System.out.println(info.symFile + " : " + cnt);
			}
			else {
				Collection<IType> types = symbolReader.getModuleScope().getTypes();
				assertNotNull(types);
				System.out.println("Initial: " + types.size());
				
				// this should trigger expansion of subtypes
				int idx = 1;
				for (IType type : types) {
					doTestType(idx, type);
					idx++;
				}
				
				types = symbolReader.getModuleScope().getTypes();
				System.out.println("After: " + types.size());
				assertEquals(info.symFile.lastSegment(), info.numberOfTypes, types.size());
				
				// now, ensure the types are still there in a new reader
				symbolReader = Symbols.getSymbolReader(info.symFile);
				assertEquals(info.symFile.lastSegment(), info.numberOfTypes, symbolReader.getModuleScope().getTypes().size());
			}
		}
	}

	/**
	 * @param idx
	 * @param type
	 */
	private void doTestType(int idx, IType type) {
		String name = getTypeName(type);
		if (type.getByteSize() == 0) {
			IType checkType = type;
			while (checkType != null) {
				if (checkType instanceof IQualifierType || checkType instanceof TypedefType)
					checkType = checkType.getType();
				else
					break;
			}
			if (checkType == null)
				return;
			if (checkType instanceof ICompositeType) {
				return; // this is allowed, even though the spec says it should be here.
						// we can't fix it up, because even if we sum up the field sizes, we can't predict the extra space used by alignment
			}
			if (checkType instanceof SubroutineType || checkType instanceof InheritanceType)
				return; // this is allowed
			
			if (checkType instanceof FieldType) {
				doTestType(idx, ((FieldType) checkType).getType());
				return;
			}
			if (checkType instanceof ArrayType) {
				for (IArrayBoundType bound : ((ArrayType) checkType).getBounds()) {
					if (bound.getElementCount() == 0)
						return;
				}
				// else, should have more
			}
				
			if (checkType == ForwardTypeReference.NULL_TYPE_ENTRY)
				return; // should not get here, but something else tests this
			if (checkType instanceof ICPPBasicType && ((ICPPBasicType) checkType).getBaseType() == ICPPBasicType.t_void)
				return; // yup
			if (checkType instanceof ITemplateParam) {
				if (checkType.getType().getName().equals("class TModelEntry")) {
					assertNull(((ITemplateParam)checkType).getProperties());
					assertNull(((ITemplateParam)checkType).getScope());
					assertTrue(((ITemplateParam)checkType).getType() instanceof ICompositeType);
					
					// following is not quite meaningful but to beef up method coverage.
					checkType.setType(null);
					checkType.dispose();
				}
				return; // no inherent size
			}
			if (checkType instanceof IArrayBoundType)
				return; // no inherent size
			fail(name + " has zero size");
		}
		if (idx % 1000 == 0) System.out.print(".");
	}

	/**
	 * This method is useful for dumping the types actually parsed and comparing them with each other.
	 */
	/* 
	public void testTypesXX() throws Exception {
		for (TestInfo info : testInfos.values()) {
			if (!info.symFile.lastSegment().contains("gcce"))
				continue;
			
			IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.symFile);
			
			Collection<IType> types = symbolReader.getModuleScope().getTypes();
			assertNotNull(types);
			
			// force expansion
			for (IType type : types) {
				//String name = 
				getTypeName(type);
			}
			
			// start again
			types = symbolReader.getModuleScope().getTypes();
			List<String> names = new ArrayList<String>();
			for (IType type : types) {
				names.add(getTypeName(type));
			}
			//Collections.sort(names);
			String fname = "true".equals(System.getProperty(Symbols.DWARF_USE_NEW_READER)) ? "new.txt" : "old.txt";
			PrintStream dump = new PrintStream(new File("/tmp/" + fname));
			for (String name : names) {
				dump.println(name);
			}
			dump.close();
		}
	}
	*/

	/**
	 * Test case(s) for specific type parses
	 * @throws Exception
	 */
	@Test
	public void testSpecificTypes1a() throws Exception {
		IEDCSymbolReader symbolReader = Symbols.getSymbolReader(getFile("BlackFlag_rvct.sym"));
		List<ICompileUnitScope> cuList = getCompileUnitsFor(symbolReader, "dbg_multipleInheritance.cpp");
		if (cuList.isEmpty())
			cuList = getCompileUnitsFor(symbolReader, "dbg_multipleinheritance.cpp");
		assertFalse(cuList.isEmpty());
		List<ICompileUnitScope> cuhList = getCompileUnitsFor(symbolReader, "dbg_multipleInheritance.h");
		assertFalse(cuhList.isEmpty());
		
		// multipleInheritance
		IFunctionScope function = null;
		for (ICompileUnitScope cu : cuList) {
			function = cu.getFunctionAtAddress(new Addr32(0xa940));
			if (function != null)
				break;
		}
		assertNotNull(function);
		assertEquals("multipleInheritance", function.getName());
		for (IVariable var : function.getVariablesInTree()) {
			if (var.getName().equals("pdv1")) {		
				// check forward reference behavior
				if (   var instanceof DwarfVariable
					&& (((DwarfVariable)var).getRawType() instanceof IForwardTypeReference)) {
					IForwardTypeReference forward = (IForwardTypeReference)(((DwarfVariable)var).getRawType());
					assertEquals("", forward.getName());
					assertEquals(4, forward.getByteSize());
					assertNull(forward.getProperties());
					assertNotNull(forward.getScope());
					IType resolvedType = forward.getType();
					assertEquals("class Derv1", resolvedType.getName());
					forward.setType(resolvedType);
					assertEquals("class Derv1", forward.getType().getName());
				}

				IType type = var.getType();
				assertFalse(type instanceof IForwardTypeReference);	// should not peek through interface
				assertNotNull(type);
				assertEquals(function, var.getScope());
				_testSpecificTypePointerToDerv1(type);
			}
		}

		// okay place to check accessibility of base link address & provider string
		DwarfDebugInfoProvider provider = getDwarfDebugInfoProvider(symbolReader);
		if (provider == null)
			return;

		// ensure placeholder null type has correct fields
		IType nullEntryType = ForwardTypeReference.NULL_TYPE_ENTRY;
		assertEquals(0, nullEntryType.getByteSize());
		assertEquals(DwarfMessages.DwarfDebugInfoProvider_UnhandledType, nullEntryType.getName());
		assertEquals(0, nullEntryType.getProperties().size());
		assertNull(nullEntryType.getScope());
		assertNull(nullEntryType.getType());
		boolean throwException = false;
		try {
			nullEntryType.setType(null);
		} catch (IllegalStateException ise) {
			throwException = true;
		}
		assertTrue(throwException);
		nullEntryType.dispose();	// should do nothing
		assertEquals(0, nullEntryType.getProperties().size()); // still alive
		
		assertEquals(provider.getBaseLinkAddress().toString(), "32768");
		IModuleScope moduleScope = provider.getModuleScope();
		assertNotNull(moduleScope);
		assertTrue(moduleScope.getEnumerators().size() == 0);
		assertTrue(moduleScope.getSymbolFile().toPortableString().contains("BlackFlag_rvct.sym"));
		
		ICompileUnitScope cuScope = provider.getCompileUnitForAddress(new Addr64("32768"));
		assertNotNull(cuScope);
		assertTrue(cuScope instanceof DwarfCompileUnit);
		DwarfCompileUnit cu = (DwarfCompileUnit)cuScope;
		cu.setParsedForVariables(false);
		assertFalse(cu.isParsedForVariables());
		cu.setParsedForVariables(true);
		assertTrue(cu.isParsedForVariables());
		AttributeList attrList = cu.getAttributeList();
		cu.setAttributes(null);
		assertNull(cu.getAttributeList());
		cu.setAttributes(attrList);
		assertNotNull(cu.getAttributeList());
		assertNotNull(cu.toString());
		assertNotNull(provider.toString());
	}

	/**
	 * Test case(s) for specific type parses, from a focused parse
	 * @throws Exception
	 */
	@Test
	public void testSpecificTypes1b() throws Exception {
		IEDCSymbolReader symbolReader = Symbols.getSymbolReader(getFile("BlackFlag_rvct.sym"));
		DwarfDebugInfoProvider provider = getDwarfDebugInfoProvider(symbolReader);
		if (provider == null)
			return;
		
		// DW_TAG_pointer_type -> Derv1
		IType type = provider.readType(0x1cb139);
		_testSpecificTypePointerToDerv1(type);

	}

	/**
	 * @param type 
	 */
	private void _testSpecificTypePointerToDerv1(IType type) {
		assertTrue(type.getName(), type instanceof IPointerType);
		
		IType derv1 = ((IPointerType) type).getType();
		assertFalse(derv1 instanceof IForwardTypeReference);	// should not peek through interface
		assertNotNull(derv1);
		assertTrue(derv1.getName(), derv1 instanceof ICompositeType);
		
		ICompositeType derv1Comp = (ICompositeType) derv1;
		assertEquals("class Derv1", derv1Comp.getName());
		assertEquals(1, derv1Comp.fieldCount());
		assertEquals(2, derv1Comp.inheritanceCount());
		IField vptrField = derv1Comp.findFields("__vptr")[0];
		assertNotNull("__vptr", vptrField);
		assertEquals(0, derv1Comp.getTemplateParams().length);
		assertEquals(ICompositeType.k_class, derv1Comp.getKey());
				
		// inherited fields also visible
		IField xField = derv1Comp.findFields("x")[0];
		assertNotNull("x", xField);
		
		// x is in an inherited type
		IInheritance[] inhs = derv1Comp.getInheritances();
		assertEquals(2, inhs.length);
		
		IType base1 = inhs[1].getType();
		assertNotNull(base1);
		assertEquals("class Base1", base1.getName());
		assertTrue(base1.getName(), base1 instanceof ICompositeType);
		
		ICompositeType base1Comp = (ICompositeType) base1;
		assertEquals(1, base1Comp.fieldCount());
		assertEquals(0, base1Comp.inheritanceCount());
		xField = base1Comp.findFields("x")[0];
		assertNotNull("x", xField);
		
		IType base2 = inhs[0].getType();
		assertNotNull(base2);
		assertEquals("class Base2", base2.getName());
		assertTrue(base2.getName(), base2 instanceof ICompositeType);
		
		ICompositeType base2Comp = (ICompositeType) base2;
		assertEquals(0, base2Comp.fieldCount());
		assertEquals(0, base2Comp.inheritanceCount());
		
		// watch for side effects (late adding of inherited fields)
		assertEquals(1, derv1Comp.fieldCount());
		assertEquals(2, derv1Comp.inheritanceCount());
		assertEquals(1, base1Comp.fieldCount());
		assertEquals(0, base1Comp.inheritanceCount());
		assertEquals(0, base2Comp.fieldCount());
		assertEquals(0, base2Comp.inheritanceCount());
		

		// the class is in the header
		IScope classScope = ((IPointerType)type).getType().getScope();
		assertTrue(classScope instanceof ICompileUnitScope);
		IPath path = ((ICompileUnitScope) classScope).getFilePath();
		assertTrue(path.toString(), path.lastSegment().equalsIgnoreCase("dbg_multipleInheritance.h"));

		// the pointer type is declared in a function (either "show3", due to "this", or the one we looked in)
		assertTrue(type.getScope() instanceof IFunctionScope);
		//assertEquals(((IFunctionScope) type.getScope()).getName(), "show3");
		IScope fileScope = type.getScope().getParent();
		assertTrue(fileScope instanceof ICompileUnitScope);
		path = ((ICompileUnitScope) fileScope).getFilePath();
		assertTrue(path.toString(), path.lastSegment().equalsIgnoreCase("dbg_multipleInheritance.cpp"));
	}

	/**
	 * Test case(s) for specific type parses
	 * @throws Exception
	 */
	@Test
	public void testSpecificTypes2() throws Exception {
		IEDCSymbolReader symbolReader = Symbols.getSymbolReader(getFile("BlackFlag_rvct.sym"));
		List<ICompileUnitScope> cuList = getCompileUnitsFor(symbolReader, "dbg_multipleInheritance.cpp");
		if (cuList.isEmpty())
			cuList = getCompileUnitsFor(symbolReader, "dbg_multipleinheritance.cpp");
		assertFalse(cuList.isEmpty());
		List<ICompileUnitScope> cuhList = getCompileUnitsFor(symbolReader, "dbg_multipleInheritance.h");
		assertFalse(cuhList.isEmpty());
		
		// Base2::show2
		IFunctionScope function = null;
		for (ICompileUnitScope cu : cuList) {
			function = cu.getFunctionAtAddress(new Addr32(0xa916));
			if (function != null)
				break;
		}
		if (function == null)
			for (ICompileUnitScope cu : cuhList) {
			function = cu.getFunctionAtAddress(new Addr32(0xa916));
			if (function != null)
				break;
		}

		assertNotNull(function);
		assertEquals("show2", function.getName());
		for (IVariable var : function.getVariablesInTree()) {
			if (var.getName().equals("Base2Show"))
				_testSpecificTypeCharArray(function, cuhList.get(0), var);
		}
	}

	/**
	 * @param function 
	 * @param headerScope 
	 * @param var
	 */
	private void _testSpecificTypeCharArray(IFunctionScope function, ICompileUnitScope headerScope, IVariable var) {
		IType type = var.getType();
		assertFalse(type instanceof IForwardTypeReference);	// should not peek through interface
		assertNotNull(type);
		assertTrue(type.getName(), type instanceof IArrayType);
		assertEquals(function, var.getScope());
		
		IType baseType = ((IArrayType) type).getType();
		assertNotNull(baseType);
		assertTrue(baseType.getName(), baseType instanceof IBasicType);
		
		// FIXME: this should be null for a primitive type, but is the previous function in the old reader
		//assertEquals(randomFunction, baseType.getScope());		

		IBasicType charType = (IBasicType) baseType;
		assertEquals("char", charType.getName());
		assertEquals(1, charType.getByteSize());
	}

	/**
	 * Test case(s) for specific type parses, from the whole module scope
	 * @throws Exception
	 */
	@Test
	public void testSpecificTypes3a() throws Exception {
		IEDCSymbolReader symbolReader = Symbols.getSymbolReader(getFile("BlackFlagMinGW.exe"));
		List<ICompileUnitScope> cuList = getCompileUnitsFor(symbolReader, "dbg_expressions.cpp");
		
		// TODO: lookup by name
		for (ICompileUnitScope cu : cuList) {
			for (IVariable var : cu.getVariables()) {
				if (var.getName().equals("genum")) {
					assertEquals(cu, var.getScope());
					_testSpecificTypeEnum(var.getType(), "dbg_typedefs.h");
					break;
				}
			}
		}
		
		////////
		
		symbolReader = Symbols.getSymbolReader(getFile("BlackFlag_rvct.sym"));
		cuList = getCompileUnitsFor(symbolReader, "dbg_typedefs.h");
		
		// TODO: lookup by name
		for (ICompileUnitScope cu : cuList) {
			for (IVariable var : cu.getVariables()) {
				if (var.getName().equals("genum")) {
					assertEquals(cu, var.getScope());
					_testSpecificTypeEnum(var.getType(), "dbg_typedefs.h");
					break;
				}
			}
		}
	}

	/**
	 * Test case(s) for specific type parses, from a focused scope
	 * @throws Exception
	 */
	@Test
	public void testSpecificTypes3b() throws Exception {
		IEDCSymbolReader symbolReader = Symbols.getSymbolReader(getFile("BlackFlagMinGW.exe"));
		DwarfDebugInfoProvider provider = getDwarfDebugInfoProvider(symbolReader);
		if (provider == null)
			return;
		
		// DW_TAG_enumeration_type : enum_type
		IType type = provider.readType(0x6a65);
		_testSpecificTypeEnum(type, "dbg_expressions.cpp");
		
		///////
		
		// defined in different place here
		symbolReader = Symbols.getSymbolReader(getFile("BlackFlag_rvct.sym"));
		provider = getDwarfDebugInfoProvider(symbolReader);
		if (provider == null)
			return;
		
		// DW_TAG_enumeration_type : enum_type
		type = provider.readType(0x1a6a3d);
		_testSpecificTypeEnum(type, "dbg_typedefs.h");
	}

	private void _testSpecificTypeEnum(IType type, String file) {
		assertTrue(getTypeName(type), type instanceof IEnumeration);
		IEnumeration enumType = (IEnumeration) type;
		assertEquals("enum_type", enumType.getName());
		assertEquals(5, enumType.enumeratorCount());
		
		assertEquals("zero", enumType.getEnumerators()[0].getName());
		assertEquals("one", enumType.getEnumerators()[1].getName());
		assertEquals("two", enumType.getEnumerators()[2].getName());
		assertEquals("three", enumType.getEnumerators()[3].getName());
		assertEquals("four", enumType.getEnumerators()[4].getName());
		
		IScope scope = type.getScope();
		assertTrue(scope instanceof ICompileUnitScope);
		ICompileUnitScope cus = (ICompileUnitScope) scope;
		assertTrue(cus.getFilePath().toString(), cus.getFilePath().lastSegment().equals(file));
	}

	@Test
	public void testStaticLocals1() throws Exception {
		for (TestInfo info : testInfos.values()) {
			if (info.blackFlagMainFilePath != null) {
				IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.symFile);
			
				List<ICompileUnitScope> cuList = getCompileUnitsFor(symbolReader, info.blackFlagMainFilePath.lastSegment());
				assertFalse(cuList.isEmpty());
				
				for (ICompileUnitScope cu : cuList) {
					for (IFunctionScope func : cu.getFunctions()) {
						if (func.getName().equals("doExampleL")) {
							for (IVariable var : func.getVariablesInTree()) {
								if (var.getName().equals("KHelloWorldText")) {
									IScope vScope = var.getScope();
									if (vScope instanceof ILexicalBlockScope)
										vScope = vScope.getParent();
									assertEquals(func, vScope);
									
									_testStaticLocal(var.getType());
								}
							}
						}
					}
				}
			}
		}
	}

	@Test
	public void testStaticLocals2() throws Exception {
		IEDCSymbolReader symbolReader = Symbols.getSymbolReader(getFile("BlackFlag_gcce.sym"));
	
		DwarfDebugInfoProvider provider = getDwarfDebugInfoProvider(symbolReader);
		if (provider == null)
			return;
		
		IType type = provider.readType(0x7e11);
		_testStaticLocal(type);
		
		///////////
		
		symbolReader = Symbols.getSymbolReader(getFile("BlackFlag_rvct.sym"));
		
		provider = getDwarfDebugInfoProvider(symbolReader);
		if (provider == null)
			return;
		
		type = provider.readType(0x1dc89a);
		_testStaticLocal(type);

	}

	/**
	 * @param type 
	 */
	private void _testStaticLocal(IType type) {
		assertTrue(getTypeName(type), type instanceof ConstType);
		type = type.getType();
		assertTrue(getTypeName(type), type instanceof ICompositeType);
		ICompositeType comp = (ICompositeType) type;
		// differs in RVCT and GCCE
		assertTrue(getTypeName(type), "struct TLitC<14>".equals(comp.getName())
				|| "class TLitC".equals(comp.getName()));
		
		assertEquals(2, comp.fieldCount());
		assertEquals(0, comp.inheritanceCount());
		
		IField f = comp.getFields()[0];
		assertEquals("iTypeLength", f.getName());
		assertTrue(getTypeName(f.getType()), f.getType() instanceof ITypedef);
		type = f.getType().getType();
		assertTrue(getTypeName(type), type instanceof IBasicType);
		
		f = comp.getFields()[1];
		assertEquals("iBuf", f.getName());
		assertTrue(getTypeName(f.getType()), f.getType() instanceof IArrayType);
		IArrayType arr = (IArrayType) f.getType();
		assertNotNull(arr.getBounds());
		assertEquals(1, arr.getBoundsCount());
		IArrayBoundType bound = arr.getBound(0);
		assertEquals(0, bound.getDimensionIndex());
		assertEquals(14, bound.getBoundCount());
		assertEquals(1, bound.getElementCount());
		type = arr.getType();
		assertTrue(getTypeName(type), type instanceof ITypedef);
		
		type = type.getType();
		assertTrue(getTypeName(type), type instanceof ICPPBasicType);
		assertEquals(8, ((ICPPBasicType)type).getQualifierBits());
		assertTrue(((ICPPBasicType)type).isUnsigned());
		assertTrue(type instanceof IMayBeQualifedType);
		assertFalse(((IMayBeQualifedType)type).isConst());
		assertFalse(((IMayBeQualifedType)type).isVolatile());		
	}

	/**
	 * Discovered while testing GCC-E
	 * @throws Exception
	 */
	@Test
	public void testSpecificTypes4() throws Exception {
		IEDCSymbolReader symbolReader = Symbols.getSymbolReader(getFile("BlackFlag_gcce.sym"));
		
		DwarfDebugInfoProvider provider = getDwarfDebugInfoProvider(symbolReader);
		if (provider == null)
			return;
		
		IType type = provider.readType(0x36104);
		_testSpecificTypeGCCEDerv1(type);
	}

	/**
	 * @param type 
	 */
	private void _testSpecificTypeGCCEDerv1(IType type) {
		assertTrue(type.getName(), type instanceof ICompositeType);
		
		ICompositeType derv1Comp = (ICompositeType) type;
		assertEquals("struct Derv1", derv1Comp.getName());
		assertEquals(1, derv1Comp.fieldCount());
		assertEquals(2, derv1Comp.inheritanceCount());
		IField vptrField = derv1Comp.findFields("_vptr$Derv1")[0];	// renamed by parser to avoid having an invalid expression-like field
		assertNotNull("_vptr$Derv1", vptrField);
		
		// inherited fields also visible
		IField xField = derv1Comp.findFields("x")[0];
		assertNotNull("x", xField);
		
		// x is in an inherited type
		IInheritance[] inhs = derv1Comp.getInheritances();
		assertEquals(2, inhs.length);
		
		IType base1 = inhs[1].getType();
		assertNotNull(base1);
		assertEquals("struct Base1", base1.getName());
		assertTrue(base1.getName(), base1 instanceof ICompositeType);
		
		ICompositeType base1Comp = (ICompositeType) base1;
		assertEquals(1, base1Comp.fieldCount());
		assertEquals(0, base1Comp.inheritanceCount());
		xField = base1Comp.findFields("x")[0];
		assertNotNull("x", xField);
		
		IType base2 = inhs[0].getType();
		assertNotNull(base2);
		assertEquals("struct Base2", base2.getName());
		assertTrue(base2.getName(), base2 instanceof ICompositeType);
		
		ICompositeType base2Comp = (ICompositeType) base2;
		assertEquals(0, base2Comp.fieldCount());
		assertEquals(0, base2Comp.inheritanceCount());
		
		// watch for side effects (late adding of inherited fields)
		assertEquals(1, derv1Comp.fieldCount());
		assertEquals(2, derv1Comp.inheritanceCount());
		assertEquals(1, base1Comp.fieldCount());
		assertEquals(0, base1Comp.inheritanceCount());
		assertEquals(0, base2Comp.fieldCount());
		assertEquals(0, base2Comp.inheritanceCount());
		

		IScope scope = type.getScope();
		assertTrue(scope instanceof ICompileUnitScope);
		IPath path = ((ICompileUnitScope) scope).getFilePath();
		assertTrue(path.toString(), path.lastSegment().equalsIgnoreCase("dbg_multipleInheritance.cpp"));
	}

	private boolean isExecutable(ISymbol symbol) {
		Boolean executable = (Boolean)symbol.getProperties().get(ISymbol.PROPERTY_EXECUTABLE);
		// for testing purposes, if the property doesn't exist, assume true
		return executable == null || executable;
	}

	/**
	 * Test that we do not have multiple entries for the same symbol with a zero size.
	 * @throws Exception
	 */
	@Test
	public void testSymbols() throws Exception {
		for (TestInfo info : testInfos.values()) {
			if (info.numberOfSymbols == 0) continue;
			IEDCSymbolReader reader = Symbols.getSymbolReader(info.symFile);
			Collection<ISymbol> symbols = reader.getSymbols();
			int numSymbols = symbols.size();
			//System.out.println(info.symFile.lastSegment() + " : " + numSymbols);
			assertEquals(info.symFile.lastSegment(), info.numberOfSymbols, numSymbols);
			Map<IAddress, List<ISymbol>> zeroSymbols = new HashMap<IAddress, List<ISymbol>>();
			for (ISymbol symbol : symbols) {
				if (symbol.getSize() == 0) {
					IAddress symAddr = symbol.getAddress();
					List<ISymbol> sameAddrList = zeroSymbols.get(symAddr);
					if (sameAddrList != null && !symAddr.getValue().equals(BigInteger.ZERO)) {
						// with the addition of multiple zero-sized symbols,
						// the criterion is that there should not now be
						// duplicate executable symbols at the same address
						if (isExecutable(symbol)) {
							for (ISymbol sameAddr : sameAddrList) {
								if (symbol.getClass().equals(sameAddr) && isExecutable(sameAddr)) {
									if (symbol instanceof IARMSymbol) {
										// you may have more than one zero-sized executable
										// symbol at the same address in ARM.  But they should
										// not be the same mode, e.g. both ARM or both Thumb.
										assertFalse("multiple zero-size symbols" + symbol.getName() + " & "+ sameAddr.getName(),
													((IARMSymbol)symbol).isThumbAddress() == ((IARMSymbol)sameAddr).isThumbAddress());
									} else {
										assertFalse("multiple zero-size symbols" + symbol.getName() + " & "+ sameAddr.getName(), true);
									}
								}
							}
						}
					} else {
						sameAddrList = new ArrayList<ISymbol>();
					}
					sameAddrList.add(symbol);
					zeroSymbols.put(symbol.getAddress(), sameAddrList);
				}
			}
		}
	}

	/**
	 * Test some type lookup edge cases
	 */
	@Test
	public void testSpecificTypes4a() throws Exception {
		IEDCSymbolReader symbolReader = Symbols.getSymbolReader(getFile("BlackFlag_rvct.sym"));
		
		List<ICompileUnitScope> scopes = getCompileUnitsFor(symbolReader, "dbg_multipleInheritance.cpp");
		if (scopes.isEmpty())
			scopes = getCompileUnitsFor(symbolReader, "dbg_multipleinheritance.cpp");
		assertFalse(scopes.isEmpty());
		/*
		if (Symbols.useNewReader())
			// TODO: along with other filepath lookup issues:
			// what happens here is, there are three CUs for dbg_multipleInheritance.cpp,
			// but one has no DW_AT_comp_dir.  All of their names are \BlackFlags\SRC\dbg_multipleInheritance.cpp,
			// which (once canonicalized) looks like an absolute path in Linux, thus comes in as
			// three distinct CUs for the same path.  In Win32, though, the comp dir is prepended
			// in two cases, since the name is not considered absolute.
			assertEquals(HostOS.IS_WIN32 ? 2 : 3, scopes.size());		
		else
			assertEquals(1, scopes.size());
		*/
		
		IFunctionScope functionScope = null;
		for (ICompileUnitScope scope : scopes) {
			functionScope = scope.getFunctionAtAddress(new Addr32(0xaa4e));
			if (functionScope != null)
				break;
		}
		assertNotNull(functionScope);
		
		Collection<IVariable> vars = functionScope.getVariablesInTree();
		assertEquals(2, vars.size());
		
		java.util.Iterator<IVariable> vit = vars.iterator();
		assertEquals("FromBase2", vit.next().getName());
		assertEquals("a", vit.next().getName());
		
		vars = functionScope.getParameters();
		assertEquals(1, vars.size());
		vit = vars.iterator();
		IVariable thisVar = vit.next();
		assertEquals("this", thisVar.getName());
		
		assertNotNull(thisVar.getType());
		_testSpecificTypes4(thisVar.getType());
	}

	/**
	 * Test some type lookup edge cases
	 */
	@Test
	public void testSpecificTypes4b() throws Exception {
		IEDCSymbolReader symbolReader = Symbols.getSymbolReader(getFile("BlackFlag_rvct.sym"));
		
		DwarfDebugInfoProvider provider = getDwarfDebugInfoProvider(symbolReader);
		if (provider == null)
			return;
		
		// 0x1cb0c6: subprogram
		// 0x1cb0de: this
		// 0x1cb098: Base2*
		
		IType type = provider.readType(0x1cb098);
		assertNotNull(type);
		_testSpecificTypes4(type);
	}

	/**
	 * @param type
	 */
	private void _testSpecificTypes4(IType type) {
		assertTrue(type.getName(), type instanceof IPointerType);
		
		IType base2 = ((IPointerType) type).getType();
		assertFalse(base2 instanceof IForwardTypeReference);	// should not peek through interface
		assertNotNull(base2);
		assertTrue(base2.getName(), base2 instanceof ICompositeType);
		
		ICompositeType base2Comp = (ICompositeType) base2;
		assertEquals("class Base2", base2Comp.getName());
		assertEquals(0, base2Comp.fieldCount());
		assertEquals(0, base2Comp.inheritanceCount());

		// the class is in the header
		IScope classScope = ((IPointerType)type).getType().getScope();
		assertTrue(classScope instanceof ICompileUnitScope);
		IPath path = ((ICompileUnitScope) classScope).getFilePath();
		assertTrue(path.toString(), path.lastSegment().equalsIgnoreCase("dbg_multipleInheritance.h"));

		// the pointer type is declared in a function
		assertTrue(type.getScope() instanceof IFunctionScope);
		IScope fileScope = type.getScope().getParent();
		assertTrue(fileScope instanceof ICompileUnitScope);
		path = ((ICompileUnitScope) fileScope).getFilePath();
		assertTrue(path.toString(), path.lastSegment().equalsIgnoreCase("dbg_multipleInheritance.cpp"));
	}

	/**
	 * Test some type lookup edge cases
	 */
	@Test
	public void testSpecificTypes5a() throws Exception {
		IEDCSymbolReader symbolReader = Symbols.getSymbolReader(getFile("BlackFlag_rvct.sym"));
		
		// inlined Der1::Der1()
		IScope scope = symbolReader.getModuleScope().getScopeAtAddress(new Addr32(0x8cda));
		assertTrue(scope instanceof IFunctionScope);
		
		IFunctionScope functionScope = (IFunctionScope) scope;

		// two locals __func_local__0 and __result are optimized out
		Collection<IVariable> vars = functionScope.getVariablesInTree();
		assertEquals(0, vars.size());
		
		java.util.Iterator<IVariable> vit;
		/*
		vit = vars.iterator();
		IVariable var = vit.next();
		assertEquals("__func_local__0", var.getName());
		var = vit.next();
		assertEquals("__result", var.getName());
		*/
		
		vars = functionScope.getParameters();
		assertEquals(1, vars.size());
		vit = vars.iterator();
		IVariable thisVar = vit.next();
		assertEquals("this", thisVar.getName());
		
		assertNotNull(thisVar.getType());
		_testSpecificTypes5(thisVar.getType());
	}

	/**
	 * @param type
	 */
	private void _testSpecificTypes5(IType type) {
		assertTrue(type.getName(), type instanceof IPointerType);
		
		IType der1 = ((IPointerType) type).getType();
		assertFalse(der1 instanceof IForwardTypeReference);	// should not peek through interface
		assertNotNull(der1);
		assertTrue(der1.getName(), der1 instanceof ICompositeType);
		
		ICompositeType der1Comp = (ICompositeType) der1;
		assertEquals("struct Der1", der1Comp.getName());
		assertEquals(1, der1Comp.fieldCount());
		assertEquals(1, der1Comp.inheritanceCount());

		IField field = der1Comp.findFields("b1")[0];
		assertNotNull("b1", field);

		field = der1Comp.findFields("__vptr")[0];
		assertNotNull("__vptr", field);

		// inherited fields also visible
		field = der1Comp.findFields("a")[0];
		assertNotNull("a", field);
		
		// x is in an inherited type
		IInheritance[] inhs = der1Comp.getInheritances();
		assertEquals(1, inhs.length);
		
		IType base01 = inhs[0].getType();
		assertNotNull(base01);
		assertEquals("struct Base01", base01.getName());
		assertTrue(base01.getName(), base01 instanceof ICompositeType);
		
		ICompositeType base01Comp = (ICompositeType) base01;
		assertEquals(2, base01Comp.fieldCount());
		assertEquals(0, base01Comp.inheritanceCount());
		
		field = base01Comp.findFields("a")[0];
		assertNotNull("a", field);
		

		field = der1Comp.findFields("__vptr")[0];
		assertNotNull("__vptr", field);
		
		// the class is in the header
		IScope classScope = ((IPointerType)type).getType().getScope();
		assertTrue(classScope instanceof ICompileUnitScope);
		IPath path = ((ICompileUnitScope) classScope).getFilePath();
		assertTrue(path.toString(), path.lastSegment().equals("dbg_rtti.cpp"));

		// the pointer type is declared in a function
		assertTrue(type.getScope() instanceof ICompileUnitScope);
		path = ((ICompileUnitScope) type.getScope()).getFilePath();
		assertTrue(path.toString(), path.lastSegment().equals("dbg_rtti.cpp"));
	}

	/**
	 * Look for DWARF files with bad scopes and make sure we fix them up properly.
	 * Use full scanning to populate the content.
	 */
	@Test
	public void testScopes1a() {
		for (TestInfo info : testInfos.values()) {
			System.out.println("Scopes for " + info.symFile.lastSegment());
			IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.symFile);
			if (symbolReader != null) {
				readFully(symbolReader);
				doTestScopes(symbolReader);
			}
		}
	}

	/**
	 * Look for DWARF files with bad scopes and make sure we fix them up properly.
	 * Use random scanning to populate the content.
	 */
	@Test
	public void testScopes1b() {
		for (TestInfo info : testInfos.values()) {
			System.out.println("Scopes for " + info.symFile.lastSegment());
			IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.symFile);
			if (symbolReader != null) {
				readRandomly(symbolReader);
				doTestScopes(symbolReader);
			}
		}
	}

	/**
	 * @param symbolReader
	 */
	private void doTestScopes(IEDCSymbolReader symbolReader) {
		IModuleScope moduleScope = symbolReader.getModuleScope();
		IAddress low = moduleScope.getLowAddress();
		IAddress high = moduleScope.getHighAddress();
		assertTrue(low.compareTo(high) < 0);
		
		checkChildScopes(moduleScope, low, high);
	}

	/**
	 * @param scope
	 * @param low
	 * @param high
	 */
	private void checkChildScopes(IScope scope, IAddress low, IAddress high) {
		for (IScope kid : scope.getChildren()) {
			IAddress kidlo = kid.getLowAddress();
			IAddress kidhi = kid.getHighAddress();
			
			if (!kid.hasEmptyRange()) {
				if (!(kidlo.compareTo(kidhi) <= 0)) {
					fail(describeScope(kid));
				}
				if (!(low.compareTo(kidlo) <= 0)) {
					fail(describeScope(kid));
				}
				if (!(kidhi.compareTo(high) <= 0)) {
					fail(describeScope(kid));
				}
			}	
			
			if (!(kid instanceof ILexicalBlockScope) && !(scope instanceof ILexicalBlockScope)) {
				checkChildScopes(kid, kidlo, kidhi);
			} else {
				// lexical blocks are not constrained to be within other lexical blocks,
				// but they should be within the function.
				checkChildScopes(kid, low, high);
				
			}
		}
		
	}

	/**
	 * Make sure our fixing up of CU scopes makes sense.  In old GCC-E (e.g. 3.4.3), the
	 * compile units do not have low_pc and high_pc, which makes it hard to find functions.
	 */
	@Test
	public void testScopes3() {
		for (TestInfo info : testInfos.values()) {
			String label = info.symFile.lastSegment();
			System.out.println("Address->Function mapping for "+ label);
			
			// explicitly read the functions
			IExecutableSymbolicsReader exeReader = ExecutableSymbolicsReaderFactory.createFor(info.symFile);
			if (exeReader == null)
				continue;
			
			DwarfDebugInfoProvider debugInfoProvider = new DwarfDebugInfoProvider(exeReader);
			IEDCSymbolReader explicitSymbolReader = new EDCSymbolReader(
					exeReader,
					debugInfoProvider);
			
			// this is NOT guaranteed:  GCC-E at link time will share function definitions among CUs,
			// so two CUs can "overlap" if you consider only their raw Lo and Hi PCs.
			/*
			// make sure the CUs are proper
			ArrayList<IScope> cuList= new ArrayList<IScope>(explicitSymbolReader.getModuleScope().getChildren());
			Collections.sort(cuList);
			long low = 0, high = 0;
			
			for (IScope cu : cuList) {
				String culabel = label + ":" + cu;
				long start = cu.getLowAddress().getValue().longValue();
				long end = cu.getHighAddress().getValue().longValue();
				if (start != end) {
					assertTrue(culabel, start < end);
					assertTrue(culabel, start >= low);
					if (high > 0)
						assertTrue(culabel, end > high);
					high = end;
				}
			}
			*/
			
			// remember all the functions
			List<IFunctionScope> allFuncs = new ArrayList<IFunctionScope>(
					explicitSymbolReader.getModuleScope().getFunctionsByName(null));
			assertTrue(allFuncs.size() >= 10);
			
			debugInfoProvider.dispose();
			
			// now, make sure we can find all those functions with a random scan
			debugInfoProvider = new DwarfDebugInfoProvider(exeReader);
			IEDCSymbolReader testSymbolReader = new EDCSymbolReader(
					exeReader,
					debugInfoProvider);
			
			StringBuilder missing = new StringBuilder();
			Random random = new Random(0x12145895);
			int count = allFuncs.size();
			while (count-- > 0) {
				IFunctionScope allFunc = allFuncs.get(random.nextInt(allFuncs.size()));
				doTestScope3Func(label, missing, testSymbolReader, allFunc);
			}
			debugInfoProvider.dispose();
			
			
			if(missing.length() > 0)
				fail(missing.toString());
		}

		// as good a place as any to test the fields of the static EDCSymbolReader.EMPTY_MODULE_SCOPE
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.compareTo(new Object()) == 0);
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.equals(new Object()) == false);
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getChildren().isEmpty());
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getCompileUnitForAddress(null) == null);
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getCompileUnitsForFile(null).isEmpty());
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getEnumerators().isEmpty());
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getFrameRegisterProvider() == null);
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getFunctionsByName(null).isEmpty());
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getHighAddress().isZero());
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getLowAddress().isZero());
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getModuleLineEntryProvider() != null);
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getName().length() == 0);
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getParent() == null);
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getRangeList() == null);
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getScopeAtAddress(null) == null);
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getSymbolFile() == null);
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getTypes().isEmpty());
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getVariables().isEmpty());
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getVariablesByName(null, false).isEmpty());
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.getVariablesByName(null, true).isEmpty());
		assertTrue(EDCSymbolReader.EMPTY_MODULE_SCOPE.hasEmptyRange());
	}

	/**
	 * Make sure our fixing up of CU scopes makes sense.  In old GCC-E (e.g. 3.4.3), the
	 * compile units do not have low_pc and high_pc, which makes it hard to find functions.
	 */
	@Test
	public void testScopes3b() {
		IEDCSymbolReader symbolReader = Symbols.getSymbolReader(getFile("BlackFlag_gcce_343.sym"));
		IScope scope = symbolReader.getModuleScope().getScopeAtAddress(new Addr32(0xad32));
		assertTrue(scope instanceof IFunctionScope || scope instanceof ILexicalBlockScope);
	}

	/**
	 * @param label
	 * @param missing
	 * @param symbolReader
	 * @param allFunc
	 */
	private void doTestScope3Func(String label, StringBuilder missing,
			IEDCSymbolReader symbolReader, IFunctionScope allFunc) {
		IScope scope1 = symbolReader.getModuleScope().getScopeAtAddress(allFunc.getLowAddress().add(1));
		IScope scope2 = symbolReader.getModuleScope().getScopeAtAddress(allFunc.getHighAddress().add(-1));
		
		if (scope1 == null || scope2 == null) {
			missing.append(label + ":"+ allFunc +" missing\n");
			
		} 
		// skip if the function is defined over a range, because this may mean interleaved runtime code
		else if (allFunc.getRangeList() == null){
			// one of both may be inlined
			while (scope1 instanceof ILexicalBlockScope ||  scope1.getParent() instanceof IFunctionScope)
				scope1 = scope1.getParent();
			while (scope2 instanceof ILexicalBlockScope || scope2.getParent() instanceof IFunctionScope)
				scope2 = scope2.getParent();
			if (scope1 != scope2) {
				missing.append(label + ":"+ allFunc +" did not find same function at low and high: " + scope1 + " / "+ scope2 + "\n");
			}
		}
	}

	@Test
	public void testRangeList() {
		TestInfo info = testInfos.get("BlackFlagMinGW.exe");

		// explicitly read the functions
		IExecutableSymbolicsReader exeReader = ExecutableSymbolicsReaderFactory.createFor(info.symFile);
		DwarfDebugInfoProvider debugInfoProvider = new DwarfDebugInfoProvider(exeReader);
		IEDCSymbolReader reader = new EDCSymbolReader(exeReader, debugInfoProvider);

		List<ICompileUnitScope> scopes = new ArrayList<ICompileUnitScope>();
		for (IScope scope : reader.getModuleScope().getChildren()) {
			if (scope instanceof ICompileUnitScope) {
				scopes.add((ICompileUnitScope) scope);
			}
		}
		
		// check and manipulate range list
		for (ICompileUnitScope cuScope : scopes) {
			if (cuScope.getRangeList() != null) {
				RangeList rangeList = (RangeList) cuScope.getRangeList();
				long low = rangeList.getLowAddress();
				long high = rangeList.getHighAddress();
				rangeList.addLowRange(low - 1);
				rangeList.addHighRange(high + 1);
				assertTrue(rangeList.isInRange(low));
				assertTrue(low > rangeList.getLowAddress());
				assertTrue(high < rangeList.getHighAddress());
				assertTrue(rangeList.toString().
						contains(Long.toHexString(rangeList.getLowAddress())));
				break;
			}
		}
	}

	@Test
	public void testFrameRegInstructions() {
		EDCServicesTracker edcTracker = null;
		try {
			TestUtils.showDebugPerspective();
			dwarfAlbum = DwarfFrameRegisterAlbum.openAlbum();
			dwarfAlbum.launchAndWaitForSuspendedContext();
			if (dwarfAlbum.getLaunch() == null) return;
			edcTracker = new EDCServicesTracker(EDCDebugger.getBundleContext(), dwarfAlbum.getSession().getId());
			Assert.assertNotNull(edcTracker);
		} catch (Exception e) {
			Assert.fail(e.getLocalizedMessage());
		}

		TestInfo info = testInfos.get("BlackFlag_rvct.sym");

		// explicitly read the types to parse the file
		IExecutableSymbolicsReader exeReader = ExecutableSymbolicsReaderFactory.createFor(info.symFile);
		DwarfDebugInfoProvider provider = new DwarfDebugInfoProvider(exeReader);
		provider.getTypes();
		FrameDescriptionEntry fde = provider.findFrameDescriptionEntry(new Addr64("32768"));
		InstructionState dummyState;
		
		// Can remove try blocks when all AbstractInstruction#applyInstruction()'s are implemented
		dummyState = new InstructionState(edcTracker, null, null, fde);
		try {
			DefCFAExpressionInstruction defCFAEI = new DefCFAExpressionInstruction(null);
			assertNotNull(defCFAEI.toString());
			defCFAEI.applyInstruction(dummyState);
		} catch (Throwable t) {
		}

		dummyState = new InstructionState(null, null, null, fde);
		try {
			// save an expression
			ExpressionInstruction ei = new ExpressionInstruction(0, null);
			assertNotNull(ei.toString());
			ei.applyInstruction(dummyState);
			assertTrue(dummyState.regRules.containsKey(0));
		} catch (Throwable t) {
		}

		dummyState = new InstructionState(null, null, null, fde);
		try {
			// save a register
			RegisterInstruction re = new RegisterInstruction(0, 1);
			assertNotNull(re.toString());
			re.applyInstruction(dummyState);
			assertTrue(dummyState.regRules.containsKey(0));
		} catch (Throwable t) {
		}

		dummyState = new InstructionState(null, null, null, fde);
		try {
			// nop
			NopInstruction nop = new NopInstruction();
			assertNotNull(nop.toString());
			int hash = dummyState.hashCode();
			nop.applyInstruction(dummyState);
			assertTrue(dummyState.hashCode() == hash);
		} catch (Throwable t) {
		}

		dummyState = new InstructionState(null, null, null, fde);
		try {
			// save an expression for a register
			ValueExpressionInstruction vei = new ValueExpressionInstruction(0, null);
			assertNotNull(vei.toString());
			vei.applyInstruction(dummyState);
			assertTrue(dummyState.regRules.containsKey(0));
		} catch (Throwable t) {
		}

		dummyState = new InstructionState(null, null, null, fde);
		try {
			// save a register offset
			ValueOffsetInstruction voi = new ValueOffsetInstruction(0, 12);
			assertNotNull(voi.toString());
			voi.applyInstruction(dummyState);
			assertTrue(dummyState.regRules.containsKey(0));
		} catch (Throwable t) {
		}

		dummyState = new InstructionState(null, null, null, fde);
		try {
			// push a state on the state stack
			RememberStateInstruction rsi = new RememberStateInstruction();
			assertNotNull(rsi.toString());
			int i = dummyState.stateStack.size();
			rsi.applyInstruction(dummyState);
			assertTrue(dummyState.stateStack.size() == i + 1);
		} catch (Throwable t) {
		}

		dummyState = new InstructionState(null, null, null, fde);
		try {
			// remove rule for instruction
			RestoreInstruction ri = new RestoreInstruction(0);
			assertNotNull(ri.toString());
			ri.applyInstruction(dummyState);
			assertFalse(dummyState.regRules.containsKey(0));
		} catch (Throwable t) {
		}

		dummyState = new InstructionState(null, null, null, fde);
		try {
			RememberStateInstruction rsi1 = new RememberStateInstruction();
			rsi1.applyInstruction(dummyState);
			// remove rule for instruction
			RestoreStateInstruction rsi = new RestoreStateInstruction();
			assertNotNull(rsi.toString());
			rsi.applyInstruction(dummyState);
			assertFalse(dummyState.regRules.isEmpty());
		} catch (Throwable t) {
		}

		dummyState = new InstructionState(null, null, null, fde);
		try {
			DefCFAInstruction defCFA = new DefCFAInstruction(0, 12);
			assertNotNull(defCFA.toString());
			defCFA.applyInstruction(dummyState);
			assertTrue(dummyState.getCFARegister() == 0);
		} catch (Throwable t) {
		}

		dummyState = new InstructionState(null, null, null, fde);
		try {
			SameValueInstruction svi = new SameValueInstruction(0);
			assertNotNull(svi.toString());
			svi.applyInstruction(dummyState);
			assertFalse(dummyState.regRules.isEmpty());
		} catch (Throwable t) {
		}

		dummyState = new InstructionState(null, null, null, fde);
		try {
			UndefinedInstruction svi = new UndefinedInstruction(0);
			assertNotNull(svi.toString());
			svi.applyInstruction(dummyState);
			assertFalse(dummyState.regRules.isEmpty());
		} catch (Throwable t) {
		}
	}

	@Test
	public void testModuleScopeStartEnd() {
		for (TestInfo info : testInfos.values()) {
			IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.symFile);
			assertNotNull(symbolReader);
			IScope moduleScope = symbolReader.getModuleScope();
			if (info.lowAddress != null) {
				assertEquals(info.lowAddress, moduleScope.getLowAddress());
				assertEquals(info.highAddress, moduleScope.getHighAddress());
			}
		}
	}

	@Test
	public void testPubnames1() {
		for (TestInfo info : testInfos.values()) {
			if (info.numberOfPubFuncNames == 0) continue;
			IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.symFile);
			
			DwarfDebugInfoProvider debugInfoProvider = (DwarfDebugInfoProvider) ((EDCSymbolReader) symbolReader).getDebugInfoProvider();
			Map<String, List<PublicNameInfo>> pubs;
			pubs = debugInfoProvider.getPublicFunctions();
			
			boolean discover = false;
			int total = 0;
			for (String pub : pubs.keySet()) {
				total += pubs.get(pub).size();
			}
			if (discover) {
				System.out.println(info.symFile + ": " + pubs.size() + " / "+ total);
			} else {
				assertEquals(info.numberOfPubFuncNames, pubs.size());
				assertEquals(info.numberOfPubFuncEntries, total);
			}
			
			pubs = debugInfoProvider.getPublicVariables();
			
			total = 0;
			for (String pub : pubs.keySet()) {
				total += pubs.get(pub).size();
			}
			if (discover) {
				System.out.println(info.symFile + ": " + pubs.size() + " / "+ total);
			} else {
				assertEquals(info.numberOfPubVarNames, pubs.size());
				assertEquals(info.numberOfPubVarEntries, total);
			}
		}
	}

	@Test
	public void testPubnames2() {
		for (TestInfo info : testInfos.values()) {
			IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.symFile);
			
			for (String name : info.pubFuncs) {
				String simpleName = stripName(name);
				Collection<IFunctionScope> funcs = symbolReader.getModuleScope().getFunctionsByName(simpleName);
				assertNotNull(info.symFile.lastSegment() + ":" + name, funcs);
				assertTrue(info.symFile.lastSegment() + ":" + name, !funcs.isEmpty());
				for (IFunctionScope func : funcs) {
					assertEquals(func.getName(), simpleName);
				}
			}
			for (String name : info.pubVars) {
				String simpleName = stripName(name);
				Collection<IVariable> vars = symbolReader.getModuleScope().getVariablesByName(simpleName, false);
				assertNotNull(info.symFile.lastSegment() + ":" + name, vars);
				assertTrue(info.symFile.lastSegment() + ":" + name, !vars.isEmpty());
				for (IVariable var : vars) {
					assertEquals(var.getName(), simpleName);
				}
			}
		}
	}

	/**
	 * Test that, for a given PC, we know which locals are in scope.
	 */
	@Test
	public void testLocalScopes1() {
		StringBuilder errors = new StringBuilder();
		for (TestInfo info : testInfos.values()) {
			for (String key : info.scopeInfos.keySet()) {
				String[] split = key.split("\\|");
				String file = split[0];
				String func = split[1];
				String className = split[2];
				if (className.equals("null"))
					className = null;
				
				IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.symFile);
				List<ICompileUnitScope> cuList = getCompileUnitsFor(symbolReader, file);
				boolean found = false;
				for (ICompileUnitScope cu : cuList) {
					for (IFunctionScope scope : cu.getFunctions()) {
						if (scope.getName().equals(func)) {
							
							if (className != null) {
								String theClassName = getClassFor(scope);
								if (!theClassName.matches("(class|struct) " +className + "(<.*>)?"))
									continue;
							}
							
							found = true;
							
							String label = info.symFile.lastSegment() + ":" + file + (className!= null ? ":" + className  : "") + ":" + func;
							
							boolean discover = false;
							if (discover) {
								System.out.println(label);
								Collection<IVariable> vars = scope.getVariables();
								for (IVariable var : vars) System.out.println(var.getName());
								vars = scope.getParameters();
								for (IVariable var : vars) System.out.println(var.getName());
							} else {							
								doTestLocalScopes1(errors, label, info.scopeInfos.get(key), scope);
							}
						}
					}
				}
				assertTrue(info.symFile.lastSegment() + ":" + key, found);
			}
		}
		if (errors.length() > 0)
			fail(errors.toString());
	}

	/**
	 * @param errors 
	 * @param scopeInfos 
	 * @param scope
	 */
	private void doTestLocalScopes1(StringBuilder errors, String label, List<ScopeInfo> scopeInfos, IFunctionScope scope) {
		// TODO: watch out for template functions, which are named the same
		Addr32 startAddr = new Addr32(scopeInfos.get(0).address);
		if (scope.getLowAddress().compareTo(startAddr) > 0
				|| scope.getHighAddress().compareTo(startAddr) <= 0) {
			return;
		}
		
		for (ScopeInfo scopeInfo : scopeInfos) {
			try {
				doTestScopeInfo(label, scope, scopeInfo);
			} catch (AssertionError e) {
				errors.append(e.getMessage());
				errors.append('\n');
			}
		}
	}

	private void doTestScopeInfo(String label, IFunctionScope scope,
			ScopeInfo scopeInfo) {
		label += ":" + Integer.toHexString(scopeInfo.address); 
		Collection<IVariable> vars = scope.getScopedVariables(new Addr32(scopeInfo.address));
		StringBuilder missing = new StringBuilder();
		for (String name : scopeInfo.names) {
			boolean found = false;
			for (IVariable var : vars) {
				if (var.getName().equals(name)) {
					found = true;
					break;
				}
			}
			if (!found)
				missing.append(name + ", ");
		}
		if (missing.length() > 0)
			fail(label + ": missing "+ missing);
		
		StringBuilder extra = new StringBuilder();
		for (IVariable var : vars) { 
			boolean found = false;
			for (String name : scopeInfo.names) {
				if (name.equals(var.getName())) {
					found = true;
					break;
				}
			}
			if (!found) {
				extra.append(var.getName());
				extra.append(", ");
			}
		}
		if (extra.length() > 0)
			fail(label +": found extra variables: " + extra);
	}

	/**
	 * Test that, for a given PC, we know which locals are in scope.
	 */
	@Test
	public void testLocalLocations() {
		StringBuilder errors = new StringBuilder();
		for (TestInfo info : testInfos.values()) {
			IEDCSymbolReader symbolReader = Symbols.getSymbolReader(info.symFile);
			for (IScope cuscope : symbolReader.getModuleScope().getChildren()) {
				ICompileUnitScope cu = (ICompileUnitScope) cuscope;
				for (IFunctionScope scope : cu.getFunctions()) {
					String label = info.symFile.lastSegment() + ":" + scope;

					for (IVariable var : scope.getVariablesInTree()) {
						checkVariableLocation(errors, label, scope, var);
					}
				}
			}
		}
		if (errors.length() > 0)
			fail(errors.toString());
	}

	/**
	 * @param errors
	 * @param label
	 * @param scope
	 * @param var
	 */
	private void checkVariableLocation(StringBuilder errors, String label,
			IScope scope, IVariable var) {
		ILocationProvider locationProvider = var.getLocationProvider();
		if (locationProvider instanceof LocationExpression) {
			LocationExpression expr = (LocationExpression) locationProvider;
			IScope varScope = expr.getScope();
			while (varScope instanceof ILexicalBlockScope ||
					(varScope != null && varScope.getParent() instanceof IFunctionScope))
				varScope = varScope.getParent();
			if (!(varScope instanceof IFunctionScope)) {
				errors.append("Wrong scope for " + var + ": " + varScope + "\n");
			}
		}
		
	}

	/**
	 * Be sure we zero extend when reading short DWARF attributes.
	 * One place this is quite important is in array bounds.  
	 * Other cases in the reader are line tables, scope ranges, etc. which
	 * are unsigned.  Enum values, though, must remain signed.
	 * @throws Exception
	 */
	@Test
	public void testAttributePromotion() throws Exception {
		// In here, we have a tmp[256] array, with DW_AT_upper_bound == 255.
		// This validates some lazy code that always cast this stuff to a long
		// without considering the sign extension.
		
		// (BTW, this bug was logged for something else, and is not the bug being tested here)
		IEDCSymbolReader reader = Symbols.getSymbolReader(getFile("bug303066.exe"));
		assertNotNull(reader);
		Collection<IFunctionScope> scopes = reader.getModuleScope().getFunctionsByName("main");
		assertNotNull(scopes);
		assertEquals(1, scopes.size());
		boolean found = false;
		int enumcnt = 0;
		for (IVariable var : scopes.iterator().next().getVariables()) {
			if (var.getName().equals("tmp")) {
				IType type = var.getType();
				assertTrue(type instanceof IArrayType);
				IArrayBoundType bound = ((IArrayType) type).getBound(0);
				assertEquals(256, bound.getBoundCount());
				found = true;
			}
			
			// these attributes *should* be sign extended
			if (var.getName().equals("val")) {
				IType type = TypeUtils.getBaseType(var.getType());
				for (IEnumerator enumr : ((IEnumeration)type).getEnumerators()) {
					if (enumr.getName().equals("Val1")) {
						assertEquals(255, enumr.getValue());
						enumcnt++;
					} else if (enumr.getName().equals("Val2")) {
						assertEquals(65535, enumr.getValue());
						enumcnt++;
					} else if (enumr.getName().equals("Val3")) {
						assertEquals(-255, enumr.getValue());
						enumcnt++;
					} else if (enumr.getName().equals("Val4")) {
						assertEquals(-65535, enumr.getValue());
						enumcnt++;
					}
				}
			}
		}
		assertEquals("Found all Val enums", 4, enumcnt);
		assertTrue("Did not find 'tmp'", found);
		
		found = false;
		for (IVariable var : reader.getModuleScope().getVariablesByName("bigbuffer", false)) {
			IType type = var.getType();
			assertTrue(type instanceof IArrayType);
			IArrayBoundType bound = ((IArrayType) type).getBound(0);
			assertEquals(65536, bound.getBoundCount());
			found = true;
			break;
		}
		assertTrue("Did not find 'bigbuffer'", found);
		
	}

	/**
	 * RVCT generates location lists with two duplicate address ranges, where
	 * the latter is the one to trust.  Be sure we filter out the earlier ones.
	 * @throws Exception
	 */
	@Test
	public void testBrokenLocationLists() throws Exception {
		IPath file = getFile("BlackFlag_rvct.sym");
		IEDCSymbolReader reader = Symbols.getSymbolReader(file);
		// show_Const_Arguments
		IFunctionScope func = (IFunctionScope) reader.getModuleScope().getScopeAtAddress(new Addr32(0x9648));
		Collection<IVariable> variables = func.getParameters();
		boolean found = false;
		for (IVariable var : variables) {
			if (var.getName().equals("aArg1")) {
				found = true;
				LocationEntry[] entries = ((LocationList)var.getLocationProvider()).getLocationEntries();
				assertEquals(2, entries.length);
				assertEquals(0x9648, entries[0].getLowPC());
				assertEquals(1, entries[0].getBytes().length);
				assertEquals((byte)0x50, entries[0].getBytes()[0]);
				assertEquals("LocationEntry [bytes=[80], highPC=38474, lowPC=38472]", entries[0].toString());
				break;
			}
		}
		assertTrue(found);
	}
}
