Exemplo n.º 1
0
        public static TestStatistics TestVendorSamples(VendorSampleDirectory samples, string bspDir, string temporaryDirectory, double testProbability = 1)
        {
            const string defaultToolchainID = "SysGCC-arm-eabi-5.3.0";
            var toolchainPath = (string)Registry.CurrentUser.OpenSubKey(@"Software\Sysprogs\GNUToolchains").GetValue(defaultToolchainID);
            if (toolchainPath == null)
                throw new Exception("Cannot locate toolchain path from registry");

            var toolchain = LoadedToolchain.Load(Environment.ExpandEnvironmentVariables(toolchainPath), new ToolchainRelocationManager());
            var bsp = LoadedBSP.Load(new BSPManager.BSPSummary(Environment.ExpandEnvironmentVariables(Path.GetFullPath(bspDir))), toolchain);

            TestStatistics stats = new TestStatistics();
            int cnt = 0, failed = 0, succeeded = 0;
            LoadedBSP.LoadedMCU[] MCUs = bsp.MCUs.ToArray();
            string outputDir = Path.Combine(temporaryDirectory, "VendorSamples");
            if (!Directory.Exists(outputDir))
                Directory.CreateDirectory(outputDir);
            int sampleCount = samples.Samples.Length;
            Random rng = new Random();
            using (var r = new TestResults(Path.Combine(temporaryDirectory, "bsptest.log")))
            {
                foreach (var vs in samples.Samples)
                {
                    LoadedBSP.LoadedMCU mcu;

                    try
                    {
                        var rgFilterID = new Regex(vs.DeviceID.Replace('x', '.'), RegexOptions.IgnoreCase);
                        mcu = bsp.MCUs.Where(f => rgFilterID.IsMatch(f.ExpandedMCU.ID)).ToArray()?.First();
                        vs.DeviceID = mcu.ExpandedMCU.ID;
                    }
                    catch (Exception ex)
                    {
                        r.ExceptionSample(ex.Message, "mcu " + vs.DeviceID + " not found in bsp");
                        Console.WriteLine("bsp have not mcu:" + vs.DeviceID);
                        continue;
                    }

                    if (testProbability < 1 && rng.NextDouble() > testProbability)
                    {
                        cnt++;
                        continue;
                    }

                    bool aflSoftFPU = true;
                    string mcuDir = Path.Combine(temporaryDirectory, "VendorSamples", vs.UserFriendlyName);
                    if (!Directory.Exists(mcuDir))
                        Directory.CreateDirectory(mcuDir);
                    if (vs.UserFriendlyName.ToUpper().Contains("RTOS"))
                        aflSoftFPU = false;
                    DateTime start = DateTime.Now;
                    var result = TestVendorSample(mcu, vs, mcuDir, aflSoftFPU, samples);

                    Console.WriteLine($"[{(DateTime.Now - start).TotalMilliseconds:f0} msec]");

                    if (result == TestResult.Failed)
                        failed++;
                    else if (result == TestResult.Succeeded)
                        succeeded++;

                    r.LogTestResult(vs.UserFriendlyName, result);
                    cnt++;
                    Console.WriteLine("{0}: {1}% done ({2}/{3} projects, {4} failed)", vs.UserFriendlyName, (cnt * 100) / sampleCount, cnt, sampleCount, failed);
                }
            }

            stats.Passed += succeeded;
            stats.Failed += failed;
            if (samples is ConstructedVendorSampleDirectory)
            {
                (samples as ConstructedVendorSampleDirectory).ToolchainDirectory = toolchainPath;
                (samples as ConstructedVendorSampleDirectory).BSPDirectory = Path.GetFullPath(bspDir);
            }
            return stats;
        }
