예제 #1
0
        private XmlOutputData ReadXmlForOutputFiles(string xmlPath, string subFolder)
        {
            XmlOutputData outputData = new XmlOutputData();

            try
            {
                // load in the xml file
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(xmlPath);

                // there should be at least one output node
                XmlNodeList outputNodes = xmlDoc.SelectNodes("//output");
                if (outputNodes.Count > 0)
                {
                    // create the list now and use the number of nodes as the initial capacity
                    outputData.OutputFiles    = new List <string>(outputNodes.Count);
                    outputData.OutputMapFiles = new List <string>(outputNodes.Count);

                    for (int ndx = 0; ndx < outputNodes.Count; ++ndx)
                    {
                        // get the output path attribute and add it to the output files list
                        XmlAttribute pathAttribute = outputNodes[ndx].Attributes["path"];

                        // must exist and be non-empty for the purposes of this unit test because we
                        // can't really check for stdout files in this batch mode
                        if (pathAttribute == null || string.IsNullOrEmpty(pathAttribute.Value))
                        {
                            Assert.Fail("XML <output> nodes without path attributes not supported in unit tests");
                        }

                        // create the full path from the output folder, the subfolder, and the attribute.
                        // don't check for existence here -- we haven't run the test yet
                        string outputPath = GetJsPath(
                            m_outputFolder,
                            subFolder,
                            pathAttribute.Value,
                            false
                            );

                        // if the output file exists, it must be from a previous run.
                        // delete it now (the Delete method does not fail if the doesn't already exist,
                        // but it WILL fail if the path to the file doesn't)
                        if (File.Exists(outputPath))
                        {
                            File.Delete(outputPath);
                        }

                        outputData.OutputFiles.Add(outputPath);

                        XmlAttribute mapPathAttribute = outputNodes[ndx].Attributes["mappath"];
                        if (mapPathAttribute != null)
                        {
                            string mapPath = this.BuildFullPath(
                                m_outputFolder,
                                subFolder,
                                mapPathAttribute.Value,
                                ".xml",
                                false
                                );

                            if (File.Exists(mapPath))
                            {
                                File.Delete(mapPath);
                            }

                            outputData.OutputMapFiles.Add(mapPath);
                        }
                    }
                }
                else
                {
                    Assert.Fail("XML input file contains no <output> nodes");
                }
            }
            catch (XmlException e)
            {
                Debug.WriteLine(e.ToString());
                Assert.Fail("XML Exception processing XML input file: {0}", e.Message);
            }

            return(outputData);
        }
