/// <summary>
        /// This overrides the CodeDomTest Run method that does verification
        /// on the tree provided in the BuildTree method you provide.
        /// </summary>
        /// <param name="provider">Provider to test.</param>
        /// <returns>True if the tree builds, compiles, searches and passes
        /// assembly verification.  False if any of these fails.</returns>
        public override bool Run (CodeDomProvider provider) {
            bool fail = false;

            // build the tree
            LogMessageIndent ();
            LogMessage ("- Generating tree.");
            CodeCompileUnit cu = new CodeCompileUnit ();
            LogMessageIndent ();
            BuildTree (provider, cu);
            LogMessageUnindent ();

            // validate tree using 'experimental' subset tester
            // but only if the test believes its in the subset
            if ((TestType & TestTypes.Subset) != 0) {
                SubsetConformance subsConf = new SubsetConformance ();
                LogMessage ("- Checking tree subset conformance.");
                if (!subsConf.ValidateCodeCompileUnit (cu))
                    LogMessage ("Failed subset tester: {0}",
                            subsConf.ToString ());
            }

            // realize source
            StringWriter sw = new StringWriter (CultureInfo.InvariantCulture);
#if WHIDBEY
            provider.GenerateCodeFromCompileUnit (cu, sw, GetGeneratorOptions (provider));
#else
            ICodeGenerator generator = provider.CreateGenerator ();
            generator.GenerateCodeFromCompileUnit (cu, sw, GetGeneratorOptions (provider));
#endif

            // only continue if the source could be realized into a string.
            if (!fail) {
                string source = sw.ToString ();

                if (saveSourceFileName.Length > 0) {
                    LogMessage ("- Saving source into '" + saveSourceFileName + "'");

                    // save this source to a file
                    DumpStringToFile (source, saveSourceFileName);
                }

                // log the source code
                //LogMessage (source);

                // search the source if the test case asks us to
                if (ShouldSearch) {
                    LogMessageIndent ();
                    Search (provider, source);
                    LogMessageUnindent ();
                }
                
                // continue only if the test case wants to compile or verify
                if (ShouldCompile || ShouldVerify) {

                    // ask the test case which compiler parameters it would like to use
                    CompilerParameters parms = GetCompilerParameters (provider);

#if FSHARP
                    // If the generated code has entrypoint, then F# requires us to generate EXE
                    bool hasEntryPoint = false;
                    foreach(CodeNamespace ns in cu.Namespaces)
                        foreach (CodeTypeDeclaration ty in ns.Types)
                            foreach(CodeTypeMember mem in ty.Members)
                                if (mem is CodeEntryPointMethod) { hasEntryPoint = true; }

                    // If the output file name is specified then it should be EXE
                    if (hasEntryPoint && parms.GenerateExecutable == false)
                    {
                        parms.GenerateExecutable = true;
                        if (saveAssemblyFileName.ToLower().EndsWith(".dll"))
                            saveAssemblyFileName = saveAssemblyFileName.Substring(0, saveAssemblyFileName.Length - 4) + ".exe";
                    }
#endif
                    
                    // add the appropriate compiler parameters if the user asked us
                    // to save assemblies to file
                    if (saveAssemblyFileName.Length > 0) {
                        parms.OutputAssembly = saveAssemblyFileName;
                        LogMessage ("- Compiling to '" + saveAssemblyFileName + "'.");
                    }

                    // always generate in memory for verification purposes
                    parms.GenerateInMemory = true;

                    // compile!
#if WHIDBEY
                    CompilerResults results = provider.CompileAssemblyFromDom (parms, cu);
#else
                    ICodeCompiler compiler = provider.CreateCompiler ();
                    CompilerResults results = compiler.CompileAssemblyFromDom (parms, cu);
#endif

                    if (results.NativeCompilerReturnValue != 0) {
                        // compilation failed
                        fail = true;
                        LogMessage ("- Compilation failed.");
                        
                        // log the compilation failed output
                        foreach (string msg in results.Output)
                            LogMessage (msg);

                    } else if (ShouldVerify) {
                        // compilation suceeded and we are asked to verify the
                        // compiled assembly
                        LogMessage ("- Verifying assembly.");

                        // verify the compiled assembly if it's there
                        if (results.CompiledAssembly != null) {
                            LogMessageIndent ();
                            VerifyAssembly (provider, results.CompiledAssembly);
                            LogMessageUnindent ();
                        }
                    }
                }
            }

            if (fail || !AreAllValidated ()) {
                // one of the steps above failed or a scenario was not
                // verified within the test case
                fail = true;
                LogMessage ("! Test '" + Name + "' failed.");

                // output failing scenarios
                if (!AreAllValidated()) {
                    LogMessage ("! Failing scenarios:");
                    foreach (Scenario s in GetNotValidated())
                    {
                        LogMessage ("-  " + s.ToString());
                    }
                }
            } else {
                // test passed
                LogMessage ("* Test '" + Name + "' passed.");
            }
            LogMessageUnindent ();

            // return true on success, false on failure
            return !fail;
        }
        /// <summary>
        /// This overrides the CodeDomTest Run method that does verification
        /// on the tree provided in the BuildTree method you provide.
        /// </summary>
        /// <param name="provider">Provider to test.</param>
        /// <returns>True if the tree builds, compiles, searches and passes
        /// assembly verification.  False if any of these fails.</returns>
        public override bool Run(CodeDomProvider provider)
        {
            bool fail = false;

            // build the tree
            LogMessageIndent();
            LogMessage("- Generating tree.");
            CodeCompileUnit cu = new CodeCompileUnit();

            LogMessageIndent();
            BuildTree(provider, cu);
            LogMessageUnindent();

            // validate tree using 'experimental' subset tester
            // but only if the test believes its in the subset
            if ((TestType & TestTypes.Subset) != 0)
            {
                SubsetConformance subsConf = new SubsetConformance();
                LogMessage("- Checking tree subset conformance.");
                if (!subsConf.ValidateCodeCompileUnit(cu))
                {
                    LogMessage("Failed subset tester: {0}",
                               subsConf.ToString());
                }
            }

            // realize source
            StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);

