project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestBldInfView.java
changeset 0 fb279309251b
child 610 bfb3ab3f70f2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestBldInfView.java	Fri Apr 03 23:33:03 2009 +0100
@@ -0,0 +1,1740 @@
+/*
+* Copyright (c) 2006-2009 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:
+*
+* Description: 
+*
+*/
+
+package com.nokia.carbide.cpp.epoc.engine.tests.model;
+
+import com.nokia.carbide.cpp.epoc.engine.model.bldinf.*;
+import com.nokia.carbide.cpp.epoc.engine.model.bldinf.IMakefileReference.EMakeEngine;
+import com.nokia.carbide.cpp.epoc.engine.preprocessor.DefineFactory;
+import com.nokia.carbide.cpp.epoc.engine.preprocessor.IDefine;
+import com.nokia.carbide.internal.api.cpp.epoc.engine.dom.IASTProblemNode;
+import com.nokia.cpp.internal.api.utils.core.IMessage;
+
+import org.eclipse.core.runtime.Path;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class TestBldInfView extends BaseBldInfViewTest {
+
+	
+	public void testPlatformsParsing() throws Exception {
+		makeModel("PRJ_PLATFORMS\nwinscw armv5\n");
+
+		IBldInfView view = getView(config);
+		assertNotNull(view);
+		checkNoProblems(view);
+
+		match(new String[] { "winscw", "armv5" }, view.getPlatforms());
+		match(new String[] { "winscw", "armv5" }, view.getData().getPlatforms());
+		
+		view.dispose();
+		model.dispose();
+
+		////
+		makeModel("PRJ_PLATFORMS\ndefault -armv5\n");
+
+		view = getView(config);
+		assertNotNull(view);
+
+		match(new String[] { "default", "-armv5" }, view.getPlatforms());
+		match(new String[] { "default", "-armv5" }, view.getData().getPlatforms());
+		view.dispose();
+		model.dispose();
+
+	}
+
+	public void testPlatformsChanging1() throws Exception {
+		makeModel("PRJ_PLATFORMS\nDEFAULTS\n");
+
+		IBldInfView view = getView(config);
+		assertNotNull(view);
+
+		List<String> platforms = view.getPlatforms();
+		match(new String[] { "DEFAULTS" }, platforms);
+
+		platforms.remove(0);
+		platforms.add("WINSCW");
+		platforms.add("ARMV5");
+		
+		commitTest(view, "PRJ_PLATFORMS\nWINSCW ARMV5\n");
+		
+		///
+		
+		platforms = view.getPlatforms();
+		platforms.remove(1);
+		commitTest(view, "PRJ_PLATFORMS\nWINSCW\n");
+		
+		///
+		view.getPlatforms().clear();
+		commitTest(view, "PRJ_PLATFORMS\n\n");
+		
+		view.dispose();
+		model.dispose();
+
+	}
+
+	public void testMmpfilesParsing1() throws Exception {
+		makeModel("PRJ_MMPFILES\n"+
+				"basic.mmp TIDY\n"+
+				"another.mmp Build_as_ARM\n"+
+				"PRJ_TESTMMPFILES\n"+
+				"test.mmp MANUAL\n");
+
+		IBldInfView view = getView(config);
+		assertNotNull(view);
+		checkNoProblems(view);
+
+		_testMmpfilesParsing1(view);
+		_testMmpfilesParsing1(view.getData());
+		
+		view.dispose();
+		model.dispose();
+
+	}
+
+	private void _testMmpfilesParsing1(IBldInfData bldInfData) {
+		List<IMakMakeReference> maks = bldInfData.getMakMakeReferences();
+		assertEquals(2, maks.size());
+		
+		IMMPReference mmp = (IMMPReference) maks.get(0);
+		assertEquals(new Path("group/basic.mmp"), mmp.getPath());
+		assertFalse(mmp.isBuildAsArm());
+		assertFalse(mmp.isManual());
+		assertFalse(mmp.isSupport());
+		assertTrue(mmp.isTidy());
+
+		mmp = (IMMPReference) maks.get(1);
+		assertEquals(new Path("group/another.mmp"), mmp.getPath());
+		assertTrue(mmp.isBuildAsArm());
+		assertFalse(mmp.isManual());
+		assertFalse(mmp.isSupport());
+		assertFalse(mmp.isTidy());
+
+		
+		////
+		maks = bldInfData.getTestMakMakeReferences();
+		assertEquals(1, maks.size());
+		
+		mmp = (IMMPReference) maks.get(0);
+		assertEquals(new Path("group/test.mmp"), mmp.getPath());
+		assertFalse(mmp.isBuildAsArm());
+		assertTrue(mmp.isManual());
+		assertFalse(mmp.isSupport());
+		assertFalse(mmp.isTidy());
+		
+	////
+		
+		IMMPReference[] mmps = bldInfData.getAllMMPReferences();
+		assertEquals(3, mmps.length);
+		assertEquals(bldInfData.getMakMakeReferences().get(0), mmps[0]);
+		assertEquals(bldInfData.getMakMakeReferences().get(1), mmps[1]);
+		assertEquals(maks.get(0), mmps[2]);
+	}
+
+	public void testMmpfilesParsing2() throws Exception {
+		// not a normally valid case, but used to validate
+		// that these are all considered equal and all expose .mmp extensions
+		makeModel("prj_mmpfiles\n"+
+				"basic TIDY\n"+
+				"baSic.MMP TIDY\n"+
+				"BasIC.kkk TIDY\n");
+		IBldInfView view = getView(config);
+		assertNotNull(view);
+		checkNoProblems(view);
+
+		_testMmpfilesParsing2(view);
+		_testMmpfilesParsing2(view.getData());
+	}
+
+	private void _testMmpfilesParsing2(IBldInfData bldInfData) {
+		IMMPReference[] mmps = bldInfData.getAllMMPReferences();
+		assertEquals(3, mmps.length);
+		assertEquals(new Path("group/basic.mmp"), mmps[0].getPath());
+		assertEquals(new Path("group/baSic.mmp"), mmps[1].getPath());
+		assertEquals(new Path("group/BasIC.mmp"), mmps[2].getPath());
+		assertEquals(mmps[0], mmps[1]);
+		assertEquals(mmps[0], mmps[2]);
+	}
+	
+	public void testMakefilesParsing1() throws Exception {
+		makeModel("PRJ_mmpFILES\n"+
+				"makefile ..\\simple.mk build_as_arm\n"+
+				"another.mmp Build_as_ARM\n"+
+				"gnumakefile Icons_scalable_dc.mk tidy\n"+
+				"PRJ_TESTMMPFILES\n"+
+				"#ifdef WINSCW\n"+
+				"nmakefile msbuild.make\n"+
+				"#endif\n"
+				);
+
+		macros = new ArrayList<IDefine>();
+		macros.add(DefineFactory.createDefine("WINSCW"));
+
+		IBldInfView view = getView(config);
+		assertNotNull(view);
+		checkNoProblems(view);
+
+		_testMakefilesParsing1(view);
+		_testMakefilesParsing1(view.getData());
+		
+		view.dispose();
+		model.dispose();
+
+	}
+
+	private void _testMakefilesParsing1(IBldInfData bldInfData) {
+		List<IMakMakeReference> maks = bldInfData.getMakMakeReferences();
+		assertEquals(3, maks.size());
+		
+		
+		IMakefileReference makefile;
+		IMMPReference mmp;
+		
+		makefile = (IMakefileReference) maks.get(0);
+		assertEquals(EMakeEngine.MAKEFILE, makefile.getMakeEngine());
+		assertEquals(new Path("simple.mk"), makefile.getPath());
+		assertTrue(makefile.isBuildAsArm());
+		assertFalse(makefile.isTidy());
+		
+		mmp = (IMMPReference) maks.get(1);
+		assertEquals(new Path("group/another.mmp"), mmp.getPath());
+		assertTrue(mmp.isBuildAsArm());
+
+		makefile = (IMakefileReference) maks.get(2);
+		assertEquals(new Path("group/Icons_scalable_dc.mk"), makefile.getPath());
+		assertEquals(EMakeEngine.GNUMAKEFILE, makefile.getMakeEngine());
+		assertTrue(makefile.isTidy());
+		assertFalse(makefile.isBuildAsArm());
+
+
+		///
+		
+		List<IMakMakeReference> testmaks = bldInfData.getTestMakMakeReferences();
+		assertEquals(1, testmaks.size());
+		
+		makefile = (IMakefileReference) testmaks.get(0);
+		assertEquals(new Path("group/msbuild.make"), makefile.getPath());
+		assertEquals(EMakeEngine.NMAKEFILE, makefile.getMakeEngine());
+		assertFalse(makefile.isTidy());
+		assertFalse(makefile.isBuildAsArm());
+		///
+		
+		IMMPReference[] mmps = bldInfData.getAllMMPReferences();
+		assertEquals(1, mmps.length);
+		assertEquals(maks.get(1), mmps[0]);
+
+		IMakefileReference[] makefiles = bldInfData.getAllMakefileReferences();
+		assertEquals(3, makefiles.length);
+		assertEquals(maks.get(0), makefiles[0]);
+		assertEquals(maks.get(2), makefiles[1]);
+		assertEquals(testmaks.get(0), makefiles[2]);
+		
+		assertEquals(4, bldInfData.getAllMakMakeReferences().length);
+	}
+	
+	public void testMmpfilesChangingCond() throws Exception {
+		makeModel("PRJ_MMPFILES\n"+
+				"#ifdef MYTARGET\n"+
+				"foo.mmp\n"+
+				"#endif\n");
+
+		IBldInfView view = getView(config);
+		assertNotNull(view);
+
+		// don't remove apparently empty statements
+		commitTest(view, "PRJ_MMPFILES\n"+
+				"#ifdef MYTARGET\n"+
+				"foo.mmp\n"+
+				"#endif\n");
+	}
+
+	public void testMmpfilesChanging() throws Exception {
+		makeModel("PRJ_MMPFILES\n");
+
+		IBldInfView view = getView(config);
+		assertNotNull(view);
+
+		IMMPReference mmp = view.createMMPReference();
+		assertFalse(mmp.isValid());
+		
+		// don't emit invalid entries
+		view.getMakMakeReferences().add(mmp);
+		
+		commitTest(view, "PRJ_MMPFILES\n");
+		
+		///
+		
+		mmp = view.createMMPReference();
+		
+		mmp.setPath(new Path("group/program.mmp"));
+		view.getMakMakeReferences().add(mmp);
+		
+		commitTest(view, 
+				"PRJ_MMPFILES\n"+
+				"program.mmp\n");
+		
+		//
+		
+		mmp = view.createMMPReference();
+		mmp.setPath(new Path("another.mmp"));
+		mmp.setBuildAsArm(true);
+		mmp.setManual(false);
+		assertTrue(mmp.isBuildAsArm());
+		assertFalse(mmp.isManual());
+		view.getMakMakeReferences().add(mmp);
+
+		// bug 4726: new format is fwd slash
+		commitTest(view, 
+				"PRJ_MMPFILES\n"+
+				"program.mmp\n"+
+				"../another.mmp BUILD_AS_ARM\n");
+		
+		//
+		
+		view.getMakMakeReferences().remove(0);
+		commitTest(view, 
+				"PRJ_MMPFILES\n"+
+				"../another.mmp BUILD_AS_ARM\n");
+
+		///
+		
+		IMakefileReference makefile = view.createMakefileReference();
+		view.getMakMakeReferences().add(makefile);
+
+		// no empty nodes
+		commitTest(view, 
+				"PRJ_MMPFILES\n"+
+				"../another.mmp BUILD_AS_ARM\n");
+
+		///
+		
+		makefile = view.createMakefileReference();
+		view.getMakMakeReferences().add(makefile);
+		makefile.setMakeEngine(EMakeEngine.GNUMAKEFILE);
+		makefile.setPath(new Path("gfx/MakeGraphics.makefile"));
+
+		commitTest(view, 
+				"PRJ_MMPFILES\n"+
+				"../another.mmp BUILD_AS_ARM\n"+
+				"gnumakefile ../gfx/MakeGraphics.makefile\n");
+
+		
+		view.dispose();
+		model.dispose();
+
+	}
+	
+	public void testMmpfilesChanging2() throws Exception {
+		makeModel("PRJ_MMPFILES\n");
+
+		IBldInfView view = getView(config);
+		assertNotNull(view);
+
+		IMMPReference mmp = view.createMMPReference();
+		mmp = view.createMMPReference();
+		
+		// ensure user intent preserved
+		mmp.setPath(new Path("group/program"));
+		view.getMakMakeReferences().add(mmp);
+		
+		commitTest(view, 
+				"PRJ_MMPFILES\n"+
+				"program\n");
+
+		// ensure change matches existing mmp and results in no change
+		mmp = view.getAllMMPReferences()[0];
+		mmp.setPath(new Path("group/program.mmp"));
+
+		commitTest(view, 
+				"PRJ_MMPFILES\n"+
+				"program\n");
+
+		// ensure matches existing mmp
+		mmp = view.getAllMMPReferences()[0];
+		mmp.setManual(true);
+		
+		commitTest(view, 
+				"PRJ_MMPFILES\n"+
+				"program MANUAL\n");
+
+		// ensure matches...
+		view.getMakMakeReferences().remove(view.getAllMMPReferences()[0]);
+		
+		// leave empty sections
+		commitTest(view, 
+				"PRJ_MMPFILES\n");
+
+		
+		view.dispose();
+		model.dispose();
+
+	}
+	
+	public void testExportsParsing() {
+		makeModel("PRJ_EXPORTS\n"+
+				"../src/MyFile.txt\n"+
+				"// user mistake below, should be full path\n"+
+				"..\\gfx\\myfile.mbm sys\\resources\\MyApp\\myfile.mbm\n"+
+				"..\\group\\here.exe c:\\sys\\bin\\virus.exe\n"+
+				":zip v28archive.zip \\epoc32\\releases\\winscw\\patches\n");
+
+		IBldInfView view = getView(config);
+		assertNotNull(view);
+		checkNoProblems(view);
+
+		_testExportsParsing(view);
+		_testExportsParsing(view.getData());
+
+	}
+
+	private void _testExportsParsing(IBldInfData bldInfData) {
+		List<IExport> exports = bldInfData.getExports();
+		assertEquals(4, exports.size());
+		
+		IExport exp = exports.get(0);
+		assertEquals(new Path("src/MyFile.txt"), exp.getSourcePath());
+		// implicit
+		assertEquals(new Path("/epoc32/include/MyFile.txt"), exp.getTargetPath());
+		assertFalse(exp.isZipped());
+		
+		exp = exports.get(1);
+		assertEquals(new Path("gfx/myfile.mbm"), exp.getSourcePath());
+		// user mistake
+		assertEquals(new Path("/epoc32/include/sys/resources/MyApp/myfile.mbm"), exp.getTargetPath());
+		assertFalse(exp.isZipped());
+		
+		exp = exports.get(2);
+		assertEquals(new Path("group/here.exe"), exp.getSourcePath());
+		assertEquals(new Path("c:/sys/bin/virus.exe"), exp.getTargetPath());
+		assertFalse(exp.isZipped());
+
+		exp = exports.get(3);
+		assertEquals(new Path("group/v28archive.zip"), exp.getSourcePath());
+		assertEquals(new Path("/epoc32/releases/winscw/patches"), exp.getTargetPath());
+		assertTrue(exp.isZipped());
+	}
+	
+	public void testExportsChanging() {
+		makeModel("// my empty bld.inf\n"+
+				"PRJ_PLATFORMS DEFAULTS\n"+
+				"PRJ_MMPFILES\n"+
+				"PRJ_EXPORTS\n");
+		IBldInfView view = getView(config);
+		assertNotNull(view);
+
+		IExport exp = view.createExport();
+		exp.setSourcePath(new Path("src/MyFile.txt"));
+		assertEquals(new Path("src/MyFile.txt"), exp.getSourcePath());
+		view.getExports().add(exp);
+		
+		exp = view.createExport();
+		exp.setSourcePath(new Path("gfx/myfile.mbm"));
+		exp.setTargetPath(new Path("\\sys\\resources\\MyApp\\myfile.mbm"));
+		assertEquals(new Path("\\sys\\resources\\MyApp\\myfile.mbm"), exp.getTargetPath());
+		view.getExports().add(exp);
+
+		exp = view.createExport();
+		exp.setSourcePath(new Path("inc/header2.h"));
+		exp.setTargetPath(new Path("\\epoc32\\include\\header2.h"));
+		view.getExports().add(exp);
+
+		exp = view.createExport();
+		exp.setSourcePath(new Path("group/here.exe"));
+		exp.setTargetPath(new Path("c:/sys/bin/virus.exe"));
+		assertFalse(exp.isZipped());
+		view.getExports().add(exp);
+		
+		exp = view.createExport();
+		exp.setSourcePath(new Path("group/v28archive.zip"));
+		exp.setTargetPath(new Path("/epoc32/releases/winscw/patches"));
+		exp.setZipped(true);
+		assertTrue(exp.isZipped());
+		view.getExports().add(exp);
+
+		
+		commitTest(view, "// my empty bld.inf\n"+
+				"PRJ_PLATFORMS DEFAULTS\n"+
+				"PRJ_MMPFILES\n"+ 
+				"PRJ_EXPORTS\n"+
+				"../src/MyFile.txt\n"+
+				"../gfx/myfile.mbm /sys/resources/MyApp/myfile.mbm\n"+
+				"../inc/header2.h\n"+ // implicit path
+				"here.exe c:\\sys\\bin\\virus.exe\n"+  // backslash needed because of use of DOS 'copy' command
+				":zip v28archive.zip /epoc32/releases/winscw/patches\n");
+
+		///
+		
+		view.getExports().get(0).setZipped(true);
+		view.getExports().get(0).setTargetPath(new Path("/epoc32/include"));
+		commitTest(view, "// my empty bld.inf\n"+
+				"PRJ_PLATFORMS DEFAULTS\n"+
+				"PRJ_MMPFILES\n"+ 
+				"PRJ_EXPORTS\n"+
+				":zip ../src/MyFile.txt\n"+
+				"../gfx/myfile.mbm /sys/resources/MyApp/myfile.mbm\n"+
+				"../inc/header2.h\n"+ // implicit path
+				"here.exe c:\\sys\\bin\\virus.exe\n"+
+				":zip v28archive.zip /epoc32/releases/winscw/patches\n");
+		
+		view.dispose();
+		model.dispose();
+	}
+	
+	public void testExportsChanging2() {
+		makeModel("PRJ_EXPORTS\n"+
+				"../src/MyFile.txt\n"+
+				"// user mistake below, should be full path\n"+
+				"..\\gfx\\myfile.mbm sys\\resources\\MyApp\\myfile.mbm\n"+
+				"..\\group\\here.exe c:\\sys\\bin\\virus.exe\n"+
+				"// unchanged entry keeps comment\n"+
+				":zip v28archive.zip \\epoc32\\releases\\winscw\\patches\n");
+
+		IBldInfView view = getView(config);
+		assertNotNull(view);
+	
+		view.getExports().get(1).setTargetPath(new Path("\\sys\\resources\\MyApp\\myfile.mbm"));
+		
+		commitTest(view,
+				"PRJ_EXPORTS\n"+
+				"../src/MyFile.txt\n"+
+				"// user mistake below, should be full path\n"+
+				"..\\gfx\\myfile.mbm \\sys\\resources\\MyApp\\myfile.mbm\n"+ // keeps predom slash fmt
+				"..\\group\\here.exe c:\\sys\\bin\\virus.exe\n"+
+				"// unchanged entry keeps comment\n"+
+				":zip v28archive.zip \\epoc32\\releases\\winscw\\patches\n");
+		view.dispose();
+		model.dispose();
+	}
+
+	public void testExportsChanging3() {
+		makeModel("PRJ_EXPORTS\n"+
+				"../src/MyFile.txt\n"+
+				"..\\gfx\\myfile.mbm\n"+
+				":zip v28archive.zip\n");
+
+		IBldInfView view = getView(config);
+		assertNotNull(view);
+	
+		assertEquals(new Path("/epoc32/include/MyFile.txt"), view.getExports().get(0).getTargetPath());
+		assertEquals(new Path("/epoc32/include/myfile.mbm"), view.getExports().get(1).getTargetPath());
+		commitTest(view,
+				"PRJ_EXPORTS\n"+
+				"../src/MyFile.txt\n"+
+				"..\\gfx\\myfile.mbm\n"+
+				":zip v28archive.zip\n");
+		view.dispose();
+		model.dispose();
+	}
+	public void testProblems() {
+		makeModel("PRJ_UNKNOWN\n"+
+				"../src/MyFile.txt\n"+
+				"PRJ_PLATFORMS eee\n");
+
+		IBldInfView view = getView(config);
+		assertNotNull(view);
+		assertEquals(2, view.getMessages().length);
+	
+		commitTest(view,"PRJ_UNKNOWN\n"+
+				"../src/MyFile.txt\n"+
+				"PRJ_PLATFORMS eee\n");
+		assertEquals(2, view.getMessages().length);
+		
+		view.getPlatforms().add("ooo");
+
+		
+		commitTest(view,"PRJ_UNKNOWN\n"+
+				"../src/MyFile.txt\n"+
+				"PRJ_PLATFORMS eee ooo\n");
+		assertEquals(2, view.getMessages().length);
+	}
+	
+	public void testRootProject() {
+		// make sure we handle project root correctly when it's the root directory
+		for (int i = 0; i < 2; i++){
+			parserConfig.projectPath = i == 0 ? new Path("c:\\") : new Path("c:");
+			this.path = new Path("c:\\symbian\\9.1\\S60_3rd\\S60Ex\\Hello\\group\\bld.inf");
+			makeModel("PRJ_MMPFILES\n"+
+					"test.mmp\n");
+			
+			IBldInfView view =model.createView(config);
+			_testRootProject(view);
+			_testRootProject(view.getData());
+		}
+	}
+
+	private void _testRootProject(IBldInfData bldInfData) {
+		IMMPReference mmp = bldInfData.getAllMMPReferences()[0];
+		// important to be relative
+		assertEquals(new Path("symbian/9.1/S60_3rd/S60Ex/Hello/group/test.mmp"), mmp.getPath());
+	}
+	
+	/**
+	 * The base directory changes as files are #included
+	 *
+	 */
+	public void testBaseDirectory() {
+		parserConfig.getFilesystem().put(new Path("c:/test/bld.inf").toOSString(), 
+				"PRJ_MMPFILES\n"+
+				"base.mmp\n"+
+				"gnumakefile sub\\base.mk\n"+
+				"PRJ_EXPORTS\n"+
+				"base.txt\n");
+
+		parserConfig.getFilesystem().put(projectPath.append("utils").append("bld.inf").toOSString(),
+				"PRJ_EXPORTS\n"+
+				"utils.txt\n"+
+				"PRJ_MMPFILES\n"+
+				"utils.mmp\n"+
+				"nmakefile ..\\utils.mk\n");
+
+		makeModel(
+				"PRJ_MMPFILES\n"+
+				"first.mmp\n"+
+				"#include \"c:\\test\\bld.inf\"\n"+
+				"#include \"../utils/bld.inf\"\n"+
+				"PRJ_MMPFILES\n"+
+				"last.mmp\n" +
+				"PRJ_EXPORTS\n"+
+				"last.txt\n");
+
+		IBldInfView view = model.createView(config);
+		_testBaseDirectory(view);
+		_testBaseDirectory(view.getData());
+		
+	}
+
+	private void _testBaseDirectory(IBldInfData bldInfData) {
+		assertEquals(6, bldInfData.getMakMakeReferences().size());
+		
+		assertEquals(new Path("group/first.mmp"), bldInfData.getMakMakeReferences().get(0).getPath());
+		
+		// note: should not be relative path when outside the project
+		assertEquals(new Path("c:/test/base.mmp"), bldInfData.getMakMakeReferences().get(1).getPath());
+		assertEquals(new Path("c:/test/sub/base.mk"), bldInfData.getMakMakeReferences().get(2).getPath());
+		
+		assertEquals(new Path("utils/utils.mmp"), bldInfData.getMakMakeReferences().get(3).getPath());
+		assertEquals(new Path("utils.mk"), bldInfData.getMakMakeReferences().get(4).getPath());
+		
+		assertEquals(new Path("group/last.mmp"), bldInfData.getMakMakeReferences().get(5).getPath());
+
+		assertEquals(3, bldInfData.getExports().size());
+		assertEquals(new Path("c:/test/base.txt"), bldInfData.getExports().get(0).getSourcePath());
+		assertEquals(new Path("utils/utils.txt"), bldInfData.getExports().get(1).getSourcePath());
+		assertEquals(new Path("group/last.txt"), bldInfData.getExports().get(2).getSourcePath());
+	}
+	
+	public void testPreprocessorProblems() {
+		String string = "PRJ_MMPFILES\n"+
+						"#if 1\n"+
+						"first.mmp\n"+
+						"#else\n"+
+						"#if\n";
+		makeModel(string);
+
+		IBldInfView view = model.createView(config);
+		IASTProblemNode[] problemNodes = getProblems(view);
+		assertEquals(1, problemNodes.length);
+		checkMessages(problemNodes);
+		
+		assertEquals(1, view.getMakMakeReferences().size());
+
+		// ensure no crash
+		commitTest(view, string);
+		
+	}
+	
+	public void testIfNestingRecovery() {
+		String string = "\n" + 
+				"PRJ_PLATFORMS\n" + 
+				"DEFAULT\n" + 
+				"\n" + 
+				"PRJ_EXPORTS\n" + 
+				"\n" + 
+				"#ifndef RD_EMAIL_DOMAIN_UTILS\n" + 
+				"..\\Utils\\inc\\IMASettingsStorer.h \\epoc32\\include\\oem\\IMASettingsStorer.h\n" + 
+				"\n" + 
+				"PRJ_MMPFILES\n" + 
+				"..\\utils\\group\\ImumUtils.mmp\n" + 
+				"\n" + 
+				"// ********** NEW INTERNAL API PART\n" + 
+				"#else\n" + 
+				"..\\Utils_newApi\\inc\\IMPICMDS.H \\epoc32\\include\\oem\\impicmds.h\n" + 
+				"\n" + 
+				"PRJ_MMPFILES\n" + 
+				"..\\DomainApi\\group\\imumda.mmp\n" + 
+				"\n" + 
+				"#endif\n"; 
+				
+		makeModel(string);
+		
+		// normal case: macro not defined
+		IBldInfView view = model.createView(config);
+		checkNoProblems(view);
+		testSourceRegions(view, true);
+		
+		assertEquals(1, view.getMakMakeReferences().size());
+		assertEquals(1, view.getExports().size());
+		
+		commitTest(view, string);
+		// SPN case: "all" filter
+		//System.out.println("\\\\\\\\\\\\\\\\\\");
+		view.dispose();
+		view = model.createView(allConfig);
+		testSourceRegions(view, true);
+		
+		// should not continue reading #else part as MMPS
+		assertEquals(2, view.getMakMakeReferences().size());
+		assertEquals(2, view.getExports().size());
+		
+		commitTest(view, string);
+		
+	}
+	
+	public void testIfNestingRecovery2() {
+		String string = "\n" + 
+				"PRJ_PLATFORMS\n" +
+				"#ifdef RD_EMAIL_DOMAIN_UTILS\n" +
+				"WINSCW\n"+
+				"#endif\n"+
+				"ARMV5\n"+
+				"#if 1\n"+
+				"PRJ_EXPORTS\n"+
+				"..\\Utils\\inc\\IMASettingsStorer.h \\epoc32\\include\\oem\\IMASettingsStorer.h\n" +
+				"#else\n"+
+				"PRJ_MMPFILES\n"+
+				"test1.mmp\n"+
+				"	#if 1\n"+
+				"	test2.mmp\n"+
+				"	PRJ_EXPORTS\n"+
+				"	foo.txt foo.txt\n"+
+				"	#endif\n"+
+				"test3.mmp\n"+ // yup, this is an export 
+				"#endif\n"; 
+				
+		makeModel(string);
+		
+		// normal case: macro not defined
+		IBldInfView view = model.createView(config);
+		checkNoProblems(view);
+		testSourceRegions(view, true);
+
+		assertEquals(1, view.getPlatforms().size());
+		assertEquals(0, view.getMakMakeReferences().size());
+		assertEquals(1, view.getExports().size());
+		
+		commitTest(view, string);
+		
+		// SPN case: "all" filter
+		view.dispose();
+		
+		view = model.createView(allConfig);
+		testSourceRegions(view, true);
+
+		assertEquals(2, view.getPlatforms().size());
+		assertEquals(2, view.getMakMakeReferences().size());
+		assertEquals(3, view.getExports().size());
+
+		commitTest(view, string);
+
+	}
+	
+	public void testIfNestingRecovery3() {
+		String incl1 = "PRJ_PLATFORMS\n"+
+		"DEFAULT\n"+
+		"\n"+
+		"PRJ_EXPORTS\n" +
+		"foo1.txt foo1.txt\n"+
+		"\n"+
+		"PRJ_MMPFILES\n"+
+		"\n"+
+		"first.mmp\n"+
+		"\n"+
+		"#if 1\n"+
+		"makefile icons1.mk\n"+
+		"#else\n"+
+		"makefile icons2.mk\n"+
+		"#endif\n"+
+		"PRJ_TESTMMPFILES\n"
+		;
+		String incl2 = "PRJ_PLATFORMS\n"+
+		"\n"+
+		"DEFAULT\n"+
+		"\n"+
+		"PRJ_MMPFILES\n"+
+		"\n"+
+		"second.mmp\n"+
+		"PRJ_TESTMMPFILES\n";
+		String string = "\n" + 
+		"#if 1\n"+
+				"#include \"inc1.h\"\n"+
+				"#include \"inc2.h\"\n"+
+				"#endif\n"+
+				"PRJ_PLATFORMS\n"+
+				""
+		;
+		
+		parserConfig.getFilesystem().put("inc1.h", incl1);
+		parserConfig.getFilesystem().put("inc2.h", incl2);
+		makeModel(string);
+		
+		IBldInfView view = model.createView(allConfig);
+		testSourceRegions(view, true);
+
+		assertEquals(4, view.getMakMakeReferences().size());
+		assertEquals(2, view.getPlatforms().size());
+		assertEquals(1, view.getExports().size());
+		
+		commitTest(view, string);
+		
+	}
+	
+	public void testIfNestingRecovery4a() {
+		// note lack of newline after PRJ_MMPFILES
+		String inf = "PRJ_EXTENSIONS\r\n" + 
+				"start		extension		base/genexec\r\n" + 
+				"\r\n" + 
+				"option		EXTRA_SRC_PATH		$(EXTENSION_ROOT)/kernel\r\n" + 
+				"\r\n" + 
+				"end\r\n" +
+				"\r\n"+
+				"PRJ_MMPFILES\r\n" + 
+				"#if defined(GENERIC_MARM) || defined(WINS) || defined(GENERIC_X86)\r\n" + 
+				"\r\n" + 
+				"#if defined(GENERIC_MARM) && !defined(ARMCC)\r\n" + 
+				"euser/epoc/egcc\r\n" + 
+				"#endif\r\n" + 
+				"\r\n" + 
+				"euser/epoc/edllstub\r\n" + 
+				"euser/edll\r\n" + 
+				"euser/eexe\r\n" +
+				"#endif\n";
+		makeModel(inf);
+		IBldInfView view = model.createView(allConfig);
+		testSourceRegions(view, true);
+
+		checkNoProblems(view);
+		assertEquals(4, view.getMakMakeReferences().size());
+		commitTest(view, inf);
+
+	}
+
+	public void testIfNestingRecovery4b() {
+		// note extra newline after PRJ_MMPFILES
+		String inf = "PRJ_EXTENSIONS\r\n" + 
+				"start		extension		base/genexec\r\n" + 
+				"\r\n" + 
+				"option		EXTRA_SRC_PATH		$(EXTENSION_ROOT)/kernel\r\n" + 
+				"\r\n" + 
+				"end\r\n" +
+				"\r\n"+
+				"PRJ_MMPFILES\r\n" + 
+				"\r\n"+
+				"#if defined(GENERIC_MARM) || defined(WINS) || defined(GENERIC_X86)\r\n" + 
+				"\r\n" + 
+				"#if defined(GENERIC_MARM) && !defined(ARMCC)\r\n" + 
+				"euser/epoc/egcc\r\n" + 
+				"#endif\r\n" + 
+				"\r\n" + 
+				"euser/epoc/edllstub\r\n" + 
+				"euser/edll\r\n" + 
+				"euser/eexe\r\n" +
+				"#endif\n";
+		makeModel(inf);
+		IBldInfView view = model.createView(allConfig);
+		testSourceRegions(view, true);
+
+		checkNoProblems(view);
+		assertEquals(4, view.getMakMakeReferences().size());
+		commitTest(view, inf);
+
+	}
+	
+	/** These two test that PRJ_PLATFORMS properly has a newline or space
+	 * between its token and its arguments, AND that the list is terminated
+	 * by a newline.
+	 *
+	 */
+	public void testAddToEmptyPlatforms() {
+		makeModel("PRJ_PLATFORMS\n"+
+				"\n"+
+				"PRJ_MMPFILES\n"+
+				"PRJ_EXPORTS\n");
+		
+		IBldInfView view = model.createView(allConfig);
+		view.getPlatforms().add("WINSCW");
+		view.getPlatforms().add("GCCE");
+		
+		IMMPReference mmp = view.createMMPReference();
+		mmp.setPath(new Path("group/file.mmp"));
+		view.getMakMakeReferences().add(mmp);
+		
+		// bug was a missing newline AND space
+		commitTest(view,
+				"PRJ_PLATFORMS\n"+
+				"WINSCW GCCE\n"+
+				"\n"+
+				"PRJ_MMPFILES\n"+
+				"file.mmp\n"+
+				"PRJ_EXPORTS\n"+
+				"");
+								
+	}
+	/** These two test that PRJ_PLATFORMS properly has a newline or space
+	 * between its token and its arguments, AND that the list is terminated
+	 * by a newline.
+	 *
+	 */
+	public void testAddToEmptyPlatforms2() {
+		makeModel("PRJ_PLATFORMS\n"+
+				"PRJ_MMPFILES\n"+
+				"PRJ_EXPORTS\n");
+		
+		IBldInfView view = model.createView(allConfig);
+		view.getPlatforms().add("WINSCW");
+		view.getPlatforms().add("GCCE");
+
+		IMMPReference mmp = view.createMMPReference();
+		mmp.setPath(new Path("group/file.mmp"));
+		view.getMakMakeReferences().add(mmp);
+
+		// bug was a missing newline AND space
+		commitTest(view,
+				"PRJ_PLATFORMS\n"+
+				"WINSCW GCCE\n"+
+				"PRJ_MMPFILES\n"+
+				"file.mmp\n"+
+				"PRJ_EXPORTS\n");
+								
+	}
+	
+	public void testHugeMess() throws Exception {
+		String spdiaText = 
+				"#include <domain\\osextensions\\platform_paths.hrh>\r\n" + 
+				"PRJ_PLATFORMS\r\n" + 
+				"DEFAULT\r\n" + 
+				"\r\n" + 
+				"PRJ_EXPORTS\r\n" + 
+				"..\\ControlInc\\SpdiaControl.h APP_LAYER_SDK_EXPORT_PATH(SpdiaControl.h)\r\n" + 
+				"..\\inc\\sdm.hlp.hrh APP_LAYER_SDK_EXPORT_PATH(cshelp\\sdm.hlp.hrh)\r\n" + 
+				"\r\n" + 
+				"PRJ_MMPFILES\r\n" + 
+				"\r\n" + 
+				"\r\n" + 
+				" \r\n" + 
+				" #ifdef __SCALABLE_ICONS\r\n" + 
+				"	gnumakefile icons_dc_scalable_speeddial.mk\r\n" + 
+				"   gnumakefile icons_aif_scalable_dc_speeddial.mk\r\n" + 
+				" #else\r\n" + 
+				"	gnumakefile icons_dc_speeddial.mk\r\n" + 
+				"   gnumakefile icons_aif_bitmaps_dc_speeddial.mk\r\n" + 
+				" #endif\r\n" + 
+				" \r\n" + 
+				"gnumakefile icons_aif_scalable_speeddial.mk\r\n" + 
+				"\r\n" + 
+				"\r\n" + 
+				"SpdCtrl.mmp\r\n" + 
+				"SpeedDial.mmp\r\n" + 
+				"\r\n" + 
+				"PRJ_TESTMMPFILES\r\n" + 
+				"//..\\tsrc\\CVTSpeeddial.mmp  // CVT test case(s)\r\n" + 
+				"//..\\TVoiceMailboxCallRemote\\group\\TVoiceMailboxCallRemote.mmp\r\n" + 
+				"\r\n" + 
+				"// End of File"; 
+				
+		String phonebookuiText =  
+				"PRJ_PLATFORMS\r\n" + 
+				"DEFAULT\r\n" + 
+				"\r\n" + 
+				"// phonebookui subsystem\r\n" + 
+				"#include \"..\\Speeddial\\group\\bld.inf\"\r\n" +
+				"\r\n" + 
+				"PRJ_EXPORTS\r\n" + 
+				"\r\n" + 
+				"PRJ_MMPFILES\r\n" + 
+				"\r\n" + 
+				"PRJ_TESTMMPFILES\r\n" + 
+				"\r\n" + 
+				"PRJ_TESTEXPORTS\r\n" + 
+				"\r\n" + 
+				"\r\n" + 
+				"\r\n" + 
+				"//  End of File  \r\n"; 
+				
+		Map<String, String> originalFiles = new HashMap<String, String>();
+		originalFiles.put("..\\Speeddial\\group\\bld.inf", spdiaText);
+		// this fails
+		originalFiles.put("platform_paths.hrh", "\n"+"#ifndef MACRO\n"+"#define MACRO\n"+"\n"+"#endif\n"+"\n");
+		// this passes
+		//originalFiles.put("platform_paths.hrh", "#ifndef MACRO\n"+"#define MACRO\n"+"\n"+"#endif\n");
+		/////originalFiles.put("platform_paths.hrh", loadFileText("data/s60/platform_paths.hrh"));
+		/*
+		originalFiles.put("data_caging_paths.hrh", loadFileText("data/s60/data_caging_paths.hrh"));
+		originalFiles.put("bldvariant.hrh", loadFileText("data/s60/bldvariant.hrh"));
+		originalFiles.put("defaultcaps.hrh", loadFileText("data/s60/defaultcaps.hrh"));
+		originalFiles.put("features.hrh", loadFileText("data/s60/features.hrh"));
+		originalFiles.put("Symbian_OS_v9.3.hrh", loadFileText("data/s60/Symbian_OS_v9.3.hrh"));
+		originalFiles.put("ProductVariant.hrh", loadFileText("data/s60/ProductVariant.hrh"));
+		originalFiles.put("PbkConfig.hrh", loadFileText("data/s60/PbkConfig.hrh"));
+		*/
+		parserConfig.getFilesystem().clear();
+		for (Map.Entry<String, String> entry : originalFiles.entrySet()) {
+			parserConfig.getFilesystem().put(entry.getKey(), entry.getValue());
+		}
+		makeModel(phonebookuiText);
+		
+		macros.add(DefineFactory.createDefine("__SCALABLE_ICONS"));
+		
+		IBldInfView view = model.createView(config);
+		for (String s  : view.getPlatforms())
+			assertEquals("DEFAULT", s);
+		/*
+		for (String p : view.getPlatforms()) {
+			System.out.print(p + " ");
+		}
+		System.out.println();*/
+		IMessage[] messages = view.getMessages();
+		for (IMessage p : messages)
+			System.out.println(p);
+		assertEquals(0, messages.length);
+		commitTest(view, phonebookuiText);
+		//view.commit();
+
+		for (Map.Entry<String, String> entry : originalFiles.entrySet()) {
+			String curFile = parserConfig.getFilesystem().get(entry.getKey());
+			assertEquals(entry.getValue(), curFile);
+		}
+		
+		assertEquals(phonebookuiText, model.getDocument().get());
+
+	}
+	
+	public void testAddNewMMP() {
+		String text = 
+			"PRJ_PLATFORMS\r\n" + 
+			"DEFAULT\r\n" + 
+			"\r\n" + 
+			"PRJ_EXPORTS\r\n" + 
+			"//..\\Common\\inc\\MPlayerConstants.h           \\epoc32\\include\\oem\\MPlayerConstants.h\r\n" + 
+			"\r\n" + 
+			"PRJ_MMPFILES\r\n" + 
+			"\r\n" + 
+			"#ifdef __ACTIVE_IDLE  \r\n" + 
+			"gnumakefile ..\\ActiveIdlePlugin\\group\\PlayerPluginIcons.mk  \r\n" + 
+			"#endif // __ACTIVE_IDLE\r\n" + 
+			"\r\n" + 
+			"gnumakefile icons_dc.mk\r\n" + 
+			"\r\n" + 
+			"gnumakefile ..\\CollectionUi\\group\\CollectionUiIcons_dc.mk\r\n" + 
+			"gnumakefile ..\\PlaybackUi\\group\\PlaybackUiIcons_dc.mk\r\n" + 
+			"\r\n" + 
+			"#ifdef __SCALABLE_ICONS\r\n" + 
+			"gnumakefile Icons_aif_scalable_dc.mk\r\n" + 
+			"#else // __SCALABLE_ICONS\r\n" + 
+			"gnumakefile Icons_aif_bitmaps_dc.mk\r\n" + 
+			"#endif // __SCALABLE_ICONS\r\n" + 
+			"\r\n" + 
+			"..\\Collection\\group\\MCCommon.mmp\r\n" + 
+			"..\\Collection\\group\\MCClient.mmp\r\n" + 
+			"..\\Collection\\group\\MusicCollection.mmp\r\n" + 
+			"..\\Collection\\group\\MCFileHandler.mmp\r\n" + 
+			"..\\Collection\\group\\MCServer.mmp\r\n" + 
+			"\r\n" + 
+			"..\\DRMHelper\\group\\MPlayerDrmHelper.mmp\r\n" + 
+			"..\\Engine\\group\\MusicPlayerEngine.mmp\r\n" + 
+			"..\\CommonUi\\group\\MPlayerCommonUi.mmp\r\n" + 
+			"..\\PlaylistEditor\\group\\MPlayerPlaylistEditor.mmp\r\n" + 
+			"..\\CollectionUi\\group\\MPlayerCollectionUi.mmp\r\n" + 
+			"..\\PlaybackUi\\group\\MPlayerPlaybackUi.mmp\r\n" + 
+			"\r\n" + 
+			"..\\App\\group\\MusicPlayer.mmp\r\n" + 
+			"\r\n" + 
+			"..\\ActiveIdleEngine\\group\\MPlayerRemoteControl.mmp\r\n" + 
+			"..\\ActiveIdleEngine\\group\\RCtrlExtPluginInterface.mmp\r\n" + 
+			"#ifdef __ACTIVE_IDLE\r\n" + 
+			"..\\ActiveIdlePlugin\\group\\PlayerPlugin.mmp\r\n" + 
+			"#endif // __ACTIVE_IDLE\r\n" + 
+			"\r\n" + 
+			"PRJ_TESTMMPFILES\r\n"; 
+			
+		String text2 = 
+			"PRJ_PLATFORMS\r\n" + 
+			"DEFAULT\r\n" + 
+			"\r\n" + 
+			"PRJ_EXPORTS\r\n" + 
+			"//..\\Common\\inc\\MPlayerConstants.h           \\epoc32\\include\\oem\\MPlayerConstants.h\r\n" + 
+			"\r\n" + 
+			"PRJ_MMPFILES\r\n" + 
+			"\r\n" + 
+			"#ifdef __ACTIVE_IDLE  \r\n" + 
+			"gnumakefile ..\\ActiveIdlePlugin\\group\\PlayerPluginIcons.mk  \r\n" + 
+			"#endif // __ACTIVE_IDLE\r\n" + 
+			"\r\n" + 
+			"gnumakefile icons_dc.mk\r\n" + 
+			"\r\n" + 
+			"gnumakefile ..\\CollectionUi\\group\\CollectionUiIcons_dc.mk\r\n" + 
+			"gnumakefile ..\\PlaybackUi\\group\\PlaybackUiIcons_dc.mk\r\n" + 
+			"\r\n" + 
+			"#ifdef __SCALABLE_ICONS\r\n" + 
+			"gnumakefile Icons_aif_scalable_dc.mk\r\n" + 
+			"#else // __SCALABLE_ICONS\r\n" + 
+			"gnumakefile Icons_aif_bitmaps_dc.mk\r\n" + 
+			"#endif // __SCALABLE_ICONS\r\n" + 
+			"\r\n" + 
+			"..\\Collection\\group\\MCCommon.mmp\r\n" + 
+			"..\\Collection\\group\\MCClient.mmp\r\n" + 
+			"..\\Collection\\group\\MusicCollection.mmp\r\n" + 
+			"..\\Collection\\group\\MCFileHandler.mmp\r\n" + 
+			"..\\Collection\\group\\MCServer.mmp\r\n" + 
+			"\r\n" + 
+			"..\\DRMHelper\\group\\MPlayerDrmHelper.mmp\r\n" + 
+			"..\\Engine\\group\\MusicPlayerEngine.mmp\r\n" + 
+			"..\\CommonUi\\group\\MPlayerCommonUi.mmp\r\n" + 
+			"..\\PlaylistEditor\\group\\MPlayerPlaylistEditor.mmp\r\n" + 
+			"..\\CollectionUi\\group\\MPlayerCollectionUi.mmp\r\n" + 
+			"..\\PlaybackUi\\group\\MPlayerPlaybackUi.mmp\r\n" + 
+			"\r\n" + 
+			"..\\App\\group\\MusicPlayer.mmp\r\n" + 
+			"\r\n" + 
+			"..\\ActiveIdleEngine\\group\\MPlayerRemoteControl.mmp\r\n" + 
+			"..\\ActiveIdleEngine\\group\\RCtrlExtPluginInterface.mmp\r\n" + 
+			"second.mmp\r\n" + 
+			"#ifdef __ACTIVE_IDLE\r\n" + 
+			"..\\ActiveIdlePlugin\\group\\PlayerPlugin.mmp\r\n" + 
+			"#endif // __ACTIVE_IDLE\r\n" + 
+			"\r\n"+
+			"PRJ_TESTMMPFILES\r\n" + 
+			""; 
+		
+		makeModel(text);
+		IBldInfView view = model.createView(config);
+		IMMPReference mmp = view.createMMPReference();
+		mmp.setPath(new Path("group/second.mmp"));
+		view.getMakMakeReferences().add(mmp);
+		commitTest(view, text2);
+	}
+	
+	public void testEmptyStmts() {
+		String text = 
+			"PRJ_PLATFORMS\n"+
+			"DEFAULT\n" +
+			"PRJ_MMPFILES\n";
+		makeModel(text);
+		IBldInfView view = model.createView(config);
+		commitTest(view, text);
+		
+		IMMPReference reference = view.createMMPReference();
+		reference.setPath(new Path("group/foo.mmp"));
+		view.getMakMakeReferences().add(reference);
+		
+		String text2 = 
+			"PRJ_PLATFORMS\n"+
+			"DEFAULT\n" +
+			"PRJ_MMPFILES\n"+
+			"foo.mmp\n";
+		commitTest(view, text2);
+		
+	}
+	
+	public void testModifyingIncludes() {
+		String inclText = 
+			"//\r\n" + 
+			"// Platforms\r\n" + 
+			"//\r\n" + 
+			"PRJ_PLATFORMS\r\n" + 
+			"DEFAULT\r\n" + 
+			"\r\n" + 
+			"//\r\n" + 
+			"// Phonebook exports\r\n" + 
+			"//\r\n" + 
+			"PRJ_EXPORTS\r\n" + 
+			"\r\n" + 
+			"// Export only when flag is not set\r\n" + 
+			"#if !defined(RD_PHONEBOOK2)\r\n" + 
+			"\r\n" + 
+			"..\\PbkMMTelUtil\\Inc\\CPbkSimEntryCopyFactory.h 		\\epoc32\\include\\oem\\Phonebook\\CPbkSimEntryCopyFactory.h\r\n" + 
+			"..\\PbkUsimUI\\Inc\\CSimPdDocumentBase.h			\\epoc32\\include\\oem\\phonebook\\CSimPdDocumentBase.h\r\n" + 
+			"..\\PbkUsimUI\\Inc\\PbkUSimServAppDef.h			\\epoc32\\include\\oem\\phonebook\\PbkUSimServAppDef.h\r\n" + 
+			"\r\n" + 
+			"#endif // RD_PHONEBOOK2\r\n" + 
+			"\r\n" + 
+			"//\r\n" + 
+			"// Phonebook SIM Bridge components\r\n" + 
+			"//\r\n" + 
+			"PRJ_MMPFILES\r\n" + 
+			"\r\n" + 
+			"#if !defined(RD_PHONEBOOK2)\r\n" + 
+			"PbkMMTelUtil.mmp\r\n" + 
+			"PbkUSimUI.mmp\r\n" + 
+			"#endif // RD_PHONEBOOK2\r\n" + 
+			"\r\n" + 
+			"// End of file\r\n";
+		String text = 
+				"PRJ_PLATFORMS\n" +
+				"DEFAULT\n" +
+				"#include \"incl.inf\"\n";
+				
+		macros.add(DefineFactory.createDefine("RD_PHONEBOOK2", "1"));
+		parserConfig.getFilesystem().put("incl.inf", inclText);
+		makeModel(text);
+		IBldInfView view = model.createView(config);
+		commitTest(view, text);
+		assertEquals(inclText, parserConfig.getFilesystem().get("incl.inf"));
+		
+	}
+	
+	public void testSpacing() {
+		makeModel("");
+
+		IBldInfView view = getView(config);
+		assertNotNull(view);
+
+		List<String> platforms = view.getPlatforms();
+
+		platforms.add("WINSCW");
+		platforms.add("ARMV5");
+
+		IMMPReference mmp = view.createMMPReference();
+		
+		mmp.setPath(new Path("group/program.mmp"));
+		view.getMakMakeReferences().add(mmp);
+
+		IExport exp = view.createExport();
+		exp.setSourcePath(new Path("src/MyFile.txt"));
+		assertEquals(new Path("src/MyFile.txt"), exp.getSourcePath());
+		view.getExports().add(exp);
+
+		commitTest(view,
+				"PRJ_PLATFORMS\n" +
+				"WINSCW ARMV5\n" +
+				"\n" +
+				"PRJ_MMPFILES\n" +
+				"program.mmp\n" +
+				"\n" +
+				"PRJ_EXPORTS\n" +
+				"../src/MyFile.txt\n");
+				
+		mmp = view.createMMPReference();
+		mmp.setPath(new Path("group/test.mmp"));
+		view.getTestMakMakeReferences().add(mmp);
+
+		mmp = view.createMMPReference();
+		mmp.setPath(new Path("group/another.mmp"));
+		view.getMakMakeReferences().add(mmp);
+
+		commitTest(view,
+				"PRJ_PLATFORMS\n" +
+				"WINSCW ARMV5\n" +
+				"\n" +
+				"PRJ_MMPFILES\n" +
+				"program.mmp\n" +
+				"another.mmp\n" +
+				"\n" +
+				"PRJ_EXPORTS\n" +
+				"../src/MyFile.txt\n"+
+				"\n"+
+				"PRJ_TESTMMPFILES\n" +
+				"test.mmp\n");
+
+	}
+	
+	/** 
+	 * Bug 2770: don't add statements to blocks in other documents,
+	 * since this copies the entire block to the main file.
+	 *
+	 */
+	public void testLeaveNonMainBlocksAlone() {
+		// Note: the minimal case for this is much smaller, but
+		// might as well test with big real-life fileset.
+		String origFile = 
+			"/*\r\n" + 
+			"* ==============================================================================\r\n" + 
+			"*  Name        : bld.inf\r\n" + 
+			"*  Part of     : \r\n" + 
+			"*  Description : \r\n" + 
+			"*  Version     : \r\n" + 
+			"*\r\n" + 
+			"*  Copyright © 2006 Nokia. All rights reserved.\r\n" + 
+			"*  This material, including documentation and any related\r\n" + 
+			"*  computer programs, is protected by copyright controlled by\r\n" + 
+			"*  Nokia Corporation. All rights are reserved. Copying,\r\n" + 
+			"*  including reproducing, storing, adapting or translating, any\r\n" + 
+			"*  or all of this material requires the prior written consent of\r\n" + 
+			"*  Nokia. This material also contains confidential\r\n" + 
+			"*  information which may not be disclosed to others without the\r\n" + 
+			"*  prior written consent of Nokia.\r\n" + 
+			"* ==============================================================================\r\n" + 
+			"*/\r\n" + 
+			"\r\n" + 
+			"#include <domain\\osextensions\\platform_paths.hrh>\r\n" + 
+			"\r\n" + 
+			"PRJ_PLATFORMS\r\n" + 
+			"DEFAULT\r\n" + 
+			"\r\n" + 
+			"PRJ_EXPORTS\r\n" + 
+			"..\\inc_domain\\mcdef.h 						APP_LAYER_DOMAIN_EXPORT_PATH(mcdef.h)\r\n" + 
+			"..\\inc_domain\\MMusicShopBrViewCallback.h 			APP_LAYER_DOMAIN_EXPORT_PATH(MMusicShopBrViewCallback.h)\r\n" + 
+			"..\\inc_domain\\MPlayerAudioUIController.h			APP_LAYER_DOMAIN_EXPORT_PATH(MPlayerAudioUIController.h)\r\n" + 
+			"..\\inc_domain\\MPlayerConstants.h				APP_LAYER_DOMAIN_EXPORT_PATH(MPlayerConstants.h)\r\n" + 
+			"..\\inc_domain\\MPlayerDrmHelper.h				APP_LAYER_DOMAIN_EXPORT_PATH(MPlayerDrmHelper.h)\r\n" + 
+			"..\\inc_domain\\MPlayerPlaybackView.h				APP_LAYER_DOMAIN_EXPORT_PATH(MPlayerPlaybackView.h)\r\n" + 
+			"..\\inc_domain\\MPlayerPlaylistEditor.h				APP_LAYER_DOMAIN_EXPORT_PATH(MPlayerPlaylistEditor.h)\r\n" + 
+			"..\\inc_domain\\MPlayerPlaylistModel.h				APP_LAYER_DOMAIN_EXPORT_PATH(MPlayerPlaylistModel.h)\r\n" + 
+			"..\\inc_domain\\MPlayerRemoteControl.h				APP_LAYER_DOMAIN_EXPORT_PATH(MPlayerRemoteControl.h)\r\n" + 
+			"..\\inc_domain\\mplayersecondarydisplayapi.h			APP_LAYER_DOMAIN_EXPORT_PATH(mplayersecondarydisplayapi.h)\r\n" + 
+			"..\\inc_domain\\MPlayerUIControllerObserver.h			APP_LAYER_DOMAIN_EXPORT_PATH(MPlayerUIControllerObserver.h)\r\n" + 
+			"..\\inc_domain\\musicplayerdomaincrkeys.h				APP_LAYER_DOMAIN_EXPORT_PATH(musicplayerdomaincrkeys.h)\r\n" + 
+			"..\\inc_domain\\MusicShopEmbeddedLauncher.h			APP_LAYER_DOMAIN_EXPORT_PATH(MusicShopEmbeddedLauncher.h)\r\n" + 
+			"..\\inc_domain\\MusicShopExternalInterface.h			APP_LAYER_DOMAIN_EXPORT_PATH(MusicShopExternalInterface.h)\r\n" + 
+			"..\\inc_domain\\MusicVisualizationPlugin.h			APP_LAYER_DOMAIN_EXPORT_PATH(MusicVisualizationPlugin.h)\r\n" + 
+			"..\\inc_domain\\MusicPlayerInternalCRKeys.h 			APP_LAYER_DOMAIN_EXPORT_PATH(MusicPlayerInternalCRKeys.h)\r\n" + 
+			"\r\n" + 
+			"\r\n" + 
+			"PRJ_MMPFILES\r\n" + 
+			"#include \"..\\MusicPlayer\\group\\bld.inf\"\r\n" + 
+			"#include \"..\\MusicShop\\group\\bld.inf\"\r\n" + 
+			"#include \"..\\MusicVisualization\\group\\bld.inf\"\r\n" + 
+			"\r\n" + 
+			"\r\n" + 
+			"//  End of File  \r\n";
+		
+		String updatedFile = 
+			origFile + 
+			"\r\n"+
+			"PRJ_MMPFILES\r\n" +
+			"FMRadio.mmp\r\n";
+		String musicPlayerBldInf = 
+			"/*\r\n" + 
+			"* ==============================================================================\r\n" + 
+			"*  Name        : bld.inf\r\n" + 
+			"*  Part of     : MusicPlayer\r\n" + 
+			"*  Description : \r\n" + 
+			"*    This file provides the information required for building the\r\n" + 
+			"*    whole MusicPlayer application including all related libraries.\r\n" + 
+			"*  Version     : \r\n" + 
+			"*\r\n" + 
+			"*  Copyright © 2002-2006 Nokia Corporation.\r\n" + 
+			"*  This material, including documentation and any related \r\n" + 
+			"*  computer programs, is protected by copyright controlled by \r\n" + 
+			"*  Nokia Corporation. All rights are reserved. Copying, \r\n" + 
+			"*  including reproducing, storing, adapting or translating, any \r\n" + 
+			"*  or all of this material requires the prior written consent of \r\n" + 
+			"*  Nokia Corporation. This material also contains confidential \r\n" + 
+			"*  information which may not be disclosed to others without the \r\n" + 
+			"*  prior written consent of Nokia Corporation.\r\n" + 
+			"* ==============================================================================\r\n" + 
+			"*/\r\n" + 
+			"\r\n" + 
+			"PRJ_PLATFORMS\r\n" + 
+			"DEFAULT\r\n" + 
+			"\r\n" + 
+			"PRJ_EXPORTS\r\n" + 
+			"//..\\Common\\inc\\MPlayerConstants.h           \\epoc32\\include\\oem\\MPlayerConstants.h\r\n" + 
+			"//..\\Engine\\inc\\MPlayerPlaylistModel.h    \\epoc32\\include\\oem\\MPlayerPlaylistModel.h\r\n" + 
+			"//..\\PlaylistEditor\\inc\\MPlayerPlaylistEditor.h  \\epoc32\\include\\oem\\MPlayerPlaylistEditor.h\r\n" + 
+			"//..\\DRMHelper\\inc\\MPlayerDrmHelper.h     \\epoc32\\include\\oem\\MPlayerDrmHelper.h\r\n" + 
+			"//..\\Common\\Inc\\MusicPlayerInternalCRKeys.h \\epoc32\\include\\oem\\MusicPlayerInternalCRKeys.h\r\n" + 
+			"//..\\Common\\Inc\\musicplayerdomaincrkeys.h \\epoc32\\include\\oem\\musicplayerdomaincrkeys.h\r\n" + 
+			"//..\\Common\\Inc\\MusicPlayerInternalPSKeys.h \\epoc32\\include\\oem\\MusicPlayerInternalPSKeys.h\r\n" + 
+			"//..\\Engine\\inc\\MPlayerAudioUiController.h \\epoc32\\include\\oem\\MPlayerAudioUiController.h\r\n" + 
+			"//..\\Engine\\inc\\MPlayerUIControllerObserver.h \\epoc32\\include\\oem\\MPlayerUIControllerObserver.h\r\n" + 
+			"//..\\PlaybackUi\\inc\\MPlayerPlaybackView.h \\epoc32\\include\\oem\\MPlayerPlaybackView.h\r\n" + 
+			"//..\\Common\\inc\\mplayersecondarydisplayapi.h           \\epoc32\\include\\oem\\secondarydisplay\\mplayersecondarydisplayapi.h\r\n" + 
+			"//..\\ActiveIdleEngine\\Inc\\MPlayerRemoteControl.h \\epoc32\\include\\oem\\MPlayerRemoteControl.h \r\n" + 
+			"\r\n" + 
+			"//..\\collection\\inc\\mcdef.h \\epoc32\\include\\oem\\mcdef.h\r\n" + 
+			"\r\n" + 
+			"//Export the compiled DBMS policy file for the Music Collection DB...\r\n" + 
+			"\r\n" + 
+			"//for emulator\r\n" + 
+			"..\\Collection\\data\\101FE031.spd \\epoc32\\release\\winscw\\udeb\\z\\private\\100012a5\\policy\\101FE031.spd\r\n" + 
+			"..\\Collection\\data\\101FE031.spd \\epoc32\\release\\winscw\\urel\\z\\private\\100012a5\\policy\\101FE031.spd\r\n" + 
+			"\r\n" + 
+			"//for ROM building\r\n" + 
+			"..\\Collection\\data\\101FE031.spd \\epoc32\\data\\z\\private\\100012a5\\policy\\101FE031.spd\r\n" + 
+			"\r\n" + 
+			"// Empty sound file\r\n" + 
+			"..\\App\\data\\NullSound.mp3 \\epoc32\\release\\winscw\\udeb\\z\\private\\102072C3\\NullSound.mp3\r\n" + 
+			"..\\App\\data\\NullSound.mp3 \\epoc32\\release\\winscw\\urel\\z\\private\\102072C3\\NullSound.mp3\r\n" + 
+			"..\\App\\data\\NullSound.mp3 \\epoc32\\data\\z\\private\\102072C3\\NullSound.mp3\r\n" + 
+			"\r\n" + 
+			"// Secure backup & restore\r\n" + 
+			"backup_registration.xml \\epoc32\\RELEASE\\winscw\\urel\\z\\private\\102072C3\\backup_registration.xml\r\n" + 
+			"backup_registration.xml \\epoc32\\RELEASE\\winscw\\udeb\\z\\private\\102072C3\\backup_registration.xml\r\n" + 
+			"backup_registration.xml \\epoc32\\data\\z\\private\\102072C3\\backup_registration.xml\r\n" + 
+			"\r\n" + 
+			"PRJ_MMPFILES\r\n" + 
+			"\r\n" + 
+			"#ifdef __ACTIVE_IDLE  \r\n" + 
+			"gnumakefile ..\\ActiveIdlePlugin\\group\\PlayerPluginIcons.mk  \r\n" + 
+			"#endif // __ACTIVE_IDLE\r\n" + 
+			"\r\n" + 
+			"gnumakefile icons_dc.mk\r\n" + 
+			"\r\n" + 
+			"gnumakefile ..\\CollectionUi\\group\\CollectionUiIcons_dc.mk\r\n" + 
+			"gnumakefile ..\\PlaybackUi\\group\\PlaybackUiIcons_dc.mk\r\n" + 
+			"\r\n" + 
+			"#ifdef __SCALABLE_ICONS\r\n" + 
+			"gnumakefile Icons_aif_scalable_dc.mk\r\n" + 
+			"#else // __SCALABLE_ICONS\r\n" + 
+			"gnumakefile Icons_aif_bitmaps_dc.mk\r\n" + 
+			"#endif // __SCALABLE_ICONS\r\n" + 
+			"\r\n" + 
+			"..\\Collection\\group\\MCCommon.mmp\r\n" + 
+			"..\\Collection\\group\\MCClient.mmp\r\n" + 
+			"..\\Collection\\group\\MusicCollection.mmp\r\n" + 
+			"..\\Collection\\group\\MCFileHandler.mmp\r\n" + 
+			"..\\Collection\\group\\MCServer.mmp\r\n" + 
+			"\r\n" + 
+			"..\\DRMHelper\\group\\MPlayerDrmHelper.mmp\r\n" + 
+			"..\\Engine\\group\\MusicPlayerEngine.mmp\r\n" + 
+			"..\\CommonUi\\group\\MPlayerCommonUi.mmp\r\n" + 
+			"..\\PlaylistEditor\\group\\MPlayerPlaylistEditor.mmp\r\n" + 
+			"..\\CollectionUi\\group\\MPlayerCollectionUi.mmp\r\n" + 
+			"..\\PlaybackUi\\group\\MPlayerPlaybackUi.mmp\r\n" + 
+			"\r\n" + 
+			"..\\App\\group\\MusicPlayer.mmp\r\n" + 
+			"\r\n" + 
+			"..\\ActiveIdleEngine\\group\\MPlayerRemoteControl.mmp\r\n" + 
+			"..\\ActiveIdleEngine\\group\\RCtrlExtPluginInterface.mmp\r\n" + 
+			"#ifdef __ACTIVE_IDLE\r\n" + 
+			"..\\ActiveIdlePlugin\\group\\PlayerPlugin.mmp\r\n" + 
+			"#endif // __ACTIVE_IDLE\r\n" + 
+			"\r\n" + 
+			"PRJ_MMPFILES\r\n" + 
+			"PRJ_TESTMMPFILES\r\n" + 
+			"";
+		
+		String musicShopBldInf =
+			"/*\r\n" + 
+			"* ==============================================================================\r\n" + 
+			"*  Name		: bld.inf\r\n" + 
+			"*  Part of	: MusicShop\r\n" + 
+			"*  Description	: This is a top level bld file that drives all sub-components\r\n" + 
+			"*                that make up the MusicShopEmbed, MusicShopApp and MusicShopLib\r\n" + 
+			"*  Version	: %version: da1mmcf#15 %\r\n" + 
+			"*\r\n" + 
+			"*  Copyright © 2006 Nokia. All rights reserved.\r\n" + 
+			"*  This material, including documentation and any related\r\n" + 
+			"*  computer programs, is protected by copyright controlled by\r\n" + 
+			"*  Nokia Corporation. All rights are reserved. Copying,\r\n" + 
+			"*  including reproducing, storing, adapting or translating, any\r\n" + 
+			"*  or all of this material requires the prior written consent of\r\n" + 
+			"*  Nokia. This material also contains confidential\r\n" + 
+			"*  information which may not be disclosed to others without the\r\n" + 
+			"*  prior written consent of Nokia.\r\n" + 
+			"* ==============================================================================\r\n" + 
+			"*/\r\n" + 
+			"\r\n" + 
+			"PRJ_PLATFORMS\r\n" + 
+			"DEFAULT\r\n" + 
+			"\r\n" + 
+			"PRJ_EXPORTS\r\n" + 
+			"\r\n" + 
+			"PRJ_MMPFILES\r\n" + 
+			"\r\n" + 
+			"#ifdef __SERIES60_NATIVE_BROWSER\r\n" + 
+			"gnumakefile MusicShop_Icons_dc.mk\r\n" + 
+			"\r\n" + 
+			"#ifdef __SCALABLE_ICONS\r\n" + 
+			"  gnumakefile MusicShop_Icons_aif_scalable_dc.mk\r\n" + 
+			"#else // !__SCALABLE_ICONS\r\n" + 
+			"  gnumakefile MusicShop_Icons_aif_bitmaps_dc.mk\r\n" + 
+			"#endif // __SCALABLE_ICONS\r\n" + 
+			"\r\n" + 
+			"..\\musicshopembed\\group\\MusicShopEmbed.mmp\r\n" + 
+			"..\\musicshoplib\\group\\musicshoplib.mmp\r\n" + 
+			"..\\musicshopapp\\group\\musicshopapp.mmp\r\n" + 
+			"\r\n" + 
+			"#endif // __SERIES60_NATIVE_BROWSER\r\n" + 
+			"\r\n" + 
+			"\r\n" + 
+			"//  End of File\r\n" + 
+			"";
+		String musicVisualizationBldInf =
+			"/*\r\n" + 
+			"* ==============================================================================\r\n" + 
+			"*  Name        : bld.inf\r\n" + 
+			"*  Part of     : MusicVisualization\r\n" + 
+			"*  Description : \r\n" + 
+			"*    This file provides the information required for building the\r\n" + 
+			"*    all MusicVisualization projects including plugins.\r\n" + 
+			"*  Version     : \r\n" + 
+			"*\r\n" + 
+			"*  Copyright © 2005 Nokia Corporation.\r\n" + 
+			"*  This material, including documentation and any related \r\n" + 
+			"*  computer programs, is protected by copyright controlled by \r\n" + 
+			"*  Nokia Corporation. All rights are reserved. Copying, \r\n" + 
+			"*  including reproducing, storing, adapting or translating, any \r\n" + 
+			"*  or all of this material requires the prior written consent of \r\n" + 
+			"*  Nokia Corporation. This material also contains confidential \r\n" + 
+			"*  information which may not be disclosed to others without the \r\n" + 
+			"*  prior written consent of Nokia Corporation.\r\n" + 
+			"* ==============================================================================\r\n" + 
+			"*/\r\n" + 
+			"\r\n" + 
+			"PRJ_PLATFORMS\r\n" + 
+			"DEFAULT\r\n" + 
+			"\r\n" + 
+			"PRJ_EXPORTS\r\n" + 
+			"\r\n" + 
+			"\r\n" + 
+			"PRJ_MMPFILES\r\n" + 
+			"\r\n" + 
+			"gnumakefile ..\\Plugins\\MVPOscilloscope\\Group\\Icons_oscilloscope.mk\r\n" + 
+			"gnumakefile ..\\Plugins\\MVPSpectrum\\Group\\Icons_spectrum.mk\r\n" + 
+			"\r\n" + 
+			"..\\Group\\MusicVisualizationPlugin.mmp\r\n" + 
+			"..\\Plugins\\MVPOscilloscope\\Group\\MVPOscilloscope.mmp\r\n" + 
+			"..\\Plugins\\MVPSpectrum\\Group\\MVPSpectrum.mmp\r\n" + 
+			"\r\n" + 
+			"PRJ_TESTMMPFILES\r\n" + 
+			"\r\n" + 
+			"// End of File\r\n" ; 
+			
+		parserConfig.getFilesystem().put("..\\MusicPlayer\\group\\bld.inf", musicPlayerBldInf);
+		parserConfig.getFilesystem().put("..\\MusicShop\\group\\bld.inf", musicShopBldInf);
+		parserConfig.getFilesystem().put("..\\MusicVisualization\\group\\bld.inf", musicVisualizationBldInf);
+			
+		makeModel(origFile);
+		
+		IBldInfView view = getView(config);
+		assertNotNull(view);
+		
+		IMMPReference ref = view.createMMPReference();
+		ref.setPath(new Path("group\\FMRadio.mmp"));
+		view.getMakMakeReferences().add(ref);
+		
+		commitTest(view, updatedFile);
+		assertEquals(parserConfig.getFilesystem().get("..\\MusicPlayer\\group\\bld.inf"), musicPlayerBldInf);
+		assertEquals(parserConfig.getFilesystem().get("..\\MusicShop\\group\\bld.inf"), musicShopBldInf);
+		assertEquals(parserConfig.getFilesystem().get("..\\MusicVisualization\\group\\bld.inf"), musicVisualizationBldInf);
+ 
+	}
+	
+	
+	/**
+	 * When we have a change that would affect another document,
+	 * then the entire node is changed and the node moves into
+	 * the main document.  When deleting stuff, the case is even worse
+	 * since updated nodes are replicated in main file, meaning
+	 * delete doesn't happen at all. 
+	 * <p>
+	 *  Bug 2784
+	 */
+	public void testDeleteFromOtherDocument() {
+		String incFile =
+			"PRJ_MMPFILES\n" +
+			"first.mmp\n"+
+			"second.mmp\n";
+		
+		String mainFile = "#include \"inc.inf\"\n";
+		
+		String inclFile = "inc.inf";
+		parserConfig.getFilesystem().put(inclFile, incFile);
+		makeModel(mainFile);
+		
+		IBldInfView view = getView(config);
+		assertEquals(2, view.getMakMakeReferences().size());
+		
+		view.getMakMakeReferences().remove(0);
+		
+		commitTest(view, 
+				"#include \"inc.inf\"\n" +
+				"");
+		assertEquals(
+				"PRJ_MMPFILES\n" +
+				"second.mmp\n",
+				parserConfig.getFilesystem().get(inclFile));
+		
+		assertEquals(1, view.getMakMakeReferences().size());
+		view.getMakMakeReferences().remove(0);
+		
+		commitTest(view, 
+				"#include \"inc.inf\"\n" +
+				"");
+		assertEquals("PRJ_MMPFILES\n" + 
+				"", 
+				parserConfig.getFilesystem().get(inclFile));
+		
+		
+	}
+	
+	public void testBug2856() {
+		String includedFile = 
+			"PRJ_EXPORTS\r\n" + 
+			"we_symbian_variant.h\r\n" + 
+			"\r\n" + 
+			"PRJ_MMPFILES\r\n" + 
+			"#include \"..\\bld2.inf\"\r\n" + 
+			"#include \"..\\..\\ui\\common\\ControlLibUIQ\\group\\bld.inf\"\r\n" + 
+			"\r\n" + 
+			"";
+		String includedFile2 = 
+			"PRJ_MMPFILES\r\n" +
+			"other.mmp\r\n" +
+			"\r\n" + 
+			"";		
+		String mainFile =  
+				"PRJ_MMPFILES\r\n" + 
+				"#include \"..\\bld1.inf\"\r\n" + 
+				"app.mmp\r\n";
+		
+		path = projectPath.append("bld.inf");
+		parserConfig.getFilesystem().put(projectPath.removeLastSegments(1).append("bld1.inf").toOSString(),
+				includedFile);
+		parserConfig.getFilesystem().put(projectPath.removeLastSegments(2).append("bld2.inf").toOSString(),
+				includedFile2);
+		makeModel(mainFile);
+
+		IBldInfView view = getView(config);
+		assertEquals(2, view.getMakMakeReferences().size());
+		// outside proj, so absolute
+		assertEquals(projectPath.removeLastSegments(2).append("other.mmp"), 
+				view.getMakMakeReferences().get(0).getPath());
+		// inside proj, so relative
+		assertEquals(new Path("app.mmp"), 
+				view.getMakMakeReferences().get(1).getPath());
+
+	}
+	
+	public void testBug3060_1() {
+		String text= "PRJ_MMPFILES\n"+
+		"test.mmp\n"+
+		"#if 0\n"+ 
+		"@idiot\n"+
+		"#endif\n"+
+		"";
+		
+		makeModel(text);
+		IBldInfView view = getView(config);
+		commitTest(view, text);
+		
+	}
+	public void testBug3060_2() {
+		// this shouldn't crash or corrupt the rewritten file
+		String text= "PRJ_MMPFILES\n"+
+		"test.mmp\n"+
+		"#ifdef 0\n"+ // yes, IFDEF 0!!! 
+		"@idiot\n"+
+		"#endif\n"+
+		"";
+		
+		makeModel(text);
+		IBldInfView view = getView(config);
+		commitTest(view, text);
+	}
+	
+	public void testBlockSyncsOverIncludes() {
+		
+		String text = "#include \"outer1.inf\"\r\n" + 
+				"#include \"outer2.inf\"\r\n" + 
+				"";
+		String outer1 = 
+				//"#include <domain\\osextensions\\platform_paths.hrh>\r\n" + 
+				"\r\n" + 
+				"PRJ_PLATFORMS\r\n" + 
+				"DEFAULT\r\n" + 
+				"\r\n" + 
+				"PRJ_EXPORTS\r\n" + 
+				"..\\inc\\cphonecntfactory.h                   |..\\..\\..\\inc\\cphonecntfactory.h\r\n" + 
+				"..\\group\\phonecntfinder_stub.SIS            \\epoc32\\data\\z\\system\\install\\phonecntfinder_stub.SIS\r\n" + 
+				"\r\n" + 
+				"PRJ_MMPFILES\r\n" + 
+				"..\\group\\phonecntfinder.mmp\r\n" + 
+				"\r\n" + 
+				"// PhoneCntFinderExt.\r\n" + 
+				"#include \"inner1.inf\"\r\n" + 
+				"\r\n" + 
+				"// End of File\r\n" + 
+				"";
+		
+		String outer2 = 
+				// 2 - 23
+				"\r\n" + 
+				"#ifndef RD_PHONE_NG\r\n" +
+				// 23-168
+				"\r\n" + 
+				"PRJ_PLATFORMS\r\n" + 
+				"DEFAULT\r\n" + 
+				"\r\n" + 
+				"PRJ_EXPORTS\r\n" + 
+				"\r\n" + 
+				"// audio \r\n" + 
+				"..\\inc\\audio\\MPhEngAudio.h                                    |..\\..\\..\\inc\\MPhEngAudio.h\r\n" + 
+				"#ifndef RD_VOIP_REL_2_2\r\n" +
+				// 193-289
+				"..\\inc\\dtmfhandling\\CPhEngDtmfSender.h                        |..\\..\\..\\inc\\CPhEngDtmfSender.h\r\n" + 
+				"#endif\r\n" + 
+				// 297-408
+				"\r\n" + 
+				"\r\n" + 
+				"// engine base\r\n" + 
+				"..\\inc\\enginebase\\CPhEngModel.h                               |..\\..\\..\\inc\\CPhEngModel.h\r\n" + 
+				"#if defined(__VOIP) && defined(RD_VOIP_REL_2_2)\r\n" +
+				// 461-683
+				"..\\inc\\extensions\\mctipluginuids.h                                     |..\\..\\..\\inc\\mctipluginuids.h\r\n" + 
+				"..\\inc\\extensions\\phoneecomplugininterfaceuids.hrh                     |..\\..\\..\\inc\\phoneecomplugininterfaceuids.hrh\r\n" + 
+				"#endif // __VOIP && RD_VOIP_REL_2_2\r\n" + 
+				"\r\n" + 
+				// 716-855
+				// this line is corrupted due to the missync above
+				"// sis stub file\r\n" + 
+				"phoneengine_stub.sis   \\epoc32\\data\\z\\system\\install\\phoneengine_stub.sis\r\n" + 
+				"\r\n" + 
+				"PRJ_MMPFILES\r\n" + 
+				"..\\Group\\PhoneEngine.mmp\r\n" + 
+				"\r\n" + 
+				"#endif // RD_PHONE_NG\r\n" + 
+				"\r\n" + 
+				// 878-896
+				"// End of File\r\n" + 
+				"";
+		String inner1 = 
+				"\r\n" + 
+				"PRJ_PLATFORMS\r\n" + 
+				"DEFAULT\r\n" + 
+				"\r\n" + 
+				"PRJ_EXPORTS\r\n" + 
+				"..\\group\\phcntvoicerecoghandler_stub.SIS    \\epoc32\\data\\z\\system\\install\\phcntvoicerecoghandler_stub.SIS\r\n" + 
+				"\r\n" + 
+				"PRJ_MMPFILES\r\n" + 
+				"..\\group\\PhCntVoiceRecogHandler.mmp\r\n" + 
+				"\r\n" + 
+				"PRJ_TESTMMPFILES\r\n" + 
+				"\r\n" + 
+				"// End of File\r\n" + 
+				"";
+		
+		String inclFile = projectPath.append("outer1.inf").toOSString();
+		parserConfig.getFilesystem().put(inclFile, outer1);
+		inclFile = projectPath.append("inner1.inf").toOSString();
+		parserConfig.getFilesystem().put(inclFile, inner1);
+		inclFile = projectPath.append("outer2.inf").toOSString();
+		parserConfig.getFilesystem().put(inclFile, outer2);
+
+		makeModel(text);
+		IBldInfView view = getView(config);
+		checkNoProblems(view);
+		assertEquals(0, view.getTestMakMakeReferences().size());
+		
+	}
+	
+
+}