예제 #2
0
        public void RunTest(bool inputExpected, string extraArguments, params string[] extraInputs)
        {
            // open the stack trace for this call
            StackTrace stackTrace = new StackTrace();
            string     testClass  = null;
            string     testName   = null;

            // save the name of the current method (RunTest)
            string currentMethodName = MethodInfo.GetCurrentMethod().Name;

            // loop from the previous frame up until we get a method name that is not the
            // same as the current method name
            for (int ndx = 1; ndx < stackTrace.FrameCount; ++ndx)
            {
                // get the frame
                StackFrame stackFrame = stackTrace.GetFrame(ndx);

                // we have different entry points with the same name -- we're interested
                // in the first one that ISN'T the same name as our method
                MethodBase methodBase = stackFrame.GetMethod();
                if (methodBase.Name != currentMethodName)
                {
                    // the calling method's name is the test name - we use this as-is for the output file name
                    // and we use any portion before an underscore as the input file
                    testName = methodBase.Name;
                    // get the method's class - we use this as the subfolder under input/output/expected
                    testClass = methodBase.DeclaringType.Name;
                    break;
                }
            }
            // we definitely should be able to find a function on the stack frame that
            // has a different name than this function, but just in case...
            Debug.Assert(testName != null && testClass != null, "Couldn't locate calling stack frame");

            // the output file is just the full test name
            string        outputFile     = testName;
            string        outputMapFile  = null;
            List <string> outputFiles    = null;
            List <string> outputMapFiles = null;

            // the input file is the portion of the test name before the underscore (if any)
            string inputFile  = testName.Split('_')[0];
            string inputPath  = null;
            int    inputCount = 0;

            // create a list we will append all our arguments to
            bool includeAnalysis     = true;
            bool specifiesRename     = false;
            LinkedList <string> args = new LinkedList <string>();

            if (!string.IsNullOrEmpty(extraArguments))
            {
                // split on spaces
                string[] options = extraArguments.Split(' ');

                // add each one to the args list
                for (int ndx = 0; ndx < options.Length; ++ndx)
                {
                    string option = options[ndx];

                    // ignore empty strings
                    if (option.Length > 0)
                    {
                        args.AddLast(option);
                        if (string.Compare(option, "-analyze", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            // don't include it -- we already added it
                            includeAnalysis = false;
                        }
                        else if (string.Compare(option, "-xml", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            // the next option should be an xml file name, so we'll add an option
                            // that is the test name, the .xml suffix, and scope it to the input path.
                            // set the inputPath variable to this path so we know we are going to use it
                            // as the "input"
                            inputPath = BuildFullPath(
                                InputFolder,
                                testClass,
                                inputFile,
                                ".xml",
                                true
                                );
                            args.AddLast(inputPath);
                            ++inputCount;

                            XmlOutputData outputData = ReadXmlForOutputFiles(inputPath, testClass);
                            outputFiles    = outputData.OutputFiles;
                            outputMapFiles = outputData.OutputMapFiles;

                            // generate the expected file names from the output file names, plus any test qualifiers
                        }
                        else if (string.Compare(option, "-rename", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            // rename with no param parts (a colon and other stuff) means the next
                            // option should be an xml file name, so we'll add an option
                            // that is the file scoped to the input path.
                            string nextFile = options[++ndx];

                            string renamePath = BuildFullPath(
                                InputFolder,
                                testClass,
                                Path.GetFileNameWithoutExtension(nextFile),
                                Path.GetExtension(nextFile),
                                true);

                            // add that scoped path to the arguments
                            args.AddLast(renamePath);
                        }
                        // the -r option can have a subpart, eg: -res:Strings, so only test to see if
                        // the first two characters of the current option are "-res"
                        else if (option.StartsWith("-res", StringComparison.OrdinalIgnoreCase))
                        {
                            // the next option is a resource file name, so we'll need to scope it to the input path
                            // FIRST we'll try to see if there's an existing compiled .RESOURCES file with the same
                            // name as the current test. eg: if test name is "foo_h", look for foo.resources
                            string resourcePath = BuildFullPath(
                                InputFolder,
                                testClass,
                                inputFile,
                                ".resources",
                                false
                                );
                            if (!File.Exists(resourcePath))
                            {
                                // if there's not .RESOURCES file, look for a .RESX file with the same
                                // name as the current test. eg: if test name is "foo_h", look for foo.resx
                                resourcePath = BuildFullPath(
                                    InputFolder,
                                    testClass,
                                    inputFile,
                                    ".resx",
                                    false
                                    );
                                if (!File.Exists(resourcePath))
                                {
                                    // doesn't exist!
                                    Assert.Fail(
                                        "Expected resource file does not exist for test '{0}' in folder {1}",
                                        inputFile,
                                        Path.Combine(InputFolder, testClass)
                                        );
                                }
                            }
                            args.AddLast(resourcePath);
                        }
                        else if (option.StartsWith("-rename:", StringComparison.OrdinalIgnoreCase) &&
                                 option.IndexOf('=') < 0 && option.IndexOf("prop", StringComparison.OrdinalIgnoreCase) < 0)
                        {
                            specifiesRename = true;
                        }
                        else if (option.StartsWith("-map", StringComparison.OrdinalIgnoreCase))
                        {
                            outputMapFile = GetJsPath(
                                m_outputFolder,
                                testClass,
                                outputFile,
                                false
                                ) + ".map";

                            if (File.Exists(outputMapFile))
                            {
                                File.Delete(outputMapFile);
                            }

                            args.AddLast(outputMapFile);
                        }
                    }
                }
            }

            // if we haven't already specified analyze option
            if (includeAnalysis)
            {
                // add the -a option
                args.AddLast("-analyze");
            }
            // if we haven't already specified a renaming option, we will
            // use -rename:none so we don't have to always figure out what the hypercrunch
            // should be
            if (!specifiesRename)
            {
                args.AddLast("-rename:none");
            }

            string outputPath = null;

            // if we haven't already set an input path, then we want to calculate the input/output
            // paths automatically from the test name (normal case)
            if (inputPath == null)
            {
                // compute the path to the output file
                outputPath = GetJsPath(
                    m_outputFolder,
                    testClass,
                    outputFile,
                    false
                    );

                // if it exists already, delete it
                if (File.Exists(outputPath))
                {
                    File.Delete(outputPath);
                }

                // add the output parameter to the end
                args.AddLast("-out");
                args.AddLast(outputPath);

                Trace.WriteLine("INPUT FILE(S):");

                // calculate the input path
                inputPath = GetJsPath(
                    InputFolder,
                    testClass,
                    inputFile,
                    false
                    );

                // always add the input file to the command line
                args.AddLast(inputPath);
                if (File.Exists(inputPath))
                {
                    // but don't trace its contents unless it actually exists
                    ++inputCount;
                    TraceFileContents(inputPath);
                }
                else
                {
                    Trace.WriteLine("[input file does not exist]");
                }

                // if there are any extra input files, add them now
                if (extraInputs != null && extraInputs.Length > 0)
                {
                    foreach (string extraInput in extraInputs)
                    {
                        if (extraInput.Length > 0)
                        {
                            // get the full path
                            inputPath = GetJsPath(
                                InputFolder,
                                testClass,
                                extraInput,
                                true
                                );

                            // add it to the list
                            args.AddLast(inputPath);

                            // output the file contents
                            Trace.WriteLine(string.Empty);
                            TraceFileContents(inputPath);
                            ++inputCount;
                        }
                    }
                }
            }
            else
            {
                Trace.WriteLine("INPUT FILE:");
                TraceFileContents(inputPath);
            }

            // create an array of strings the appropriate size
            string[] mainArguments = new string[args.Count];
            // copy the arguments to the array
            args.CopyTo(mainArguments, 0);

            // show command-line args
            Trace.WriteLine(string.Empty);
            Trace.WriteLine("COMMAND-LINE SWITCHES:");
            foreach (string arg in mainArguments)
            {
                if (arg.IndexOf(' ') >= 0)
                {
                    // at least one space -- enclose the argument in quotes
                    Trace.Write('"');
                    Trace.Write(arg);
                    Trace.Write('"');
                }
                else
                {
                    // no spaces; don't need quotes
                    Trace.Write(arg);
                }
                Trace.Write(' ');
            }
            Trace.WriteLine(string.Empty);

            // call the NUglify main function
            Trace.WriteLine(string.Empty);
            Trace.WriteLine("AJAXMIN Debug Spew:");

            // call Main directly
            int retValue = MainClass.Main(mainArguments);

            Trace.Write("RETURN CODE: ");
            Trace.WriteLine(retValue);

            // after the run, if we had inputs and one output file...
            if (inputCount > 0 && !string.IsNullOrEmpty(outputPath))
            {
                // compute the path to the expected file
                string expectedPath = GetJsPath(
                    m_expectedFolder,
                    testClass,
                    outputFile,
                    false
                    );

                Trace.WriteLine(string.Empty);
                Trace.WriteLine("odd \"" + expectedPath + "\" \"" + outputPath + "\"");

                Trace.WriteLine(string.Empty);
                Trace.WriteLine("EXPECTED OUTPUT FILE:");
                if (File.Exists(expectedPath))
                {
                    // trace output contents
                    TraceFileContents(expectedPath);
                }
                else
                {
                    // no expected file means we expect the output to be empty
                    Trace.WriteLine("File doesn't exist -- expect output file to be empty");
                }

                // the output file BETTER exist (even if it's just empty)...
                if (File.Exists(outputPath))
                {
                    Trace.WriteLine(string.Empty);
                    Trace.WriteLine("ACTUAL OUTPUT FILE:");
                    // trace output contents
                    TraceFileContents(outputPath);

                    // fail the test if the files do not match
                    AssertCompareTextFiles(outputPath, expectedPath);
                    //Assert.IsTrue(retValue == 0, "Run didn't succeed. Return code: {0}", retValue);
                }
                else if (File.Exists(expectedPath))
                {
                    // no output file, but we did expect an output! That is a failure
                    Assert.Fail("Output file does not exist, but one was expected!");
                }
                else
                {
                    // input file(s) and output file, but can't find output
                    Assert.IsTrue(
                        retValue != 0,
                        "Run shouldn't succeed if no output is generated. Return code: {0}; output file: {1}",
                        retValue,
                        outputPath
                        );
                }

                if (outputMapFile != null)
                {
                    string expectedMapFile = this.BuildFullPath(
                        m_expectedFolder,
                        testClass,
                        Path.GetFileName(outputMapFile),
                        ".map",
                        true
                        );

                    this.CompareSymbolMapFiles(outputMapFile, expectedMapFile);
                }
            }
            else if (inputCount > 0)
            {
                if (outputFiles != null && outputFiles.Count > 0)
                {
                    // get the test suffix, if any
                    var testSuffix    = string.Empty;
                    var ndxUnderscore = testName.IndexOf('_');
                    if (ndxUnderscore > 0)
                    {
                        // we have one. Use it as a suffix for the expected file
                        testSuffix = testName.Substring(ndxUnderscore);
                    }

                    // for each one...
                    for (int ndx = 0; ndx < outputFiles.Count; ++ndx)
                    {
                        outputPath = outputFiles[ndx];

                        // compute the expected file path from the filename of the output path
                        // with any test extension added
                        string expectedPath = GetJsPath(
                            m_expectedFolder,
                            testClass,
                            Path.GetFileNameWithoutExtension(outputPath) + testSuffix + Path.GetExtension(outputPath),
                            false
                            );

                        // trace the expected file contents
                        Trace.WriteLine(string.Empty);
                        Trace.WriteLine(string.Format("EXPECTED OUTPUT FILE {0}:", ndx + 1));
                        if (File.Exists(expectedPath))
                        {
                            // trace output contents
                            TraceFileContents(expectedPath);
                        }
                        else
                        {
                            // no expected file means we expect the output to be empty
                            Trace.WriteLine("File doesn't exist -- expect output file to be empty");
                        }

                        // trace the output file contents
                        Trace.WriteLine(string.Empty);
                        Trace.WriteLine(string.Format("ACTUAL OUTPUT FILE {0}:", ndx + 1));
                        // trace output contents
                        if (File.Exists(outputPath))
                        {
                            TraceFileContents(outputPath);
                        }
                        else
                        {
                            Trace.WriteLine("Output file doesn't exist");
                        }

                        // fail the entire test if the files do not match
                        AssertCompareTextFiles(outputPath, expectedPath);
                    }
                }
                else
                {
                    // input file(s), but no output file
                    Assert.Fail("No output files");
                }

                if (outputMapFiles != null)
                {
                    for (int ndx = 0; ndx < outputMapFiles.Count; ++ndx)
                    {
                        outputMapFile = outputMapFiles[ndx];

                        string expectedMapFile = this.BuildFullPath(
                            m_expectedFolder,
                            testClass,
                            Path.GetFileNameWithoutExtension(outputMapFile),
                            ".xml",
                            true
                            );

                        this.CompareSymbolMapFiles(outputMapFile, expectedMapFile);
                    }
                }
            }
            else
            {
                // no input file(s)
                Trace.WriteLine("No input file(s).");

                // if we expected there to be input files, then we failed
                Assert.IsFalse(inputExpected, "Expected input files to exist");
                // and if we didn't expect the input files to exist, we better have failed
                Assert.IsTrue(retValue != 0, "Run shouldn't succeed if no input file(s). Return code: {0}", retValue);
            }
        }