Exemplo n.º 2
0
        private static TestResult TestVendorSample(LoadedBSP.LoadedMCU mcu, BSPEngine.VendorSample vs, string mcuDir, bool pSoftFPU, VendorSampleDirectory sampleDir)
        {
            var configuredMCU = new LoadedBSP.ConfiguredMCU(mcu, GetDefaultPropertyValues(mcu.ExpandedMCU.ConfigurableProperties));
            if (configuredMCU.ExpandedMCU.FLASHSize == 0)
            {
                configuredMCU.Configuration["com.sysprogs.bspoptions.primary_memory"] = "sram";
            }
            var bspDict = configuredMCU.BuildSystemDictionary(new BSPManager(), null);
            bspDict["PROJECTNAME"] = "test";
            bspDict["SYS:VSAMPLE_DIR"] = sampleDir.Path;
            var prj = new GeneratedProject(configuredMCU, vs, mcuDir, bspDict, vs.Configuration.Frameworks ?? new string[0]);

            var frameworkCfg = PropertyDictionary2.ReadPropertyDictionary(vs.Configuration.Configuration);
            var frameworkIDs = vs.Configuration.Frameworks?.ToDictionary(fw => fw, fw => true);
            prj.AddBSPFilesToProject(bspDict, frameworkCfg, frameworkIDs);
            var flags = prj.GetToolFlags(bspDict, frameworkCfg, frameworkIDs);

            //ToolFlags flags = new ToolFlags { CXXFLAGS = "  ", COMMONFLAGS = "-mcpu=cortex-m3  -mthumb", LDFLAGS = "-Wl,-gc-sections -Wl,-Map," + "test.map", CFLAGS = "-ffunction-sections -Os -MD" };
            if (!pSoftFPU)
                flags.COMMONFLAGS = flags.COMMONFLAGS.Replace("soft", "hard");

            flags.CFLAGS += " -MD";
            flags.CXXFLAGS += " -MD";

            flags.IncludeDirectories = LoadedBSP.Combine(flags.IncludeDirectories, vs.IncludeDirectories);
            flags.PreprocessorMacros = LoadedBSP.Combine(flags.PreprocessorMacros, vs.PreprocessorMacros);

            flags = LoadedBSP.ConfiguredMCU.ExpandToolFlags(flags, bspDict, null);

            Dictionary<string, bool> sourceExtensions = new Dictionary<string, bool>(StringComparer.InvariantCultureIgnoreCase);
            sourceExtensions.Add("c", true);
            sourceExtensions.Add("cpp", true);

            return BuildAndRunValidationJob(mcu, mcuDir, false, null, prj, flags, sourceExtensions, null, vs);
        }
Exemplo n.º 3
0
        public virtual Dictionary <string, string> InsertVendorSamplesIntoBSP(ConstructedVendorSampleDirectory dir, VendorSample[] sampleList, string bspDirectory)
        {
            List <VendorSample> finalSamples = new List <VendorSample>();

            string outputDir = Path.Combine(bspDirectory, "VendorSamples");

            if (Directory.Exists(outputDir))
            {
                Console.WriteLine($"Deleting {outputDir}...");
                Directory.Delete(outputDir, true);
            }

            var mapper = CreatePathMapper(dir) ?? new PathMapper(dir);

            Dictionary <string, string> copiedFiles = new Dictionary <string, string>();

            Console.WriteLine("Processing sample list...");

            List <string> tooLongPaths = new List <string>();

            foreach (var s in sampleList)
            {
                if (s.AllDependencies == null)
                {
                    continue;
                }

                var deps = s.AllDependencies
                           .Concat(new[] { s.LinkerScript })
                           .Concat(s.SourceFiles)
                           .Distinct()
                           .Select(d => new ParsedDependency {
                    OriginalFile = d, MappedFile = mapper.MapPath(d)
                })
                           .Where(d => d.MappedFile != null)
                           .ToArray();

                mapper.MapPathList(ref s.HeaderFiles);
                mapper.MapPathList(ref s.IncludeDirectories);
                mapper.MapPathList(ref s.SourceFiles);

                s.LinkerScript = mapper.MapPath(s.LinkerScript);

                s.Configuration = DetectKnownFrameworksAndFilterPaths(ref s.SourceFiles, ref s.HeaderFiles, ref s.IncludeDirectories, ref s.PreprocessorMacros, ref deps, s.Configuration);
                FilterPreprocessorMacros(ref s.PreprocessorMacros);

                const int ReasonableVendorSampleDirPathLengthForUsers = 120;

                foreach (var dep in deps)
                {
                    if (dep.MappedFile.StartsWith("$$SYS:BSP_ROOT$$/"))
                    {
                        continue;   //The file was already copied
                    }
                    copiedFiles[dep.OriginalFile] = dep.MappedFile.Replace(SampleRootDirMarker, outputDir);

                    int estimatedTargetPathLength = ReasonableVendorSampleDirPathLengthForUsers + dep.MappedFile.Length - SampleRootDirMarker.Length;
                    if (estimatedTargetPathLength > 254)
                    {
                        tooLongPaths.Add(dep.MappedFile);
                    }
                }

                s.AllDependencies = deps.Select(d => d.MappedFile).ToArray();

                var rawPath = s.Path;
                s.Path = mapper.MapPath(rawPath);
                if (s.Path == null)
                {
                    throw new Exception("Invalid sample path for " + s.UserFriendlyName);
                }

                s.VirtualPath = BuildVirtualSamplePath(s.Path);

                if (s.LinkerScript != null)
                {
                    string prefix = s.Path.TrimEnd('/', '\\') + "/";
                    if (s.LinkerScript.StartsWith(prefix))
                    {
                        s.LinkerScript = s.LinkerScript.Substring(prefix.Length).TrimStart('/');
                    }
                    else if (s.LinkerScript.StartsWith("$$SYS:BSP_ROOT$$") || s.LinkerScript.StartsWith("$$SYS:VSAMPLE_DIR$$"))
                    {
                        //Nothing to do. VisualGDB will automatically expand this.
                    }
                    else
                    {
                        throw new Exception($"Unexpected linker script path {s.LinkerScript}. VisualGDB may not be able to expand it.");
                    }
                }

                finalSamples.Add(s);
            }

            if (tooLongPaths.Count > 0)
            {
                throw new Exception($"Found {tooLongPaths.Count} files with excessively long paths. Please update MapPath() in the BSP-specific path mapper to shorten the target paths.");
            }

            Console.WriteLine($"Copying {copiedFiles.Count} files...");
            foreach (var kv in copiedFiles)
            {
                Directory.CreateDirectory(Path.GetDirectoryName(kv.Value));
                if (!File.Exists(kv.Value))
                {
                    File.Copy(kv.Key, kv.Value);
                }
                File.SetAttributes(kv.Value, File.GetAttributes(kv.Value) & ~(FileAttributes.ReadOnly | FileAttributes.Hidden | FileAttributes.System));
            }

            Console.WriteLine("Updating BSP...");
            VendorSampleDirectory finalDir = new VendorSampleDirectory {
                Samples = finalSamples.ToArray()
            };

            Directory.CreateDirectory(outputDir);

            using (var fs = File.Create(Path.Combine(outputDir, "VendorSamples.xml.gz")))
                using (var gs = new GZipStream(fs, CompressionMode.Compress))
                {
                    XmlTools.SaveObjectToStream(finalDir, gs);
                }

            return(copiedFiles);
        }
