예제 #1
0
        public async Task EnsureDotnetsdkDownloadScriptUpToDate()
        {
            string shDownloadUrl  = "https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.sh";
            string ps1DownloadUrl = "https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.ps1";

            using (HttpClient downloadClient = new HttpClient())
            {
                var response = await downloadClient.GetAsync("https://www.bing.com");

                if (!response.IsSuccessStatusCode)
                {
                    return;
                }

                string shScript = await downloadClient.GetStringAsync(shDownloadUrl);

                string ps1Script = await downloadClient.GetStringAsync(ps1DownloadUrl);

                string existingShScript  = File.ReadAllText(Path.Combine(TestUtil.GetSrcPath(), "Misc/dotnet-install.sh"));
                string existingPs1Script = File.ReadAllText(Path.Combine(TestUtil.GetSrcPath(), "Misc/dotnet-install.ps1"));

                bool shScriptMatched = string.Equals(shScript.TrimEnd('\n', '\r', '\0').Replace("\r\n", "\n").Replace("\r", "\n"), existingShScript.TrimEnd('\n', '\r', '\0').Replace("\r\n", "\n").Replace("\r", "\n"));
                Assert.True(shScriptMatched, "Fix the test by updating Src/Misc/dotnet-install.sh with content from https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.sh");

                bool ps1ScriptMatched = string.Equals(ps1Script.TrimEnd('\n', '\r', '\0').Replace("\r\n", "\n").Replace("\r", "\n"), existingPs1Script.TrimEnd('\n', '\r', '\0').Replace("\r\n", "\n").Replace("\r", "\n"));
                Assert.True(ps1ScriptMatched, "Fix the test by updating Src/Misc/dotnet-install.sh with content from https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.ps1");
            }
        }
예제 #2
0
        public void IsLocStringsPrettyPrint()
        {
            // Load the strings.
            string stringsFile = Path.Combine(TestUtil.GetSrcPath(), "Misc", "layoutbin", "en-US", "strings.json");

            Assert.True(File.Exists(stringsFile), $"File does not exist: {stringsFile}");
            var resourceDictionary = IOUtil.LoadObject <Dictionary <string, object> >(stringsFile);

            // sort the dictionary.
            Dictionary <string, object> sortedResourceDictionary = new Dictionary <string, object>();

            foreach (var res in resourceDictionary.OrderBy(r => r.Key))
            {
                sortedResourceDictionary[res.Key] = res.Value;
            }

            // print to file.
            string prettyStringsFile = Path.Combine(TestUtil.GetSrcPath(), "Misc", "layoutbin", "en-US", "strings.json.pretty");

            IOUtil.SaveObject(sortedResourceDictionary, prettyStringsFile);

            Assert.True(string.Equals(File.ReadAllText(stringsFile), File.ReadAllText(prettyStringsFile)), $"Orginal string.json file: {stringsFile} is not pretty printed, replace it with: {prettyStringsFile}");

            // delete file on succeed
            File.Delete(prettyStringsFile);
        }
예제 #3
0
        public async Task SuccessReadProcessEnv()
        {
            using (TestHostContext hc = new TestHostContext(this))
            {
                Tracing trace = hc.GetTrace();

                string envName  = Guid.NewGuid().ToString();
                string envValue = Guid.NewGuid().ToString();

                Process sleep = null;
                try
                {
                    string node = Path.Combine(
                        TestUtil.GetSrcPath(), "..", "_layout", "externals", "node", "bin", "node");

                    // TODO: this was formerly skipped on Windows - why?
                    hc.EnqueueInstance <IProcessInvoker>(new ProcessInvokerWrapper());

                    var startInfo = new ProcessStartInfo(node, "-e \"setTimeout(function(){{}}, 15 * 1000);\"");
                    startInfo.Environment[envName] = envValue;
                    sleep = Process.Start(startInfo);

                    var timeout = Process.GetProcessById(sleep.Id);
                    while (timeout == null)
                    {
                        await Task.Delay(500);

                        timeout = Process.GetProcessById(sleep.Id);
                    }

                    try
                    {
                        trace.Info($"Read env from {timeout.Id}");
                        var value = timeout.GetEnvironmentVariable(hc, envName);
                        if (string.Equals(value, envValue, StringComparison.OrdinalIgnoreCase))
                        {
                            trace.Info($"Find the env.");
                            return;
                        }
                        else
                        {
                            Assert.True(false, "Expected environment '" + envValue + "' did not match actual '" + value + "'");
                        }
                    }
                    catch (Exception ex)
                    {
                        trace.Error(ex);
                        Assert.True(false, "Fail to retrive process environment variable due to exception: " + ex.Message + "\n" + ex.StackTrace);
                    }

                    Assert.True(false, "Fail to retrive process environment variable.");
                }
                finally
                {
                    sleep?.Kill();
                }
            }
        }
