Ejemplo n.º 1
0
        public void GenerateNuSpec()
        {
            var pkg = m_packageGenerator.AnalyzePackage(
                @"<?xml version='1.0' encoding='utf-8'?>
<package xmlns='http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd'>
  <metadata>
    <id>MyPkg</id>
    <version>1.999</version>
    <dependencies>
      <group targetFramework='.NETFramework4.5'>
        <dependency id='System.Collections' version='4.0.11' />
        <dependency id='System.Collections.Concurrent' version='4.0.12' />
      </group>
      <group targetFramework='.NETFramework4.5.1'>
        <dependency id='System.Collections' version='4.0.11' />
        <dependency id='System.Collections.Concurrent' version='4.0.12' />
      </group>
      <group targetFramework='.NETStandard2.0'>
        <dependency id='Newtonsoft.Json' version='10.0.0' exclude='Build,Analyzers' />
      </group>
    </dependencies>
  </metadata>
</package>",
                s_packagesOnConfig, new string[] { "lib/net45/my.dll", "lib/net451/my.dll", "lib/netstandard2.0/my.dll" });

            var spec = new NugetSpecGenerator(m_context.PathTable, pkg).CreateScriptSourceFile(pkg);
            var text = spec.ToDisplayStringV2();

            m_output.WriteLine(text);

            string expectedSpec = $@"import {{Transformer}} from ""Sdk.Transformers"";
import * as Managed from ""Sdk.Managed"";

export declare const qualifier: {{
    targetFramework: ""net45"" | ""net451"" | ""net452"" | ""net46"" | ""net461"" | ""net462"" | ""net472"" | ""netstandard2.0"" | ""netcoreapp2.0"" | ""netcoreapp2.1"" | ""netcoreapp2.2"" | ""netcoreapp3.0"" | ""netcoreapp3.1"" | ""netstandard2.1"",
    targetRuntime: ""win-x64"" | ""osx-x64"" | ""linux-x64"",
}};

const packageRoot = Contents.packageRoot;

namespace Contents {{
    export declare const qualifier: {{
    }};
    export const packageRoot = d`../../../pkgs/TestPkg.1.999`;
    @@public
    export const all: StaticDirectory = Transformer.sealDirectory(
        packageRoot,
        [
            f`${{packageRoot}}/lib/net45/my.dll`,
            f`${{packageRoot}}/lib/net451/my.dll`,
            f`${{packageRoot}}/lib/netstandard2.0/my.dll`,
            f`${{packageRoot}}/TestPkg.nuspec`,
        ]
    );
}}

@@public
export const pkg: Managed.ManagedNugetPackage = (() => {{
    switch (qualifier.targetFramework) {{
        case ""net45"":
            return Managed.Factory.createNugetPackage(
                ""TestPkg"",
                ""1.999"",
                Contents.all,
                [Managed.Factory.createBinaryFromFiles(f`${{packageRoot}}/lib/net45/my.dll`)],
                [Managed.Factory.createBinaryFromFiles(f`${{packageRoot}}/lib/net45/my.dll`)],
                [importFrom(""System.Collections"").pkg, importFrom(""System.Collections.Concurrent"").pkg]
            );
        case ""net451"":
        case ""net452"":
        case ""net46"":
        case ""net461"":
        case ""net462"":
        case ""net472"":
            return Managed.Factory.createNugetPackage(
                ""TestPkg"",
                ""1.999"",
                Contents.all,
                [Managed.Factory.createBinaryFromFiles(f`${{packageRoot}}/lib/net451/my.dll`)],
                [Managed.Factory.createBinaryFromFiles(f`${{packageRoot}}/lib/net451/my.dll`)],
                [importFrom(""System.Collections"").pkg, importFrom(""System.Collections.Concurrent"").pkg]
            );
        case ""netstandard2.0"":
        case ""netcoreapp2.0"":
        case ""netcoreapp2.1"":
        case ""netcoreapp2.2"":
        case ""netcoreapp3.0"":
        case ""netcoreapp3.1"":
        case ""netstandard2.1"":
            return Managed.Factory.createNugetPackage(
                ""TestPkg"",
                ""1.999"",
                Contents.all,
                [Managed.Factory.createBinaryFromFiles(f`${{packageRoot}}/lib/netstandard2.0/my.dll`)],
                [
                    Managed.Factory.createBinaryFromFiles(f`${{packageRoot}}/lib/netstandard2.0/my.dll`),
                ],
                [...addIfLazy(qualifier.targetFramework === ""netstandard2.0"", () => [importFrom(""Newtonsoft.Json"").pkg])]
            );
        default:
            Contract.fail(""Unsupported target framework"");
    }};
}}
)();";

            XAssert.AreEqual(expectedSpec, text);
            var hashingHelper = new global::BuildXL.Storage.Fingerprints.HashingHelper(m_context.PathTable, recordFingerprintString: false);

            hashingHelper.Add(expectedSpec);
            var hash = BitConverter.ToString(hashingHelper.GenerateHashBytes()).Replace("-", string.Empty);

            const string CurrentSpecHash       = "54628A3B7DB3041473955EE2FC145009CFD298A2";
            const int    CurrentSpecGenVersion = 6;

            if (CurrentSpecHash != hash)
            {
                var hasFormatVersionIncreased = NugetSpecGenerator.SpecGenerationFormatVersion > CurrentSpecGenVersion;
                if (!hasFormatVersionIncreased)
                {
                    XAssert.Fail(
                        $@"
**********************************************************************************
** It looks like NuGet spec generation has changed but the version of 
** '{nameof(NugetSpecGenerator.SpecGenerationFormatVersion)}.{nameof(NugetSpecGenerator)}' didn't increase.
**
** Please bump up the spec generation format version from {CurrentSpecGenVersion} to {CurrentSpecGenVersion+1} and then
** update the '{nameof(CurrentSpecHash)}' and '{nameof(CurrentSpecGenVersion)}' values in this
** test to '{hash}' and '{CurrentSpecGenVersion+1}' respectively.
**********************************************************************************");
                }
                else
                {
                    var lines = new[]
                    {
                        $"Congratulations on remembering to increment '{nameof(NugetSpecGenerator.SpecGenerationFormatVersion)}.{nameof(NugetSpecGenerator)}'",
                        $"after updating NuGet spec generator!",
                        $"",
                        $"To keep this reminder working, please update the '{nameof(CurrentSpecHash)}' and '{nameof(CurrentSpecGenVersion)}'",
                        $"values in this unit test to '{hash}' and '{NugetSpecGenerator.SpecGenerationFormatVersion}' respectively.",
                    };
                    const int width   = 94;
                    var       fst     = " " + String.Concat(Enumerable.Repeat("_", width + 2)) + " ";
                    var       snd     = $"/ {' ',-width} \\";
                    var       aligned = lines.Select(l => $"| {l,-width} |");
                    var       last    = "\\" + String.Concat(Enumerable.Repeat("_", width + 2)) + "/";
                    XAssert.Fail(string.Join(Environment.NewLine, new[] { fst, snd }.Concat(aligned).Concat(new[] { last })));
                }
            }
        }
Ejemplo n.º 2
0
        public async Task Stress()
        {
            const int N              = 5;
            const int M              = N * N;
            var       context        = BuildXLContext.CreateInstanceForTesting();
            var       loggingContext = CreateLoggingContextForTest();
            var       pathTable      = context.PathTable;

            using (var tempFiles = new TempFileStorage(canGetFileNames: true))
            {
                var config = ConfigHelpers.CreateDefault(pathTable, tempFiles.GetUniqueFileName(), tempFiles);

                using (var pipTable = new PipTable(
                           context.PathTable,
                           context.SymbolTable,
                           initialBufferSize: 1024,
                           maxDegreeOfParallelism: (Environment.ProcessorCount + 2) / 3,
                           debug: false))
                {
                    var executionEnvironment = new PipQueueTestExecutionEnvironment(
                        context,
                        config,
                        pipTable,
                        Path.Combine(TestOutputDirectory, "temp"),
                        TryGetSubstSourceAndTarget(out string substSource, out string substTarget) ? (substSource, substTarget) : default((string, string)?),
                        GetSandboxConnection());

                    Func <RunnablePip, Task <PipResult> > taskFactory = async(runnablePip) =>
                    {
                        PipResult result;
                        var       operationTracker = new OperationTracker(runnablePip.LoggingContext);
                        var       pip = runnablePip.Pip;
                        using (var operationContext = operationTracker.StartOperation(PipExecutorCounter.PipRunningStateDuration, pip.PipId, pip.PipType, runnablePip.LoggingContext))
                        {
                            result = await TestPipExecutor.ExecuteAsync(operationContext, executionEnvironment, pip);
                        }

                        executionEnvironment.MarkExecuted(pip);
                        return(result);
                    };

                    string       executable         = CmdHelper.OsShellExe;
                    FileArtifact executableArtifact = FileArtifact.CreateSourceFile(AbsolutePath.Create(pathTable, executable));

                    // This is the only file artifact we reference without a producer. Rather than scheduling a hashing pip, let's just invent one (so fingerprinting can succeed).
                    executionEnvironment.AddWellKnownFile(executableArtifact, WellKnownContentHashes.UntrackedFile);

                    using (var phase1PipQueue = new PipQueue(executionEnvironment.Configuration.Schedule))
                    {
                        // phase 1: create some files
                        var baseFileArtifacts = new List <FileArtifact>();
                        for (int i = 0; i < N; i++)
                        {
                            string       destination             = tempFiles.GetUniqueFileName();
                            AbsolutePath destinationAbsolutePath = AbsolutePath.Create(pathTable, destination);
                            FileArtifact destinationArtifact     = FileArtifact.CreateSourceFile(destinationAbsolutePath).CreateNextWrittenVersion();
                            baseFileArtifacts.Add(destinationArtifact);

                            PipData contents = PipDataBuilder.CreatePipData(
                                context.StringTable,
                                " ",
                                PipDataFragmentEscaping.CRuntimeArgumentRules,
                                i.ToString(CultureInfo.InvariantCulture));

                            var writeFile = new WriteFile(destinationArtifact, contents, WriteFileEncoding.Utf8, ReadOnlyArray <StringId> .Empty, PipProvenance.CreateDummy(context));
                            var pipId     = pipTable.Add((uint)(i + 1), writeFile);

                            var contentHash = ContentHashingUtilities.HashString(contents.ToString(pathTable));
                            executionEnvironment.AddExpectedWrite(writeFile, destinationArtifact, contentHash);

                            var runnable = RunnablePip.Create(loggingContext, executionEnvironment, pipId, pipTable.GetPipType(pipId), 0, taskFactory, 0);
                            runnable.Start(new OperationTracker(loggingContext), loggingContext);
                            runnable.SetDispatcherKind(DispatcherKind.IO);
                            phase1PipQueue.Enqueue(runnable);
                        }

                        phase1PipQueue.SetAsFinalized();
                        phase1PipQueue.DrainQueues();
                        await Task.WhenAll(
                            Enumerable.Range(0, 2).Select(
                                async range =>
                        {
                            using (var phase2PipQueue = new PipQueue(executionEnvironment.Configuration.Schedule))
                            {
                                // phase 2: do some more with those files
                                var pips         = new ConcurrentDictionary <PipId, Tuple <string, int> >();
                                var checkerTasks = new ConcurrentQueue <Task>();
                                Action <PipId, Task <PipResult> > callback =
                                    (id, task) =>
                                {
                                    XAssert.IsTrue(task.Status == TaskStatus.RanToCompletion);
                                    XAssert.IsFalse(task.Result.Status.IndicatesFailure());
                                    Tuple <string, int> t;
                                    if (!pips.TryRemove(id, out t))
                                    {
                                        XAssert.Fail();
                                    }

                                    checkerTasks.Enqueue(
                                        Task.Run(
                                            () =>
                                    {
                                        string actual = File.ReadAllText(t.Item1).Trim();

                                        // TODO: Make this async
                                        XAssert.AreEqual(actual, t.Item2.ToString());
                                    }));
                                };
                                var r = new Random(0);
                                for (int i = 0; i < M; i++)
                                {
                                    int sourceIndex             = r.Next(baseFileArtifacts.Count);
                                    FileArtifact sourceArtifact = baseFileArtifacts[sourceIndex];

                                    string destination = tempFiles.GetUniqueFileName();
                                    AbsolutePath destinationAbsolutePath = AbsolutePath.Create(pathTable, destination);
                                    FileArtifact destinationArtifact     = FileArtifact.CreateSourceFile(destinationAbsolutePath).CreateNextWrittenVersion();
                                    Pip pip;

                                    DispatcherKind queueKind;
                                    switch (r.Next(2))
                                    {
                                    case 0:
                                        pip       = new CopyFile(sourceArtifact, destinationArtifact, ReadOnlyArray <StringId> .Empty, PipProvenance.CreateDummy(context));
                                        queueKind = DispatcherKind.IO;
                                        executionEnvironment.AddExpectedWrite(pip, destinationArtifact, executionEnvironment.GetExpectedContent(sourceArtifact));
                                        break;

                                    case 1:
                                        string workingDirectory =
                                            OperatingSystemHelper.IsUnixOS ? "/tmp" :
                                            Environment.GetFolderPath(Environment.SpecialFolder.Windows);

                                        AbsolutePath workingDirectoryAbsolutePath = AbsolutePath.Create(pathTable, workingDirectory);

                                        var pipData = OperatingSystemHelper.IsUnixOS ?
                                                      PipDataBuilder.CreatePipData(pathTable.StringTable, " ", PipDataFragmentEscaping.CRuntimeArgumentRules, "-c", "'", "cp", sourceArtifact, destinationArtifact, "'") :
                                                      PipDataBuilder.CreatePipData(pathTable.StringTable, " ", PipDataFragmentEscaping.CRuntimeArgumentRules, "/d", "/c", "copy", "/B", sourceArtifact, destinationArtifact);

                                        queueKind = DispatcherKind.CPU;
                                        pip       = new Process(
                                            executableArtifact,
                                            workingDirectoryAbsolutePath,
                                            pipData,
                                            FileArtifact.Invalid,
                                            PipData.Invalid,
                                            ReadOnlyArray <EnvironmentVariable> .Empty,
                                            FileArtifact.Invalid,
                                            FileArtifact.Invalid,
                                            FileArtifact.Invalid,
                                            tempFiles.GetUniqueDirectory(pathTable),
                                            null,
                                            null,
                                            ReadOnlyArray <FileArtifact> .FromWithoutCopy(executableArtifact, sourceArtifact),
                                            ReadOnlyArray <FileArtifactWithAttributes> .FromWithoutCopy(destinationArtifact.WithAttributes()),
                                            ReadOnlyArray <DirectoryArtifact> .Empty,
                                            ReadOnlyArray <DirectoryArtifact> .Empty,
                                            ReadOnlyArray <PipId> .Empty,
                                            ReadOnlyArray <AbsolutePath> .From(CmdHelper.GetCmdDependencies(pathTable)),
                                            ReadOnlyArray <AbsolutePath> .From(CmdHelper.GetCmdDependencyScopes(pathTable)),
                                            ReadOnlyArray <StringId> .Empty,
                                            ReadOnlyArray <int> .Empty,
                                            ReadOnlyArray <ProcessSemaphoreInfo> .Empty,
                                            provenance: PipProvenance.CreateDummy(context),
                                            toolDescription: StringId.Invalid,
                                            additionalTempDirectories: ReadOnlyArray <AbsolutePath> .Empty);
                                        executionEnvironment.AddExpectedWrite(pip, destinationArtifact, executionEnvironment.GetExpectedContent(sourceArtifact));
                                        break;

                                    default:
                                        Contract.Assert(false);
                                        continue;
                                    }

                                    var pipId = pipTable.Add((uint)((range *M) + N + i + 1), pip);

                                    Func <RunnablePip, Task> taskFactoryWithCallback = async(runnablePip) =>
                                    {
                                        var task      = taskFactory(runnablePip);
                                        var pipResult = await task;
                                        callback(pipId, task);
                                    };

                                    var runnable = RunnablePip.Create(loggingContext, executionEnvironment, pipId, pipTable.GetPipType(pipId), 0, taskFactoryWithCallback, 0);
                                    runnable.Start(new OperationTracker(loggingContext), loggingContext);
                                    runnable.SetDispatcherKind(queueKind);
                                    phase2PipQueue.Enqueue(runnable);

                                    if (!pips.TryAdd(pipId, Tuple.Create(destination, sourceIndex)))
                                    {
                                        Contract.Assert(false);
                                    }
                                }

                                phase2PipQueue.SetAsFinalized();
                                phase2PipQueue.DrainQueues();
                                XAssert.AreEqual(0, pips.Count);
                                await Task.WhenAll(checkerTasks);
                            }
                        }));
                    }
                }
            }
        }
Ejemplo n.º 3
0
        private async Task VerifyReporting(AccessType access, Action <FileAccessManifest> populateManifest, params ExpectedReportEntry[] expectedExplicitReports)
        {
            // We need a process which will generate the expected accesses.
            var testProcess = CreateTestProcess(access, expectedExplicitReports);
            var pathTable   = Context.PathTable;

            var info = ToProcessInfo(testProcess, "FileAccessExplicitReportingTest");

            info.FileAccessManifest.ReportFileAccesses           = false;
            info.FileAccessManifest.ReportUnexpectedFileAccesses = true;
            info.FileAccessManifest.FailUnexpectedFileAccesses   = false;

            populateManifest(info.FileAccessManifest);

            using (ISandboxedProcess process = await StartProcessAsync(info))
            {
                SandboxedProcessResult result = await process.GetResultAsync();

                XAssert.AreEqual(0, result.ExitCode,
                                 "\r\ncmd: {0} \r\nStandard out: '{1}' \r\nStandard err: '{2}'.",
                                 info.Arguments,
                                 await result.StandardOutput.ReadValueAsync(),
                                 await result.StandardError.ReadValueAsync());
                XAssert.IsNotNull(result.ExplicitlyReportedFileAccesses);

                Dictionary <AbsolutePath, ExpectedReportEntry> pathsToExpectations = expectedExplicitReports.ToDictionary(
                    e => e.File.Path,
                    e => e);

                var verifiedPaths = new HashSet <AbsolutePath>();
                foreach (var actualReport in result.ExplicitlyReportedFileAccesses)
                {
                    string actualReportedPathString = actualReport.GetPath(pathTable);
                    XAssert.AreEqual(
                        FileAccessStatus.Allowed,
                        actualReport.Status,
                        "Incorrect status for path " + actualReportedPathString);

                    if (!TryVerifySingleReport(pathTable, actualReport, access, pathsToExpectations, out var actualReportPath))
                    {
                        if ((actualReport.RequestedAccess & RequestedAccess.Enumerate) != 0)
                        {
                            // To account for 'explicitly reported' enumerations globally, we need to be lenient about unexpected enumerations.
                            // Alternatively instead opt-in to enumeration reports under certain scopes.
                        }
                        else
                        {
                            AbsolutePath actualReportedPath = AbsolutePath.Create(pathTable, actualReportedPathString);
                            XAssert.Fail("No expectations for an explicitly reported path {0}", actualReportedPath.ToString(pathTable));
                        }
                    }
                    else
                    {
                        verifiedPaths.Add(actualReportPath);
                    }
                }

                foreach (var actualReport in result.AllUnexpectedFileAccesses)
                {
                    XAssert.AreEqual(FileAccessStatus.Denied, actualReport.Status);
                    if (TryVerifySingleReport(pathTable, actualReport, access, pathsToExpectations, out var actualReportPath))
                    {
                        verifiedPaths.Add(actualReportPath);
                    }

                    // Note that we allow extra unexpected file accesses for the purposes of these tests.
                }

                var expectedPathsSet = new HashSet <AbsolutePath>(pathsToExpectations.Keys);
                var disagreeingPaths = new HashSet <AbsolutePath>(verifiedPaths);
                disagreeingPaths.SymmetricExceptWith(expectedPathsSet);
                if (disagreeingPaths.Any())
                {
                    var disagreeingReports = "Disagreeing reports:" + string.Join(string.Empty, disagreeingPaths
                                                                                  .Select(p => (tag: expectedPathsSet.Contains(p) ? "Missing" : "Unexpected", path: p))
                                                                                  .Select(t => $"{Environment.NewLine}  {t.tag} report for path {t.path.ToString(pathTable)}"));
                    var expectedReports = "Expected reports:" + string.Join(string.Empty, pathsToExpectations.Keys
                                                                            .Select(p => $"{Environment.NewLine}  {p.ToString(pathTable)}"));
                    var verifiedReports = "Verified reports:" + string.Join(string.Empty, verifiedPaths
                                                                            .Select(p => $"{Environment.NewLine}  {p.ToString(pathTable)}"));
                    XAssert.Fail(string.Join(Environment.NewLine, disagreeingReports, expectedReports, verifiedReports));
                }
            }
        }
Ejemplo n.º 4
0
        private static object CreateInstance(BuildXLContext context, Type type, bool booleanDefault)
        {
            string path = A("x", "path");

            type = GetNonNullableType(type);

            if (type == typeof(bool))
            {
                return(booleanDefault);
            }

            if (type == typeof(double))
            {
                return((double)0.23423);
            }

            if (type == typeof(byte))
            {
                return((byte)123);
            }

            if (type == typeof(sbyte))
            {
                return((sbyte)123);
            }

            if (type == typeof(short))
            {
                return((short)123);
            }

            if (type == typeof(ushort))
            {
                return((ushort)123);
            }

            if (type == typeof(int))
            {
                return(123);
            }

            if (type == typeof(uint))
            {
                return((uint)123);
            }

            if (type == typeof(long))
            {
                return((long)123);
            }

            if (type == typeof(ulong))
            {
                return((ulong)123);
            }

            if (type == typeof(string))
            {
                return("nonDefaultString");
            }

            if (type == typeof(ModuleId))
            {
                return(new ModuleId(123));
            }

            if (type == typeof(LocationData))
            {
                return(new LocationData(AbsolutePath.Create(context.PathTable, path), 12, 23));
            }

            if (type == typeof(AbsolutePath))
            {
                return(AbsolutePath.Create(context.PathTable, path));
            }

            if (type == typeof(RelativePath))
            {
                string relativePath = R("rel1", "dir1", "path");
                return(RelativePath.Create(context.StringTable, relativePath));
            }

            if (type == typeof(FileArtifact))
            {
                return(FileArtifact.CreateSourceFile(AbsolutePath.Create(context.PathTable, path)));
            }

            if (type == typeof(PathAtom))
            {
                return(PathAtom.Create(context.StringTable, "atom"));
            }

            if (type == typeof(global::BuildXL.Utilities.LineInfo))
            {
                return(new global::BuildXL.Utilities.LineInfo(1, 1));
            }

            if (type.GetTypeInfo().IsEnum)
            {
                bool first = true;
                foreach (var value in Enum.GetValues(type))
                {
                    if (!first)
                    {
                        return(value);
                    }

                    first = false;
                }

                XAssert.Fail($"Enum {type.FullName} doesn't have more than one value, so can't pick the second one.");
            }

            if (type.GetTypeInfo().IsGenericType)
            {
                var generic = type.GetGenericTypeDefinition();

                if (generic == typeof(IReadOnlyList <>))
                {
                    // Treat IReadOnlyList as if it was List
                    type    = typeof(List <>).MakeGenericType(type.GenericTypeArguments[0]);
                    generic = type.GetGenericTypeDefinition();
                }

                if (generic == typeof(List <>))
                {
                    var newList = (IList)Activator.CreateInstance(type);
                    newList.Add(CreateInstance(context, type.GenericTypeArguments[0], booleanDefault));
                    return(newList);
                }

                if (generic == typeof(IReadOnlyDictionary <,>))
                {
                    // Treat IReadOnlyList as if it was List
                    type    = typeof(Dictionary <,>).MakeGenericType(type.GenericTypeArguments[0], type.GenericTypeArguments[1]);
                    generic = type.GetGenericTypeDefinition();
                }

                if (generic == typeof(Dictionary <,>))
                {
                    var newDictionary = (IDictionary)Activator.CreateInstance(type);
                    newDictionary.Add(
                        CreateInstance(context, type.GenericTypeArguments[0], booleanDefault),
                        CreateInstance(context, type.GenericTypeArguments[1], booleanDefault));
                    return(newDictionary);
                }

                if (generic == typeof(ValueTuple <,>))
                {
                    var newTuple = Activator.CreateInstance(type);

                    // In ValueTuple classes, the first 7 values are accessible via Item1-Item7 fields.
                    // The tuple field names (named tuples) aren't part of runtime representation.
                    type.GetField("Item1").SetValue(newTuple, CreateInstance(context, type.GenericTypeArguments[0], booleanDefault));
                    type.GetField("Item2").SetValue(newTuple, CreateInstance(context, type.GenericTypeArguments[1], booleanDefault));

                    return(newTuple);
                }
            }

            if (type.GetTypeInfo().IsInterface)
            {
                // Treat interfaces as if it was the mutable class
                type = ConfigurationConverter.FindImplementationType(
                    type,
                    ObjectLiteral.Create(new List <Binding>(), default(LineInfo), AbsolutePath.Invalid),

                    // Return a SourceResolver to instantiate
                    () => "SourceResolver");
            }

            if (type.GetTypeInfo().IsClass)
            {
                var instance = Activator.CreateInstance(type);
                PopulateObject(context, type, instance, booleanDefault);
                return(instance);
            }

            XAssert.Fail($"Don't know how to create objects for this type: {type.FullName}.");
            return(null);
        }
Ejemplo n.º 5
0
 public static void StaticAwaitCond(Func <bool> evaluator, TimeSpan max, TimeSpan?interval)
 {
     InternalAwaitCondition(evaluator, max, interval, (format, args) => XAssert.Fail(string.Format(format, args)));
 }
Ejemplo n.º 6
0
 public SortedReadOnlyArray <FileArtifact, OrdinalFileArtifactComparer> ListSealedDirectoryContents(DirectoryArtifact directoryArtifact)
 {
     XAssert.Fail("Shouldn't be called since no sealed directories are introduced");
     return(default(SortedReadOnlyArray <FileArtifact, OrdinalFileArtifactComparer>));
 }
Ejemplo n.º 7
0
        public static void ValidateEqual(BuildXLContext context, Type type, object expected, object actual, string objPath, Remapper remapper)
        {
            type = GetNonNullableType(type);

            if (type == typeof(bool))
            {
                XAssert.AreEqual((bool)expected, (bool)actual, $"{nameof(Boolean)} values don't match for objPath: {objPath}");
                return;
            }

            if (type == typeof(int) || type == typeof(short) || type == typeof(sbyte) || type == typeof(long))
            {
                XAssert.AreEqual(
                    Convert.ToInt64(expected),
                    Convert.ToInt64(actual),
                    $"Numeric values don't match for objPath: {objPath}");
                return;
            }

            if (type == typeof(uint) || type == typeof(ushort) || type == typeof(byte) || type == typeof(ulong))
            {
                XAssert.AreEqual(
                    Convert.ToUInt64(expected),
                    Convert.ToUInt64(actual),
                    $"Numeric values don't match for objPath: {objPath}");
                return;
            }

            if (type == typeof(double))
            {
                XAssert.AreEqual(
                    Convert.ToDouble(expected),
                    Convert.ToDouble(actual),
                    $"Numeric values don't match for objPath: {objPath}");
                return;
            }

            if (type == typeof(string))
            {
                XAssert.AreEqual((string)expected, (string)actual, $"{nameof(String)} values don't match for objPath: {objPath}");
                return;
            }

            if (type == typeof(ModuleId))
            {
                XAssert.AreEqual(
                    (ModuleId)expected,
                    (ModuleId)actual,
                    $"{nameof(ModuleId)} id values don't match for objPath: {objPath}");
                return;
            }

            if (type == typeof(LocationData))
            {
                AssertEqualLocationData(context, objPath, remapper, (LocationData)expected, (LocationData)actual);
                return;
            }

            if (type == typeof(RelativePath))
            {
                AssertEqualRelativePaths(context, objPath, remapper, (RelativePath)expected, (RelativePath)actual);
                return;
            }

            if (type == typeof(AbsolutePath))
            {
                AssertEqualAbsolutePaths(context, objPath, remapper, (AbsolutePath)expected, (AbsolutePath)actual);
                return;
            }

            if (type == typeof(FileArtifact))
            {
                AssertEqualFileArtifacts(context, objPath, remapper, (FileArtifact)expected, (FileArtifact)actual);
                return;
            }

            if (type == typeof(PathAtom))
            {
                AssertEqualPathAtoms(context, objPath, remapper, (PathAtom)expected, (PathAtom)actual);
                return;
            }

            if (type == typeof(SymbolAtom))
            {
                XAssert.AreEqual((SymbolAtom)expected, (SymbolAtom)actual, $"{nameof(SymbolAtom)} values don't match for objPath: {objPath}");
                return;
            }

            if (type == typeof(global::BuildXL.Utilities.LineInfo))
            {
                XAssert.AreEqual(
                    (global::BuildXL.Utilities.LineInfo)expected,
                    (global::BuildXL.Utilities.LineInfo)actual,
                    $"{nameof(global::BuildXL.Utilities.LineInfo)} values don't match for objPath: {objPath}");
                return;
            }

            if (type == typeof(LineInfo))
            {
                XAssert.AreEqual(
                    (LineInfo)expected,
                    (LineInfo)actual,
                    $"{nameof(LineInfo)} values don't match for objPath: {objPath}");
                return;
            }

            if (type.GetTypeInfo().IsEnum)
            {
                XAssert.AreEqual((Enum)expected, (Enum)actual, $"Enum values don't match for objPath: {objPath}");
                return;
            }

            if (type.GetTypeInfo().IsGenericType)
            {
                var generic = type.GetGenericTypeDefinition();
                if (generic == typeof(List <>) || generic == typeof(IReadOnlyList <>))
                {
                    XAssert.IsTrue((expected == null) == (actual == null));

                    var expectedList = expected as IList;
                    var actualList   = actual as IList;

                    XAssert.IsTrue(
                        (expectedList == null) == (actualList == null),
                        "One of the lists is null, the other isn't for objPath: {0}",
                        objPath);
                    if (expectedList != null)
                    {
                        XAssert.AreEqual(expectedList.Count, actualList.Count, $"Counts of lists don't match for objPath: {objPath}");
                        for (int i = 0; i < expectedList.Count; i++)
                        {
                            ValidateEqual(
                                context,
                                type.GenericTypeArguments[0],
                                expectedList[i],
                                actualList[i],
                                objPath + "[" + i.ToString(CultureInfo.InvariantCulture) + "]",
                                remapper);
                        }
                    }

                    return;
                }

                if (generic == typeof(Dictionary <,>) || generic == typeof(IReadOnlyDictionary <,>) || generic == typeof(ConcurrentDictionary <,>))
                {
                    XAssert.IsTrue((expected == null) == (actual == null));

                    var expectedDictionary = expected as IDictionary;
                    var actualDictionary   = actual as IDictionary;

                    XAssert.IsTrue(
                        (expectedDictionary == null) == (actualDictionary == null),
                        $"One of the dictionaries is null, the other isn't for objPath: {objPath}");
                    if (expectedDictionary != null)
                    {
                        XAssert.AreEqual(
                            expectedDictionary.Count,
                            expectedDictionary.Count,
                            $"Counts of dictionaries don't match for objPath: {objPath}");
                        foreach (var kv in expectedDictionary)
                        {
                            var key         = kv.GetType().GetProperty("Key").GetValue(kv);
                            var value       = kv.GetType().GetTypeInfo().GetProperty("Value").GetValue(kv);
                            var actualValue = actualDictionary[key];

                            ValidateEqual(context, type.GenericTypeArguments[1], value, actualValue, objPath + "[" + key + "]", remapper);
                        }
                    }

                    return;
                }
            }

            if (type.GetTypeInfo().IsInterface)
            {
                var actualType = ConfigurationConverter.FindImplementationType(
                    type,
                    ObjectLiteral.Create(new List <Binding>(), default(LineInfo), AbsolutePath.Invalid),

                    // Note we only create a sourceresolver, so no need to fiddle, just compare with SourceResolver.
                    () => "SourceResolver");
                ValidateEqualMembers(context, actualType, expected, actual, objPath, remapper);
                return;
            }

            if (type.GetTypeInfo().IsClass)
            {
                ValidateEqualMembers(context, type, expected, actual, objPath, remapper);
                return;
            }

            XAssert.Fail($"Don't know how to compare objects of this type '{type}' for objPath: {objPath}");
        }
Ejemplo n.º 8
0
        public void GetOrSetStress()
        {
            // Generate a bunch of operations that work on a set of fields that trigger resizes, updates and reads.
            var list                = new ConcurrentArrayList <TestValue>(1, true);
            var rnd                 = new Random();
            int maxIndex            = 2000;
            int maxOperationsFactor = 1000;

            int val0 = 0xfff0000;
            int val1 = 0x000ff000;
            int val2 = 0x00000fff;

            var operations = Enumerable
                             .Range(0, maxIndex * maxOperationsFactor)
                             .Select(
                index =>
            {
                int value;
                int valueToSet = rnd.Next(3);
                switch (valueToSet)
                {
                case 0:
                    value = val0;
                    break;

                case 1:
                    value = val1;
                    break;

                case 2:
                    value = val2;
                    break;

                default:
                    value = 0;
                    XAssert.Fail("sdfsd");
                    break;
                }

                return(new
                {
                    Index = index / maxOperationsFactor,
                    Value = value
                });
            })
                             .ToArray()
                             .OrderBy(x => rnd.Next(maxIndex));

            Parallel.ForEach(
                operations,
                operation =>
            {
                // Make sure it is one of the legal value.
                TestValue res = list.GetOrSet(operation.Index, () => new TestValue(operation.Value));
                XAssert.IsTrue(res.Value == val0 || res.Value == val1 || res.Value == val2);

                // Also inspect random location. Make sure it is a legal value (or null when it is not set yet)
                TestValue other = list[rnd.Next(maxIndex)];
                XAssert.IsTrue(other == null || other.Value == val0 || other.Value == val1 || other.Value == val2);
            });
        }
Ejemplo n.º 9
0
 void IObserver <ChangedPathInfo> .OnError(Exception error)
 {
     XAssert.Fail("Error processing: " + error);
 }
Ejemplo n.º 10
0
        public void AllBasicEvents()
        {
            using (var l = new TestListener())
            {
                MemberInfo[] allEventsMembers = typeof(Events).GetMembers(BindingFlags.Public | BindingFlags.Instance);

                foreach (MemberInfo eventsMember in allEventsMembers)
                {
                    if (eventsMember is MethodInfo)
                    {
                        // Not all members are methods.
                        continue;
                    }

                    var eventAttribute = eventsMember.GetCustomAttribute(typeof(EventAttribute)) as EventAttribute;
                    if (eventAttribute == null)
                    {
                        // Not all members are tagged with [Event] data.
                        continue;
                    }

                    var      eventMethod = (MethodInfo)eventsMember;
                    bool     containsRelatedActivityId;
                    object[] payload = CreateEventPayload(eventMethod, out containsRelatedActivityId);

                    eventMethod.Invoke(Events.Log, payload);

                    XAssert.AreEqual(eventAttribute.EventId, l.LastEvent.EventId, "Wrong event ID logged for event {0}", eventMethod.Name);
                    XAssert.AreNotEqual(0, eventAttribute.Task, "Invalid task id == 0 for event {0} (this results in auto-assignment of task id)", eventMethod.Name);
                    XAssert.AreEqual(eventAttribute.Task, l.LastEvent.Task, "Wrong task logged for event {0}", eventMethod.Name);
                    XAssert.AreEqual(eventAttribute.Opcode, l.LastEvent.Opcode, "Wrong opcode logged for event {0}", eventMethod.Name);
                    XAssert.AreEqual(eventAttribute.Level, l.LastEvent.Level, "Wrong level logged for event {0}", eventMethod.Name);
                    XAssert.IsTrue(!containsRelatedActivityId || eventAttribute.Opcode == EventOpcode.Start, "Found related activity ID for non-start event {0}", eventMethod.Name);

                    // EventSource does something weird with the top bits, but the bottom bits should be non-zero.
                    unchecked
                    {
                        XAssert.AreEqual <uint>(
                            (uint)eventAttribute.Keywords,
                            (uint)l.LastEvent.Keywords,
                            "Wrong keywords logged for event {0}",
                            eventMethod.Name);
                        XAssert.AreNotEqual <uint>(0, (uint)eventAttribute.Keywords, "Event {0} should have keywords defined", eventMethod.Name);
                    }

                    XAssert.IsTrue(
                        (eventAttribute.Keywords & Keywords.Diagnostics) == 0 || (eventAttribute.Keywords & Keywords.UserMessage) == 0,
                        "Event {0} specifies both the UserMessage and Diagnostics keywords; these are mutually exclusive.", eventMethod.Name);

                    string formattedMessage;
                    try
                    {
                        formattedMessage = string.Format(CultureInfo.InvariantCulture, l.LastEvent.Message, l.LastEvent.Payload.ToArray());
                    }
                    catch (FormatException ex)
                    {
                        XAssert.Fail(
                            "Formatting the message for event {0}. Maybe the format string does not match the WriteEvent arguments. Exception: {1}",
                            eventMethod.Name,
                            ex.ToString());
                        return;
                    }

                    if (containsRelatedActivityId)
                    {
                        object[] payloadCopy = new object[payload.Length - 1];
                        Array.Copy(payload, 1, payloadCopy, 0, payloadCopy.Length);
                        payload = payloadCopy;
                    }

                    XAssert.AreEqual(
                        payload.Length,
                        l.LastEvent.Payload.Count,
                        "Wrong payload size for event {0} (formatted message: `{1}`)",
                        eventMethod.Name,
                        formattedMessage);

                    for (int i = 0; i < payload.Length; i++)
                    {
                        XAssert.AreEqual(
                            payload[i],
                            l.LastEvent.Payload[i],
                            "Incorrect payload value for event {0}, position {1} (formatted message: `{2}`)",
                            eventMethod.Name,
                            i,
                            formattedMessage);
                    }

                    // We now verify that all strings in the payload appear in the message.
                    // We exclude pip-provenance and phase events for now because for some reason they define GUIDs that never actually
                    // get logged (which is probably not a valid thing to do on an EventSource).
                    if (!l.LastEvent.Message.StartsWith(EventConstants.ProvenancePrefix, StringComparison.Ordinal) &&
                        !l.LastEvent.Message.StartsWith(EventConstants.PhasePrefix, StringComparison.Ordinal))
                    {
                        for (int i = 0; i < payload.Length; i++)
                        {
                            var currentPayload = payload[i] as string;

                            if (currentPayload != null)
                            {
                                XAssert.IsTrue(
                                    formattedMessage.Contains(currentPayload),
                                    "The formatted message for event {0} did not include the payload string at index {1}",
                                    eventMethod.Name,
                                    i);
                            }
                        }
                    }

                    if (eventAttribute.EventId != (int)EventId.ErrorEvent)
                    {
                        XAssert.IsTrue(
                            eventAttribute.Level != EventLevel.Error ||
                            (eventAttribute.Keywords & Keywords.UserMessage) == Keywords.UserMessage,
                            "Event {0} marked as Error must be Keywords.UserMessage",
                            eventMethod.Name);
                    }
                }
            }
        }
Ejemplo n.º 11
0
        public void RoundTripLog()
        {
            BuildXLContext context = BuildXLContext.CreateInstanceForTesting();

            var pt = context.PathTable;

            string path1 = A("c", "a", "b", "c");
            var    ap1   = AbsolutePath.Create(pt, path1);
            string path2 = A("c", "d", "c", "a");
            var    ap2   = AbsolutePath.Create(pt, path2);

            string path3 = A("d", "a", "c", "a");
            var    ap3   = AbsolutePath.Create(pt, path3);

            string path3Caps = A("D", "A", "c", "a");
            var    ap3Caps   = AbsolutePath.Create(pt, path3Caps);

            int  lastTestCase0EventIteration = 0;
            int  testCase0EventIteration     = 0;
            int  expectedReadCount           = 0;
            Guid logId = Guid.NewGuid();

            using (MemoryStream ms = new MemoryStream())
            {
                using (BinaryLogger writer = new BinaryLogger(ms, context, logId, lastStaticAbsolutePathIndex: ap2.Value.Value, closeStreamOnDispose: false))
                {
                    using (var eventScope = writer.StartEvent((uint)EventId.TestCase0, workerId: 0))
                    {
                        eventScope.Writer.Write(ap1);
                        eventScope.Writer.Write("test string");
                        eventScope.Writer.Write(ap3);
                        eventScope.Writer.Write(12345);
                        expectedReadCount++;
                        lastTestCase0EventIteration++;
                    }

                    using (var eventScope = writer.StartEvent((uint)EventId.TestCase0, workerId: 0))
                    {
                        eventScope.Writer.Write("test string 2");
                        eventScope.Writer.Write(true);
                        eventScope.Writer.Write(ap3);
                        expectedReadCount++;
                        lastTestCase0EventIteration++;
                    }
                }

                ms.Position = 0;

                using (BinaryLogReader reader = new BinaryLogReader(ms, context))
                {
                    XAssert.IsTrue(reader.LogId.HasValue);
                    XAssert.AreEqual(logId, reader.LogId.Value);
                    reader.RegisterHandler((uint)EventId.TestCase0, (eventId, workerId, timestamp, eventReader) =>
                    {
                        switch (testCase0EventIteration)
                        {
                        case 0:
                            XAssert.AreEqual(ap1, eventReader.ReadAbsolutePath());
                            XAssert.AreEqual("test string", eventReader.ReadString());
                            XAssert.AreEqual(ap3, eventReader.ReadAbsolutePath());
                            XAssert.AreEqual(12345, eventReader.ReadInt32());
                            break;

                        case 1:
                            XAssert.AreEqual("test string 2", eventReader.ReadString());
                            XAssert.AreEqual(true, eventReader.ReadBoolean());
                            XAssert.AreEqual(ap3, eventReader.ReadAbsolutePath());
                            break;

                        default:
                            XAssert.Fail("Event raised unexpected number of times.");
                            break;
                        }

                        testCase0EventIteration++;
                    });

                    reader.RegisterHandler((uint)EventId.UnusedEvent, (eventId, workerId, timestamp, eventReader) =>
                    {
                        XAssert.Fail("This event should never be called.");
                    });

                    int readCount = 0;
                    BinaryLogReader.EventReadResult?readResult;
                    while ((readResult = reader.ReadEvent()) == BinaryLogReader.EventReadResult.Success)
                    {
                        XAssert.IsTrue(readCount < expectedReadCount);
                        readCount++;
                    }

                    XAssert.AreEqual(expectedReadCount, readCount);
                    XAssert.AreEqual(lastTestCase0EventIteration, testCase0EventIteration);
                    XAssert.AreEqual(BinaryLogReader.EventReadResult.EndOfStream, readResult);
                }
            }
        }
Ejemplo n.º 12
0
        public void ChildProcessCanBreakawayWhenConfigured(bool letInfiniteWaiterSurvive)
        {
            // Skip this test if running on .NET Framework with vstest
            // Reason: when this is the case and code coverage is turned on, launching breakaway
            //         processes here causes the code coverage monitoring process to hang.
            if (!OperatingSystemHelper.IsDotNetCore && IsRunningInVsTestTestHost())
            {
                return;
            }

            // We use InfiniteWaiter (a process that waits forever) as a long-living process that we can actually check it can
            // escape the job object
            var fam = new FileAccessManifest(
                Context.PathTable,
                childProcessesToBreakawayFromSandbox: letInfiniteWaiterSurvive ? new[] { InfiniteWaiterToolName } : null)
            {
                FailUnexpectedFileAccesses = false
            };

            // We instruct the regular test process to spawn InfiniteWaiter as a child
            var info = ToProcessInfo(
                ToProcess(
                    Operation.SpawnExe(
                        Context.PathTable,
                        CreateFileArtifactWithName(InfiniteWaiterToolName, TestDeploymentDir))),
                fileAccessManifest: fam);

            // Let's shorten the default time to wait for nested processes, since we are spawning
            // a process that never ends and we don't want this test to wait for that long
            info.NestedProcessTerminationTimeout = TimeSpan.FromMilliseconds(10);

            var result = RunProcess(info).GetAwaiter().GetResult();

            XAssert.AreEqual(0, result.ExitCode);

            if (!letInfiniteWaiterSurvive)
            {
                // If we didn't let infinite waiter escape, we should have killed it when the job object was finalized
                XAssert.IsTrue(result.Killed);
                XAssert.Contains(
                    result.SurvivingChildProcesses.Select(p => p?.Path).Where(p => p != null).Select(p => System.IO.Path.GetFileName(p).ToUpperInvariant()),
                    InfiniteWaiterToolName.ToUpperInvariant());
            }
            else
            {
                // If we did let it escape, then nothing should have been killed (nor tried to survive and later killed, from the job object point of view)
                XAssert.IsFalse(result.Killed);
                if (result.SurvivingChildProcesses != null && result.SurvivingChildProcesses.Any())
                {
                    var survivors = string.Join(
                        ", ",
                        result.SurvivingChildProcesses.Select(p => p?.Path != null ? System.IO.Path.GetFileName(p.Path) : "<unknown>"));
                    XAssert.Fail($"Unexpected {result.SurvivingChildProcesses.Count()} surviving child processes: {survivors}");
                }

                // Let's retrieve the child process and confirm it survived
                var infiniteWaiterInfo = RetrieveChildProcessesCreatedBySpawnExe(result).Single();
                // The fact that this does not throw confirms survival
                var dummyWaiter = Process.GetProcessById(infiniteWaiterInfo.pid);
                // Just being protective, let's make sure we are talking about the same process
                XAssert.AreEqual(infiniteWaiterInfo.processName, dummyWaiter.ProcessName);

                // Now let's kill the surviving process, since we don't want it to linger around unnecessarily
                dummyWaiter.Kill();
            }
        }