Exemplo n.º 4
0
        public void InsertVendorSamplesIntoBSP(ConstructedVendorSampleDirectory dir, string bspDirectory, PathMapper mapper = null)
        {
            List <VendorSample> finalSamples = new List <VendorSample>();

            string outputDir = Path.Combine(bspDirectory, "VendorSamples");

            if (Directory.Exists(outputDir))
            {
                Console.WriteLine($"Deleting {outputDir}...");
                Directory.Delete(outputDir, true);
            }

            if (mapper == null)
            {
                mapper = new PathMapper(dir);
            }
            Dictionary <string, string> copiedFiles = new Dictionary <string, string>();

            Console.WriteLine("Processing sample list...");

            foreach (var s in dir.Samples)
            {
                if (s.AllDependencies == null)
                {
                    continue;
                }
                var deps = s.AllDependencies.Concat(s.SourceFiles).Distinct().Select(d => new ParsedDependency {
                    OriginalFile = d, MappedFile = mapper.MapPath(d)
                }).Where(d => d.MappedFile != null).ToArray();

                mapper.MapPathList(ref s.HeaderFiles);
                mapper.MapPathList(ref s.IncludeDirectories);
                mapper.MapPathList(ref s.SourceFiles);

                s.Configuration = DetectKnownFrameworksAndFilterPaths(ref s.SourceFiles, ref s.HeaderFiles, ref s.IncludeDirectories, ref deps, s.Configuration.MCUConfiguration);
                FilterPreprocessorMacros(ref s.PreprocessorMacros);

                foreach (var dep in deps)
                {
                    copiedFiles[dep.OriginalFile] = dep.MappedFile.Replace(SampleRootDirMarker, outputDir);
                }

                s.AllDependencies = deps.Select(d => d.MappedFile).ToArray();

                s.Path        = mapper.MapPath(s.Path);
                s.VirtualPath = BuildVirtualSamplePath(s.Path);
                finalSamples.Add(s);
            }

            Console.WriteLine($"Copying {copiedFiles.Count} files...");
            foreach (var kv in copiedFiles)
            {
                Directory.CreateDirectory(Path.GetDirectoryName(kv.Value));
                if (!File.Exists(kv.Value))
                {
                    File.Copy(kv.Key, kv.Value);
                }
                File.SetAttributes(kv.Value, File.GetAttributes(kv.Value) & ~(FileAttributes.ReadOnly | FileAttributes.Hidden | FileAttributes.System));
            }

            Console.WriteLine("Updating BSP...");
            VendorSampleDirectory finalDir = new VendorSampleDirectory {
                Samples = finalSamples.ToArray()
            };

            Directory.CreateDirectory(outputDir);

            using (var fs = File.Create(Path.Combine(outputDir, "VendorSamples.xml.gz")))
                using (var gs = new GZipStream(fs, CompressionMode.Compress))
                {
                    XmlTools.SaveObjectToStream(finalDir, gs);
                }
        }