예제 #4
0
        public async Task SuccessReadProcessEnv()
        {
            using (TestHostContext hc = new TestHostContext(this))
            {
                Tracing trace = hc.GetTrace();

                string envName  = Guid.NewGuid().ToString();
                string envValue = Guid.NewGuid().ToString();

                Process sleep = null;
                try
                {
#if OS_WINDOWS
                    string node = Path.Combine(TestUtil.GetSrcPath(), @"..\_layout\externals\node\bin\node");
#else
                    string node = Path.Combine(TestUtil.GetSrcPath(), @"../_layout/externals/node/bin/node");
                    hc.EnqueueInstance <IProcessInvoker>(new ProcessInvokerWrapper());
#endif
                    var startInfo = new ProcessStartInfo(node, "-e \"setTimeout(function(){{}}, 15 * 1000);\"");
                    startInfo.Environment[envName] = envValue;
                    sleep = Process.Start(startInfo);

                    var timeout = Process.GetProcessById(sleep.Id);
                    while (timeout == null)
                    {
                        await Task.Delay(500);

                        timeout = Process.GetProcessById(sleep.Id);
                    }

                    try
                    {
                        trace.Info($"Read env from {timeout.Id}");
                        var value = timeout.GetEnvironmentVariable(hc, envName);
                        if (string.Equals(value, envValue, StringComparison.OrdinalIgnoreCase))
                        {
                            trace.Info($"Find the env.");
                            return;
                        }
                    }
                    catch (Exception ex)
                    {
                        trace.Error(ex);
                    }

                    Assert.True(false, "Fail to retrive process environment variable.");
                }
                finally
                {
                    sleep?.Kill();
                }
            }
        }
예제 #5
0
        public TestHostContext(object testClass, [CallerMemberName] string testName = "")
        {
            ArgUtil.NotNull(testClass, nameof(testClass));
            ArgUtil.NotNullOrEmpty(testName, nameof(testName));
            _loadContext            = AssemblyLoadContext.GetLoadContext(typeof(TestHostContext).GetTypeInfo().Assembly);
            _loadContext.Unloading += LoadContext_Unloading;
            _testName = testName;

            // Trim the test assembly's root namespace from the test class's full name.
            _suiteName = testClass.GetType().FullName.Substring(
                startIndex: typeof(Tests.TestHostContext).FullName.LastIndexOf(nameof(TestHostContext)));
            _suiteName = _suiteName.Replace(".", "_");

            // Setup the trace manager.
            TraceFileName = Path.Combine(
                Path.Combine(TestUtil.GetSrcPath(), "Test", "TestLogs"),
                $"trace_{_suiteName}_{_testName}.log");
            if (File.Exists(TraceFileName))
            {
                File.Delete(TraceFileName);
            }

            var traceListener = new HostTraceListener(TraceFileName);

            traceListener.DisableConsoleReporting = true;
            _secretMasker = new SecretMasker();
            _secretMasker.AddValueEncoder(ValueEncoders.JsonStringEscape);
            _secretMasker.AddValueEncoder(ValueEncoders.UriDataEscape);
            _secretMasker.AddValueEncoder(ValueEncoders.BackslashEscape);
            _traceManager = new TraceManager(traceListener, _secretMasker);
            _trace        = GetTrace(nameof(TestHostContext));

            // inject a terminal in silent mode so all console output
            // goes to the test trace file
            _term        = new Terminal();
            _term.Silent = true;
            SetSingleton <ITerminal>(_term);
            EnqueueInstance <ITerminal>(_term);

            if (!TestUtil.IsWindows())
            {
                string eulaFile = Path.Combine(GetDirectory(WellKnownDirectory.Externals), Constants.Path.TeeDirectory, "license.html");
                Directory.CreateDirectory(GetDirectory(WellKnownDirectory.Externals));
                Directory.CreateDirectory(Path.Combine(GetDirectory(WellKnownDirectory.Externals), Constants.Path.TeeDirectory));
                File.WriteAllText(eulaFile, "testeulafile");
            }
        }