#if WHIDBEY
            provider.GenerateCodeFromCompileUnit(cu, sw, GetGeneratorOptions(provider));
#else
            ICodeGenerator generator = provider.CreateGenerator();
            generator.GenerateCodeFromCompileUnit(cu, sw, GetGeneratorOptions(provider));
#endif

            // only continue if the source could be realized into a string.
            if (!fail)
            {
                string source = sw.ToString();

                if (saveSourceFileName.Length > 0)
                {
                    LogMessage("- Saving source into '" + saveSourceFileName + "'");

                    // save this source to a file
                    DumpStringToFile(source, saveSourceFileName);
                }

                // log the source code
                //LogMessage (source);

                // search the source if the test case asks us to
                if (ShouldSearch)
                {
                    LogMessageIndent();
                    Search(provider, source);
                    LogMessageUnindent();
                }

                // continue only if the test case wants to compile or verify
                if (ShouldCompile || ShouldVerify)
                {
                    // ask the test case which compiler parameters it would like to use
                    CompilerParameters parms = GetCompilerParameters(provider);

#if FSHARP
                    // If the generated code has entrypoint, then F# requires us to generate EXE
                    bool hasEntryPoint = false;
                    foreach (CodeNamespace ns in cu.Namespaces)
                    {
                        foreach (CodeTypeDeclaration ty in ns.Types)
                        {
                            foreach (CodeTypeMember mem in ty.Members)
                            {
                                if (mem is CodeEntryPointMethod)
                                {
                                    hasEntryPoint = true;
                                }
                            }
                        }
                    }

                    // If the output file name is specified then it should be EXE
                    if (hasEntryPoint && parms.GenerateExecutable == false)
                    {
                        parms.GenerateExecutable = true;
                        if (saveAssemblyFileName.ToLower().EndsWith(".dll"))
                        {
                            saveAssemblyFileName = saveAssemblyFileName.Substring(0, saveAssemblyFileName.Length - 4) + ".exe";
                        }
                    }
#endif

                    // add the appropriate compiler parameters if the user asked us
                    // to save assemblies to file
                    if (saveAssemblyFileName.Length > 0)
                    {
                        parms.OutputAssembly = saveAssemblyFileName;
                        LogMessage("- Compiling to '" + saveAssemblyFileName + "'.");
                    }

                    // always generate in memory for verification purposes
                    parms.GenerateInMemory = true;

                    // compile!
#if WHIDBEY
                    CompilerResults results = provider.CompileAssemblyFromDom(parms, cu);
#else
                    ICodeCompiler   compiler = provider.CreateCompiler();
                    CompilerResults results  = compiler.CompileAssemblyFromDom(parms, cu);
#endif

                    if (results.NativeCompilerReturnValue != 0)
                    {
                        // compilation failed
                        fail = true;
                        LogMessage("- Compilation failed.");

                        // log the compilation failed output
                        foreach (string msg in results.Output)
                        {
                            LogMessage(msg);
                        }
                    }
                    else if (ShouldVerify)
                    {
                        // compilation suceeded and we are asked to verify the
                        // compiled assembly
                        LogMessage("- Verifying assembly.");

                        // verify the compiled assembly if it's there
                        if (results.CompiledAssembly != null)
                        {
                            LogMessageIndent();
                            VerifyAssembly(provider, results.CompiledAssembly);
                            LogMessageUnindent();
                        }
                    }
                }
            }

            if (fail || !AreAllValidated())
            {
                // one of the steps above failed or a scenario was not
                // verified within the test case
                fail = true;
                LogMessage("! Test '" + Name + "' failed.");

                // output failing scenarios
                if (!AreAllValidated())
                {
                    LogMessage("! Failing scenarios:");
                    foreach (Scenario s in GetNotValidated())
                    {
                        LogMessage("-  " + s.ToString());
                    }
                }
            }
            else
            {
                // test passed
                LogMessage("* Test '" + Name + "' passed.");
            }
            LogMessageUnindent();

            // return true on success, false on failure
            return(!fail);
        }