Exemplo n.º 5
0
        public static TestStatistics TestVendorSamples(VendorSampleDirectory samples, string bspDir, string temporaryDirectory, double testProbability = 1, bool esp32 = false)
        {
            string defaultToolchainID = "SysGCC-arm-eabi-6.2.0";

            flEsp32 = false;

            if (esp32)
            {
                defaultToolchainID = "SysGCC-xtensa-esp32-elf-5.2.0";
                flEsp32            = true;
            }

            var toolchainPath = (string)Registry.CurrentUser.OpenSubKey(@"Software\Sysprogs\GNUToolchains").GetValue(defaultToolchainID);

            if (toolchainPath == null)
            {
                throw new Exception("Cannot locate toolchain path from registry");
            }

            var toolchain = LoadedToolchain.Load(new ToolchainSource.Other(Environment.ExpandEnvironmentVariables(toolchainPath)));
            var bsp       = LoadedBSP.Load(new BSPEngine.BSPSummary(Environment.ExpandEnvironmentVariables(Path.GetFullPath(bspDir))), toolchain);

            if (flEsp32)
            {
                toolchainPath = toolchainPath.Replace('\\', '/'); //esp32
            }
            TestStatistics stats = new TestStatistics();
            int            cnt = 0, failed = 0, succeeded = 0;

            LoadedBSP.LoadedMCU[] MCUs = bsp.MCUs.ToArray();
            string outputDir           = Path.Combine(temporaryDirectory, "VendorSamples");

            if (!Directory.Exists(outputDir))
            {
                Directory.CreateDirectory(outputDir);
            }
            int    sampleCount = samples.Samples.Length;
            Random rng         = new Random();

            using (var r = new TestResults(Path.Combine(temporaryDirectory, "bsptest.log")))
            {
                r.BeginSample("Vendor Samples");
                foreach (var vs in samples.Samples)
                {
                    LoadedBSP.LoadedMCU mcu;
                    try
                    {
                        var rgFilterID = new Regex(vs.DeviceID.Replace('x', '.'), RegexOptions.IgnoreCase);
                        mcu         = bsp.MCUs.Where(f => rgFilterID.IsMatch(f.ExpandedMCU.ID)).ToArray()?.First();
                        vs.DeviceID = mcu.ExpandedMCU.ID;
                    }
                    catch (Exception ex)
                    {
                        r.ExceptionSample(ex.Message, "mcu " + vs.DeviceID + " not found in bsp");
                        Console.WriteLine("bsp have not mcu:" + vs.DeviceID);
                        continue;
                    }

                    if (testProbability < 1 && rng.NextDouble() > testProbability)
                    {
                        cnt++;
                        continue;
                    }

                    string mcuDir = Path.Combine(temporaryDirectory, "VendorSamples", vs.UserFriendlyName);
                    mcuDir += $"-{mcu.ExpandedMCU.ID}";
                    if (!Directory.Exists(mcuDir))
                    {
                        Directory.CreateDirectory(mcuDir);
                    }
                    DateTime start = DateTime.Now;

                    string[] hwSubstrings = new[]
                    {
                        @"\ARM_CM4F\port.c",
                        @"ARM_CM7\r0p1\port.c",
                        @"CM4_GCC.a",
                    };

                    if (vs.SourceFiles.FirstOrDefault(f => ContainsAnySubstrings(f, hwSubstrings)) != null)
                    {
                        if (vs.Configuration.MCUConfiguration != null)
                        {
                            var dict = PropertyDictionary2.ReadPropertyDictionary(vs.Configuration.MCUConfiguration);
                            dict["com.sysprogs.bspoptions.arm.floatmode"] = "-mfloat-abi=hard";
                            vs.Configuration.MCUConfiguration             = new PropertyDictionary2 {
                                Entries = dict.Select(kv => new PropertyDictionary2.KeyValue {
                                    Key = kv.Key, Value = kv.Value
                                }).ToArray()
                            };
                        }
                        else
                        {
                            vs.Configuration.MCUConfiguration = new PropertyDictionary2
                            {
                                Entries = new PropertyDictionary2.KeyValue[]
                                { new PropertyDictionary2.KeyValue {
                                      Key = "com.sysprogs.bspoptions.arm.floatmode", Value = "-mfloat-abi=hard"
                                  } }
                            };
                        }
                    }

                    vs.SourceFiles = vs.SourceFiles.Where(s => !IsNonGCCFile(vs, s)).ToArray();

                    var result = TestVendorSample(mcu, vs, mcuDir, samples);

                    Console.WriteLine($"[{(DateTime.Now - start).TotalMilliseconds:f0} msec]");

                    if (result == TestResult.Failed)
                    {
                        failed++;
                    }
                    else if (result == TestResult.Succeeded)
                    {
                        succeeded++;
                    }

                    r.LogTestResult(vs.UserFriendlyName, result);
                    cnt++;
                    Console.WriteLine("{0}: {1}% done ({2}/{3} projects, {4} failed)", vs.UserFriendlyName, (cnt * 100) / sampleCount, cnt, sampleCount, failed);
                }
                r.EndSample();
            }

            stats.Passed += succeeded;
            stats.Failed += failed;
            if (samples is ConstructedVendorSampleDirectory)
            {
                (samples as ConstructedVendorSampleDirectory).ToolchainDirectory = toolchainPath;
                (samples as ConstructedVendorSampleDirectory).BSPDirectory       = Path.GetFullPath(bspDir);
            }
            return(stats);
        }