예제 #6
0
        public TestHostContext(object testClass, [CallerMemberName] string testName = "")
        {
            ArgUtil.NotNull(testClass, nameof(testClass));
            ArgUtil.NotNullOrEmpty(testName, nameof(testName));
            _loadContext            = AssemblyLoadContext.GetLoadContext(typeof(TestHostContext).GetTypeInfo().Assembly);
            _loadContext.Unloading += LoadContext_Unloading;
            _testName = testName;

            // Trim the test assembly's root namespace from the test class's full name.
            _suiteName = testClass.GetType().FullName.Substring(
                startIndex: typeof(Tests.TestHostContext).FullName.LastIndexOf(nameof(TestHostContext)));
            _suiteName = _suiteName.Replace(".", "_");

            // Setup the trace manager.
            TraceFileName = Path.Combine(
                Path.Combine(TestUtil.GetSrcPath(), "Test", "TestLogs"),
                $"trace_{_suiteName}_{_testName}.log");
            if (File.Exists(TraceFileName))
            {
                File.Delete(TraceFileName);
            }

            var traceListener = new HostTraceListener(TraceFileName);

            _secretMasker = new SecretMasker();
            _traceManager = new TraceManager(traceListener, _secretMasker);
            _trace        = GetTrace(nameof(TestHostContext));
            SetSingleton <ISecretMasker>(_secretMasker);

            // inject a terminal in silent mode so all console output
            // goes to the test trace file
            _term        = new Terminal();
            _term.Silent = true;
            SetSingleton <ITerminal>(_term);
            EnqueueInstance <ITerminal>(_term);
        }
예제 #7
0
        public void FindExtraLocStrings()
        {
            // Load the strings.
            string stringsFile = Path.Combine(TestUtil.GetSrcPath(), "Misc", "layoutbin", "en-US", "strings.json");

            Assert.True(File.Exists(stringsFile), $"File does not exist: {stringsFile}");
            var resourceDictionary = IOUtil.LoadObject <Dictionary <string, object> >(stringsFile);

            // Find all loc string key in source file.
            //
            // Note, narrow the search to each project folder only. Otherwise intermittent errors occur
            // when recursively searching due to parallel tests are deleting temp folders (DirectoryNotFoundException).
            var keys = new List <string>();

            string[] sourceFiles =
                Directory.GetFiles(TestUtil.GetProjectPath("Microsoft.VisualStudio.Services.Agent"), "*.cs", SearchOption.AllDirectories)
                .Concat(Directory.GetFiles(TestUtil.GetProjectPath("Agent.Listener"), "*.cs", SearchOption.AllDirectories))
                .Concat(Directory.GetFiles(TestUtil.GetProjectPath("Agent.Worker"), "*.cs", SearchOption.AllDirectories))
                .Concat(Directory.GetFiles(TestUtil.GetProjectPath("Agent.Plugins"), "*.cs", SearchOption.AllDirectories))
                .Concat(Directory.GetFiles(TestUtil.GetProjectPath("Agent.Sdk"), "*.cs", SearchOption.AllDirectories))
                .ToArray();
            foreach (string sourceFile in sourceFiles)
            {
                // Skip files in the obj directory.
                if (sourceFile.Contains(StringUtil.Format("{0}obj{0}", Path.DirectorySeparatorChar)))
                {
                    continue;
                }

                foreach (string line in File.ReadAllLines(sourceFile))
                {
                    // Search for calls to the StringUtil.Loc method within the line.
                    const string Pattern     = "StringUtil.Loc(";
                    int          searchIndex = 0;
                    int          patternIndex;
                    while (searchIndex < line.Length &&
                           (patternIndex = line.IndexOf(Pattern, searchIndex)) >= 0)
                    {
                        // Bump the search index in preparation for the for the next iteration within the same line.
                        searchIndex = patternIndex + Pattern.Length;

                        // Extract the resource key.
                        int keyStartIndex = patternIndex + Pattern.Length;
                        int keyEndIndex;
                        if (keyStartIndex + 2 < line.Length &&  // Key should start with a ", be followed by at least
                            line[keyStartIndex] == '"' &&       // one character, and end with a ".
                            (keyEndIndex = line.IndexOf('"', keyStartIndex + 1)) > 0)
                        {
                            // Remove the first and last double quotes.
                            keyStartIndex++;
                            keyEndIndex--;
                            string key = line.Substring(
                                startIndex: keyStartIndex,
                                length: keyEndIndex - keyStartIndex + 1);
                            if (ValidKeyRegex.IsMatch(key))
                            {
                                // A valid key was extracted.
                                keys.Add(key);
                                continue;
                            }
                        }
                    }
                }
            }

            // find extra loc strings.
            var extraKeys = resourceDictionary.Keys.Where(x => !keys.Contains(x))?.ToList();

            if (extraKeys != null)
            {
                Assert.True(extraKeys.Count == 0, $"Please save company's money by removing extra loc strings:{Environment.NewLine}{string.Join(Environment.NewLine, extraKeys)}");
            }
        }
예제 #8
0
        private void ValidateLocStrings(TestHostContext hc, string project)
        {
            using (hc)
            {
                Tracing trace    = hc.GetTrace();
                var     keys     = new List <string>();
                var     badLines = new List <BadLineInfo>();

                // Search for source files within the project.
                trace.Verbose("Searching source files:");
                string[] sourceFiles = Directory.GetFiles(
                    TestUtil.GetProjectPath(project),
                    "*.cs",
                    SearchOption.AllDirectories);
                foreach (string sourceFile in sourceFiles)
                {
                    // Skip files in the obj directory.
                    if (sourceFile.Contains(StringUtil.Format("{0}obj{0}", Path.DirectorySeparatorChar)))
                    {
                        continue;
                    }

                    trace.Verbose($"  {sourceFile}");
                    foreach (string line in File.ReadAllLines(sourceFile))
                    {
                        // Search for calls to the StringUtil.Loc method within the line.
                        const string Pattern     = "StringUtil.Loc(";
                        int          searchIndex = 0;
                        int          patternIndex;
                        while (searchIndex < line.Length &&
                               (patternIndex = line.IndexOf(Pattern, searchIndex)) >= 0)
                        {
                            // Bump the search index in preparation for the for the next iteration within the same line.
                            searchIndex = patternIndex + Pattern.Length;

                            // Extract the resource key.
                            int keyStartIndex = patternIndex + Pattern.Length;
                            int keyEndIndex;
                            if (keyStartIndex + 2 < line.Length &&  // Key should start with a ", be followed by at least
                                line[keyStartIndex] == '"' &&       // one character, and end with a ".
                                (keyEndIndex = line.IndexOf('"', keyStartIndex + 1)) > 0)
                            {
                                // Remove the first and last double quotes.
                                keyStartIndex++;
                                keyEndIndex--;
                                string key = line.Substring(
                                    startIndex: keyStartIndex,
                                    length: keyEndIndex - keyStartIndex + 1);
                                if (ValidKeyRegex.IsMatch(key))
                                {
                                    // A valid key was extracted.
                                    keys.Add(key);
                                    continue;
                                }
                            }

                            // Something went wrong. The pattern was found, but the resource key could not be determined.
                            badLines.Add(new BadLineInfo {
                                File = sourceFile, Line = line
                            });
                        }
                    }
                }

                // Load the strings.
                string stringsFile = Path.Combine(TestUtil.GetSrcPath(), "Misc", "layoutbin", "en-US", "strings.json");
                Assert.True(File.Exists(stringsFile), $"File does not exist: {stringsFile}");
                var resourceDictionary = IOUtil.LoadObject <Dictionary <string, object> >(stringsFile);

                // Find missing keys.
                string[] missingKeys =
                    keys
                    .Where(x => !resourceDictionary.ContainsKey(x))
                    .OrderBy(x => x)
                    .ToArray();
                if (missingKeys.Length > 0)
                {
                    trace.Error("One or more resource keys missing from resources file:");
                    foreach (string missingKey in missingKeys)
                    {
                        trace.Error($"  {missingKey}");
                    }
                }

                // Validate whether resource keys couldn't be interpreted.
                if (badLines.Count > 0)
                {
                    trace.Error("Bad lines detected. Unable to interpret resource key(s).");
                    IEnumerable <IGrouping <string, BadLineInfo> > badLineGroupings =
                        badLines
                        .GroupBy(x => x.File)
                        .OrderBy(x => x.Key)
                        .ToArray();
                    foreach (IGrouping <string, BadLineInfo> badLineGrouping in badLineGroupings)
                    {
                        trace.Error($"File: {badLineGrouping.First().File}");
                        foreach (BadLineInfo badLine in badLineGrouping)
                        {
                            trace.Error($"  Line: {badLine.Line}");
                        }
                    }
                }

                Assert.True(missingKeys.Length == 0, $"One or more resource keys missing from resources files. Consult the trace log: {hc.TraceFileName}");
                Assert.True(badLines.Count == 0, $"Unable to determine one or more resource keys. Consult the trace log: {hc.TraceFileName}");
            }
        }