Exemplo n.º 6
0
        private static TestResult TestVendorSample(LoadedBSP.LoadedMCU mcu, BSPEngine.VendorSample vs, string mcuDir, VendorSampleDirectory sampleDir)
        {
            var configuredMCU = new LoadedBSP.ConfiguredMCU(mcu, GetDefaultPropertyValues(mcu.ExpandedMCU.ConfigurableProperties));

            configuredMCU.Configuration["com.sysprogs.toolchainoptions.arm.libnosys"] = "--specs=nosys.specs";
            if (configuredMCU.ExpandedMCU.FLASHSize == 0)
            {
                configuredMCU.Configuration["com.sysprogs.bspoptions.primary_memory"] = "sram";
            }

            var entries = vs.Configuration.MCUConfiguration?.Entries;

            if (entries != null)
            {
                foreach (var e in entries)
                {
                    configuredMCU.Configuration[e.Key] = e.Value;
                }
            }


            var bspDict = configuredMCU.BuildSystemDictionary(SystemDirs);

            bspDict["PROJECTNAME"]     = "test";
            bspDict["SYS:VSAMPLE_DIR"] = sampleDir.Path;
            var prj = new GeneratedProject(configuredMCU, vs, mcuDir, bspDict, vs.Configuration.Frameworks ?? new string[0]);

            var projectCfg = PropertyDictionary2.ReadPropertyDictionary(vs.Configuration.MCUConfiguration);

            var frameworkCfg = PropertyDictionary2.ReadPropertyDictionary(vs.Configuration.Configuration);

            foreach (var k in projectCfg.Keys)
            {
                bspDict[k] = projectCfg[k];
            }
            var frameworkIDs = vs.Configuration.Frameworks?.ToDictionary(fw => fw, fw => true);

            prj.AddBSPFilesToProject(bspDict, frameworkCfg, frameworkIDs);
            var flags = prj.GetToolFlags(bspDict, frameworkCfg, frameworkIDs);

            //ToolFlags flags = new ToolFlags { CXXFLAGS = "  ", COMMONFLAGS = "-mcpu=cortex-m3  -mthumb", LDFLAGS = "-Wl,-gc-sections -Wl,-Map," + "test.map", CFLAGS = "-ffunction-sections -Os -MD" };

            flags.CFLAGS   += " -MD";
            flags.CXXFLAGS += " -MD";

            flags.IncludeDirectories = LoadedBSP.Combine(flags.IncludeDirectories, vs.IncludeDirectories).Distinct().ToArray();
            flags.PreprocessorMacros = LoadedBSP.Combine(flags.PreprocessorMacros, vs.PreprocessorMacros);

            flags = LoadedBSP.ConfiguredMCU.ExpandToolFlags(flags, bspDict, null);

            Dictionary <string, bool> sourceExtensions = new Dictionary <string, bool>(StringComparer.InvariantCultureIgnoreCase);

            sourceExtensions.Add("c", true);
            sourceExtensions.Add("cpp", true);
            sourceExtensions.Add("s", true);

            return(BuildAndRunValidationJob(mcu, mcuDir, false, null, prj, flags, sourceExtensions, null, null, vs));
        }
Exemplo n.º 7
0
        public static TestStatistics TestVendorSamples(VendorSampleDirectory samples, string bspDir, string temporaryDirectory, double testProbability = 1)
        {
            const string defaultToolchainID = "SysGCC-arm-eabi-5.3.0";
            var          toolchainPath      = (string)Registry.CurrentUser.OpenSubKey(@"Software\Sysprogs\GNUToolchains").GetValue(defaultToolchainID);

            if (toolchainPath == null)
            {
                throw new Exception("Cannot locate toolchain path from registry");
            }

            var toolchain = LoadedToolchain.Load(Environment.ExpandEnvironmentVariables(toolchainPath), new ToolchainRelocationManager());
            var bsp       = LoadedBSP.Load(new BSPManager.BSPSummary(Environment.ExpandEnvironmentVariables(Path.GetFullPath(bspDir))), toolchain);

            TestStatistics stats = new TestStatistics();
            int            cnt = 0, failed = 0, succeeded = 0;

            LoadedBSP.LoadedMCU[] MCUs = bsp.MCUs.ToArray();
            string outputDir           = Path.Combine(temporaryDirectory, "VendorSamples");

            if (!Directory.Exists(outputDir))
            {
                Directory.CreateDirectory(outputDir);
            }
            int    sampleCount = samples.Samples.Length;
            Random rng         = new Random();

            using (var r = new TestResults(Path.Combine(temporaryDirectory, "bsptest.log")))
            {
                foreach (var vs in samples.Samples)
                {
                    LoadedBSP.LoadedMCU mcu;

                    try
                    {
                        var rgFilterID = new Regex(vs.DeviceID.Replace('x', '.'), RegexOptions.IgnoreCase);
                        mcu         = bsp.MCUs.Where(f => rgFilterID.IsMatch(f.ExpandedMCU.ID)).ToArray()?.First();
                        vs.DeviceID = mcu.ExpandedMCU.ID;
                    }
                    catch (Exception ex)
                    {
                        r.ExceptionSample(ex.Message, "mcu " + vs.DeviceID + " not found in bsp");
                        Console.WriteLine("bsp have not mcu:" + vs.DeviceID);
                        continue;
                    }

                    if (testProbability < 1 && rng.NextDouble() > testProbability)
                    {
                        cnt++;
                        continue;
                    }

                    bool   aflSoftFPU = true;
                    string mcuDir     = Path.Combine(temporaryDirectory, "VendorSamples", vs.UserFriendlyName);
                    if (!Directory.Exists(mcuDir))
                    {
                        Directory.CreateDirectory(mcuDir);
                    }
                    if (vs.UserFriendlyName.ToUpper().Contains("RTOS"))
                    {
                        aflSoftFPU = false;
                    }
                    DateTime start  = DateTime.Now;
                    var      result = TestVendorSample(mcu, vs, mcuDir, aflSoftFPU, samples);

                    Console.WriteLine($"[{(DateTime.Now - start).TotalMilliseconds:f0} msec]");

                    if (result == TestResult.Failed)
                    {
                        failed++;
                    }
                    else if (result == TestResult.Succeeded)
                    {
                        succeeded++;
                    }

                    r.LogTestResult(vs.UserFriendlyName, result);
                    cnt++;
                    Console.WriteLine("{0}: {1}% done ({2}/{3} projects, {4} failed)", vs.UserFriendlyName, (cnt * 100) / sampleCount, cnt, sampleCount, failed);
                }
            }

            stats.Passed += succeeded;
            stats.Failed += failed;
            if (samples is ConstructedVendorSampleDirectory)
            {
                (samples as ConstructedVendorSampleDirectory).ToolchainDirectory = toolchainPath;
                (samples as ConstructedVendorSampleDirectory).BSPDirectory       = Path.GetFullPath(bspDir);
            }
            return(stats);
        }