Example #1
0
        public void ILLink_only_runs_when_switch_is_enabled(string targetFramework)
        {
            var projectName          = "HelloWorld";
            var referenceProjectName = "ClassLibForILLink";
            var rid = EnvironmentInfo.GetCompatibleRid(targetFramework);

            var testProject = CreateTestProjectForILLinkTesting(targetFramework, projectName, referenceProjectName);

            string[] restoreArgs = { $"/p:RuntimeIdentifier={rid}", "/p:SelfContained=true" };
            var      testAsset   = _testAssetsManager.CreateTestProject(testProject)
                                   .Restore(Log, testProject.Name, restoreArgs);

            var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name));

            publishCommand.Execute($"/p:RuntimeIdentifier={rid}", $"/p:SelfContained=true").Should().Pass();

            var publishDirectory      = publishCommand.GetOutputDirectory(targetFramework: targetFramework, runtimeIdentifier: rid).FullName;
            var intermediateDirectory = publishCommand.GetIntermediateDirectory(targetFramework: targetFramework, runtimeIdentifier: rid).FullName;
            var linkedDirectory       = Path.Combine(intermediateDirectory, "linked");

            Directory.Exists(linkedDirectory).Should().BeFalse();

            var publishedDll       = Path.Combine(publishDirectory, $"{projectName}.dll");
            var unusedDll          = Path.Combine(publishDirectory, $"{referenceProjectName}.dll");
            var unusedFrameworkDll = Path.Combine(publishDirectory, $"{unusedFrameworkAssembly}.dll");

            // Linker inputs are kept, including unused assemblies
            File.Exists(publishedDll).Should().BeTrue();
            File.Exists(unusedDll).Should().BeTrue();
            File.Exists(unusedFrameworkDll).Should().BeTrue();

            var depsFile = Path.Combine(publishDirectory, $"{projectName}.deps.json");

            DoesDepsFileHaveAssembly(depsFile, referenceProjectName).Should().BeTrue();
            DoesDepsFileHaveAssembly(depsFile, unusedFrameworkAssembly).Should().BeTrue();
        }
Example #2
0
        public void It_only_runs_readytorun_compiler_when_switch_is_enabled(string targetFramework)
        {
            var projectName = "CrossgenTest1";

            var testProject = CreateTestProjectForR2RTesting(
                EnvironmentInfo.GetCompatibleRid(targetFramework),
                projectName,
                "ClassLib");

            var testProjectInstance = _testAssetsManager.CreateTestProject(testProject)
                                      .Restore(Log, testProject.Name);

            var publishCommand = new PublishCommand(Log, Path.Combine(testProjectInstance.Path, testProject.Name));

            publishCommand.Execute("/v:n").Should().Pass();

            DirectoryInfo publishDirectory = publishCommand.GetOutputDirectory(
                targetFramework,
                "Debug",
                EnvironmentInfo.GetCompatibleRid(targetFramework));

            DoesImageHaveR2RInfo(Path.Combine(publishDirectory.FullName, $"{projectName}.dll")).ToString().Should().Be(false.ToString());
            DoesImageHaveR2RInfo(Path.Combine(publishDirectory.FullName, "ClassLib.dll")).ToString().Should().Be(false.ToString());
        }
Example #3
0
        public void ILLink_accepts_root_descriptor(string targetFramework)
        {
            var projectName          = "HelloWorld";
            var referenceProjectName = "ClassLibForILLink";
            var rid = EnvironmentInfo.GetCompatibleRid(targetFramework);

            var testProject = CreateTestProjectForILLinkTesting(targetFramework, projectName, referenceProjectName);

            string[] restoreArgs = { $"/p:RuntimeIdentifier={rid}", "/p:SelfContained=true" };
            var      testAsset   = _testAssetsManager.CreateTestProject(testProject)
                                   .WithProjectChanges(project => EnableNonFrameworkTrimming(project))
                                   .WithProjectChanges(project => AddRootDescriptor(project, $"{referenceProjectName}.xml"))
                                   .Restore(Log, testProject.Name, restoreArgs);

            var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name));
            // Inject extra arguments to prevent the linker from
            // keeping the entire referenceProject assembly. The
            // linker by default runs in a conservative mode that
            // keeps all used assemblies, but in this case we want to
            // check whether the root descriptor actually roots only
            // the specified method.
            var extraArgs = $"-p link {referenceProjectName}";

            publishCommand.Execute($"/p:RuntimeIdentifier={rid}", $"/p:SelfContained=true", "/p:PublishTrimmed=true",
                                   $"/p:_ExtraTrimmerArgs={extraArgs}", "/v:n").Should().Pass();

            var publishDirectory = publishCommand.GetOutputDirectory(targetFramework: targetFramework, runtimeIdentifier: rid).FullName;
            var publishedDll     = Path.Combine(publishDirectory, $"{projectName}.dll");
            var unusedDll        = Path.Combine(publishDirectory, $"{referenceProjectName}.dll");

            // With root descriptor, linker keeps specified roots but removes unused methods
            File.Exists(publishedDll).Should().BeTrue();
            File.Exists(unusedDll).Should().BeTrue();
            DoesImageHaveMethod(unusedDll, "UnusedMethod").Should().BeFalse();
            DoesImageHaveMethod(unusedDll, "UnusedMethodToRoot").Should().BeTrue();
        }
        private void Versions_are_included(bool build, [CallerMemberName] string callingMethod = "")
        {
            var testProject = GetTestProject();

            if (!EnvironmentInfo.SupportsTargetFramework(testProject.TargetFrameworks))
            {
                return;
            }

            testProject.RuntimeIdentifier = EnvironmentInfo.GetCompatibleRid(testProject.TargetFrameworks);

            var testAsset = _testAssetsManager.CreateTestProject(testProject, callingMethod);

            MSBuildCommand command;

            if (build)
            {
                command = new BuildCommand(testAsset);
            }
            else
            {
                command = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name));
            }

            command.Execute()
            .Should()
            .Pass();

            var outputDirectory = command.GetOutputDirectory(testProject.TargetFrameworks, runtimeIdentifier: testProject.RuntimeIdentifier);

            outputDirectory.Should().HaveFile(testProject.Name + ".deps.json");

            var depsFilePath = Path.Combine(outputDirectory.FullName, $"{testProject.Name}.deps.json");

            CheckVersionsInDepsFile(depsFilePath);
        }
Example #5
0
        public void NetStandardFacadesArePublished()
        {
            var netStandardProject = new TestProject()
            {
                Name             = "NetStandardProject",
                TargetFrameworks = "netstandard2.0"
            };

            var testProject = new TestProject()
            {
                TargetFrameworks = "net462",
                IsExe            = true
            };

            testProject.ReferencedProjects.Add(netStandardProject);

            var testAsset = _testAssetsManager.CreateTestProject(testProject);

            var publishCommand = new PublishCommand(testAsset);

            publishCommand.Execute()
            .Should()
            .Pass();

            //  There are close to 100 facades that should be copied, just check for a few of them here
            publishCommand.GetOutputDirectory(testProject.TargetFrameworks)
            .Should()
            .HaveFiles(new[]
            {
                "netstandard.dll",
                "System.IO.dll",
                "System.Runtime.dll"
            })
            .And
            .NotHaveFile("netfx.force.conflicts.dll");
        }
        public void AoT_Publish_InRelease_Works()
        {
            // Arrange
            var testAppName  = "BlazorWasmWithLibrary";
            var testInstance = CreateAspNetSdkTestAssetWithAot(testAppName, new [] { "blazorwasm" });

            File.WriteAllText(Path.Combine(testInstance.TestRoot, "blazorwasm", "App.razor.css"), "h1 { font-size: 16px; }");

            var publishCommand = new PublishCommand(Log, Path.Combine(testInstance.TestRoot, "blazorwasm"));

            publishCommand.Execute("/p:Configuration=Release").Should().Pass();

            var publishDirectory = publishCommand.GetOutputDirectory(DefaultTfm, "Release");

            var blazorPublishDirectory = Path.Combine(publishDirectory.ToString(), "wwwroot");

            var expectedFiles = new[]
            {
                "wwwroot/_framework/blazor.boot.json",
                "wwwroot/_framework/blazor.webassembly.js",
                "wwwroot/_framework/dotnet.wasm",
                "wwwroot/_framework/blazorwasm.dll",
                "wwwroot/_framework/System.Text.Json.dll",
                "wwwroot/_content/RazorClassLibrary/wwwroot/exampleJsInterop.js",
                "wwwroot/_content/RazorClassLibrary/styles.css",
                "wwwroot/index.html",
                "wwwroot/js/LinkedScript.js",
                "wwwroot/blazorwasm.styles.css",
                "wwwroot/css/app.css",
                "web.config"
            };

            publishDirectory.Should().HaveFiles(expectedFiles);

            new FileInfo(Path.Combine(blazorPublishDirectory, "css", "app.css")).Should().Contain(".publish");
        }
        public void It_can_make_a_Windows_GUI_exe()
        {
            var runtimeIdentifier = EnvironmentInfo.GetCompatibleRid("netcoreapp2.0");

            var testAsset = _testAssetsManager
                            .CopyTestAsset(TestProjectName)
                            .WithSource()
                            .WithProjectChanges(doc =>
            {
                doc.Root.Element("PropertyGroup").Element("TargetFramework").SetValue(TargetFramework);
            })
                            .Restore(Log, relativePath: "", args: $"/p:RuntimeIdentifier={runtimeIdentifier}");

            var publishCommand = new PublishCommand(Log, testAsset.TestRoot);

            publishCommand
            .Execute(
                "/p:SelfContained=true",
                "/p:OutputType=WinExe",
                $"/p:TargetFramework={TargetFramework}",
                $"/p:RuntimeIdentifier={runtimeIdentifier}")
            .Should()
            .Pass();

            string outputDirectory = publishCommand.GetOutputDirectory(
                targetFramework: TargetFramework,
                runtimeIdentifier: runtimeIdentifier).FullName;

            byte[] fileContent    = File.ReadAllBytes(Path.Combine(outputDirectory, TestProjectName + ".exe"));
            UInt32 peHeaderOffset = BitConverter.ToUInt32(fileContent, PEHeaderPointerOffset);

            BitConverter
            .ToUInt16(fileContent, (int)(peHeaderOffset + SubsystemOffset))
            .Should()
            .Be(2);
        }
        public void It_publishes_windows_Forms_app_with_warning()
        {
            var         targetFramework = "net6.0-windows";
            TestProject testProject     = new TestProject()
            {
                Name             = "WinformsWarnPresentPassTest",
                TargetFrameworks = targetFramework,
                IsWinExe         = true
            };

            testProject.AdditionalProperties["UseWindowsForms"]   = "true";
            testProject.AdditionalProperties["SelfContained"]     = "true";
            testProject.AdditionalProperties["RuntimeIdentifier"] = "win-x64";
            testProject.AdditionalProperties["PublishTrimmed"]    = "true";
            var testAsset = _testAssetsManager.CreateTestProject(testProject);

            var publishCommand = new PublishCommand(testAsset);

            publishCommand.Execute()
            .Should()
            .Pass()
            .And
            .HaveStdOutContaining("NETSDK1175");
        }
        public void NativeAot_compiler_runs_when_PublishAot_is_enabled(string targetFramework)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                var projectName = "WarningAppWithPublishAot";
                var rid         = EnvironmentInfo.GetCompatibleRid(targetFramework);

                // PublishAot should enable the EnableAotAnalyzer, EnableTrimAnalyzer and EnableSingleFileAnalyzer
                var testProject = CreateTestProjectWithAnalysisWarnings(targetFramework, projectName, true);
                testProject.AdditionalProperties["PublishAot"] = "true";
                testProject.AdditionalProperties["SuppressTrimAnalysisWarnings"] = "false";
                testProject.AdditionalProperties["RuntimeIdentifier"]            = rid;
                var testAsset = _testAssetsManager.CreateTestProject(testProject);

                var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name));
                publishCommand
                .Execute()
                .Should().Pass()
                .And.HaveStdOutContaining("warning IL3050")
                .And.HaveStdOutContaining("warning IL3056")
                .And.HaveStdOutContaining("warning IL2026")
                .And.HaveStdOutContaining("warning IL3002");

                var publishDirectory = publishCommand.GetOutputDirectory(targetFramework: targetFramework, runtimeIdentifier: rid);

                var publishedExe = Path.Combine(publishDirectory.FullName, $"{testProject.Name}{Constants.ExeSuffix}");

                // The exe exist and should be native
                File.Exists(publishedExe).Should().BeTrue();
                IsNativeImage(publishedExe).Should().BeTrue();

                var command = new RunExeCommand(Log, publishedExe)
                              .Execute().Should().Pass()
                              .And.HaveStdOutContaining("Hello world");
            }
        }
Example #10
0
        public void Publish_self_contained_app_with_dot_in_the_name()
        {
            var targetFramework = "netcoreapp2.1";
            var rid             = EnvironmentInfo.GetCompatibleRid(targetFramework);

            TestProject testProject = new TestProject()
            {
                Name              = "Hello.World",
                TargetFrameworks  = targetFramework,
                RuntimeIdentifier = rid,
                IsExe             = true,
            };

            testProject.AdditionalProperties["CopyLocalLockFileAssemblies"] = "true";
            testProject.SourceFiles["Program.cs"] = @"
using System;
public static class Program
{
    public static void Main()
    {
        Console.WriteLine(""Hello from a netcoreapp2.1!"");
    }
}
";
            var testProjectInstance = _testAssetsManager.CreateTestProject(testProject);

            var publishCommand = new PublishCommand(testProjectInstance);

            publishCommand.Execute().Should().Pass();

            var publishDirectory = publishCommand.GetOutputDirectory(
                targetFramework: targetFramework,
                runtimeIdentifier: rid);

            publishDirectory.Should().HaveFile($"Hello.World{Constants.ExeSuffix}");
        }
Example #11
0
        public void It_does_not_support_framework_dependent_publishing(string targetFramework)
        {
            var projectName = "FrameworkDependent";

            var testProject = CreateTestProjectForR2RTesting(
                EnvironmentInfo.GetCompatibleRid(targetFramework),
                projectName,
                "ClassLib");

            testProject.AdditionalProperties["PublishReadyToRun"] = "True";

            var testProjectInstance = _testAssetsManager.CreateTestProject(testProject)
                                      .Restore(Log, testProject.Name);

            // TODO: This test should be changed to expect publishing to succeed when fixing #3109 and #3110.
            // When fixing the issues, change the function name to reflect what we're testing, and change the test's expected
            // behavior (check that the output assemblies exist and are R2R images).
            var publishCommand = new PublishCommand(Log, Path.Combine(testProjectInstance.Path, testProject.Name));

            publishCommand.Execute("/p:SelfContained=false", "/v:n")
            .Should()
            .Fail()
            .And.HaveStdOutContainingIgnoreCase("NETSDK1095");
        }
        public void It_publishes_projects_with_simple_dependencies_with_filter_profile()
        {
            string project = "SimpleDependencies";

            TestAsset simpleDependenciesAsset = _testAssetsManager
                                                .CopyTestAsset(project)
                                                .WithSource()
                                                .Restore();

            string filterProjDir   = _testAssetsManager.GetAndValidateTestProjectDirectory("FilterProfiles");
            string filterProjFile1 = Path.Combine(filterProjDir, "NewtonsoftFilterProfile.xml");
            string filterProjFile2 = Path.Combine(filterProjDir, "NewtonsoftMultipleVersions.xml");

            PublishCommand publishCommand = new PublishCommand(Stage0MSBuild, simpleDependenciesAsset.TestRoot);

            publishCommand
            .Execute($"/p:FilterProjectFiles={filterProjFile1}%3b{filterProjFile2}")
            .Should()
            .Pass();

            DirectoryInfo publishDirectory = publishCommand.GetOutputDirectory();

            publishDirectory.Should().OnlyHaveFiles(new[] {
                $"{project}.dll",
                $"{project}.pdb",
                $"{project}.deps.json",
                $"{project}.runtimeconfig.json",
                "System.Collections.NonGeneric.dll"
            });

            var runtimeConfig = ReadJson(System.IO.Path.Combine(publishDirectory.ToString(), $"{project}.runtimeconfig.json"));

            runtimeConfig["runtimeOptions"]["tfm"].ToString().Should().Be("netcoreapp1.1");

//TODO: Enable testing the run once dotnet host has the notion of looking up shared packages
        }
Example #13
0
        public void It_publishes_the_project_correctly(string targetFramework, string [] expectedPublishFiles)
        {
            PublishCommand publishCommand = GetPublishCommand(targetFramework);

            publishCommand
            .Execute()
            .Should()
            .Pass();

            DirectoryInfo publishDirectory = publishCommand.GetOutputDirectory(targetFramework);

            publishDirectory.Should().OnlyHaveFiles(expectedPublishFiles);

            using (var depsJsonFileStream = File.OpenRead(Path.Combine(publishDirectory.FullName, "TestApp.deps.json")))
            {
                var dependencyContext = new DependencyContextJsonReader().Read(depsJsonFileStream);

                // Ensure Newtonsoft.Json doesn't get excluded from the deps.json file.
                // TestLibrary has a hard dependency on Newtonsoft.Json.
                // TestApp has a PrivateAssets=All dependency on Microsoft.Extensions.DependencyModel, which depends on Newtonsoft.Json.
                // This verifies that P2P references get walked correctly when doing PrivateAssets exclusion.
                VerifyDependency(dependencyContext, "Newtonsoft.Json", "lib/netstandard1.0/", null);

                // Verify P2P references get created correctly in the .deps.json file.
                VerifyDependency(dependencyContext, "TestLibrary", "", null,
                                 "da", "de", "fr");

                // Verify package reference with satellites gets created correctly in the .deps.json file
                VerifyDependency(dependencyContext, "Humanizer.Core", "lib/netstandard1.0/", "Humanizer",
                                 "af", "ar", "az", "bg", "bn-BD", "cs", "da", "de", "el", "es", "fa", "fi-FI", "fr", "fr-BE", "he", "hr",
                                 "hu", "hy", "id", "it", "ja", "lv", "ms-MY", "mt", "nb", "nb-NO", "nl", "pl", "pt", "ro", "ru", "sk", "sl", "sr",
                                 "sr-Latn", "sv", "tr", "uk", "uz-Cyrl-UZ", "uz-Latn-UZ", "vi", "zh-CN", "zh-Hans", "zh-Hant");
            }

            var runtimeConfigJsonContents = File.ReadAllText(Path.Combine(publishDirectory.FullName, "TestApp.runtimeconfig.json"));
            var runtimeConfigJsonObject   = JObject.Parse(runtimeConfigJsonContents);

            var baselineConfigJsonObject = JObject.Parse(@"{
    ""runtimeOptions"": {
        ""configProperties"": {
            ""System.Diagnostics.Debugger.IsSupported"": true,
            ""System.Diagnostics.Tracing.EventSource.IsSupported"": false,
            ""System.Globalization.Invariant"": true,
            ""System.GC.Concurrent"": false,
            ""System.GC.Server"": true,
            ""System.GC.RetainVM"": false,
            ""System.Net.Http.EnableActivityPropagation"": false,
            ""System.Resources.UseSystemResourceKeys"": true,
            ""System.Runtime.TieredCompilation"": true,
            ""System.Runtime.TieredCompilation.QuickJit"": true,
            ""System.Runtime.TieredCompilation.QuickJitForLoops"": true,
            ""System.StartupHookProvider.IsSupported"": false,
            ""System.Threading.Thread.EnableAutoreleasePool"": false,
            ""System.Resources.ResourceManager.AllowCustomResourceTypes"": false,
            ""System.ComponentModel.TypeConverter.EnableUnsafeBinaryFormatterInDesigntimeLicenseContextSerialization"": false,
            ""System.Text.Encoding.EnableUnsafeUTF7Encoding"": false,
            ""System.Threading.ThreadPool.MinThreads"": 2,
            ""System.Threading.ThreadPool.MaxThreads"": 9,
            ""extraProperty"": true
        },
        ""framework"": {
            ""name"": ""Microsoft.NETCore.App"",
            ""version"": ""set below""
        },
        ""applyPatches"": true
    }
}");

            baselineConfigJsonObject["runtimeOptions"]["tfm"] = targetFramework;
            baselineConfigJsonObject["runtimeOptions"]["framework"]["version"] =
                targetFramework == "netcoreapp1.0" ? "1.0.5" : "1.1.2";

            runtimeConfigJsonObject
            .Should()
            .BeEquivalentTo(baselineConfigJsonObject);
        }
        public void It_publishes_the_project_correctly(string targetFramework, string [] expectedPublishFiles)
        {
            TestAsset testAsset = _testAssetsManager
                                  .CopyTestAsset("KitchenSink", "KitchenSinkPublish_", targetFramework)
                                  .WithSource()
                                  .WithProjectChanges((path, project) =>
            {
                if (Path.GetFileName(path).Equals("TestApp.csproj", StringComparison.OrdinalIgnoreCase))
                {
                    var ns = project.Root.Name.Namespace;

                    var targetFrameworkElement = project.Root.Elements(ns + "PropertyGroup").Elements(ns + "TargetFramework").Single();
                    targetFrameworkElement.SetValue(targetFramework);
                }
            });

            testAsset.Restore(Log, "TestApp");
            testAsset.Restore(Log, "TestLibrary");

            var appProjectDirectory = Path.Combine(testAsset.TestRoot, "TestApp");

            PublishCommand publishCommand = new PublishCommand(Log, appProjectDirectory);

            publishCommand
            .Execute()
            .Should()
            .Pass();

            DirectoryInfo publishDirectory = publishCommand.GetOutputDirectory(targetFramework);

            publishDirectory.Should().OnlyHaveFiles(expectedPublishFiles);

            using (var depsJsonFileStream = File.OpenRead(Path.Combine(publishDirectory.FullName, "TestApp.deps.json")))
            {
                var dependencyContext = new DependencyContextJsonReader().Read(depsJsonFileStream);

                // Ensure Newtonsoft.Json doesn't get excluded from the deps.json file.
                // TestLibrary has a hard dependency on Newtonsoft.Json.
                // TestApp has a PrivateAssets=All dependency on Microsoft.Extensions.DependencyModel, which depends on Newtonsoft.Json.
                // This verifies that P2P references get walked correctly when doing PrivateAssets exclusion.
                VerifyDependency(dependencyContext, "Newtonsoft.Json", "lib/netstandard1.0/", null);

                // Verify P2P references get created correctly in the .deps.json file.
                VerifyDependency(dependencyContext, "TestLibrary", "", null,
                                 "da", "de", "fr");

                // Verify package reference with satellites gets created correctly in the .deps.json file
                VerifyDependency(dependencyContext, "Humanizer.Core", "lib/netstandard1.0/", "Humanizer",
                                 "af", "ar", "bg", "bn-BD", "cs", "da", "de", "el", "es", "fa", "fi-FI", "fr", "fr-BE", "he", "hr",
                                 "hu", "id", "it", "ja", "lv", "nb", "nb-NO", "nl", "pl", "pt", "ro", "ru", "sk", "sl", "sr",
                                 "sr-Latn", "sv", "tr", "uk", "uz-Cyrl-UZ", "uz-Latn-UZ", "vi", "zh-CN", "zh-Hans", "zh-Hant");
            }

            var runtimeConfigJsonContents = File.ReadAllText(Path.Combine(publishDirectory.FullName, "TestApp.runtimeconfig.json"));
            var runtimeConfigJsonObject   = JObject.Parse(runtimeConfigJsonContents);

            var baselineConfigJsonObject = JObject.Parse(@"{
    ""runtimeOptions"": {
        ""configProperties"": {
            ""System.GC.Concurrent"": false,
            ""System.GC.Server"": true,
            ""System.GC.RetainVM"": false,
            ""System.Threading.ThreadPool.MinThreads"": 2,
            ""System.Threading.ThreadPool.MaxThreads"": 9,
            ""extraProperty"": true
        },
        ""framework"": {
            ""name"": ""Microsoft.NETCore.App"",
            ""version"": ""set below""
        },
        ""applyPatches"": true
    }
}");

            baselineConfigJsonObject["runtimeOptions"]["tfm"] = targetFramework;
            baselineConfigJsonObject["runtimeOptions"]["framework"]["version"] =
                targetFramework == "netcoreapp1.0" ? "1.0.5" : "1.1.2";

            runtimeConfigJsonObject
            .Should()
            .BeEquivalentTo(baselineConfigJsonObject);
        }
        //  "No build" scenario doesn't currently work: https://github.com/dotnet/sdk/issues/2956
        //[InlineData(true)]
        public void PublishWithRuntimeIdentifier(bool publishNoBuild)
        {
            var testProject = new TestProject()
            {
                Name             = "PublishWithRid",
                TargetFrameworks = "netcoreapp3.0",
                IsExe            = true
            };

            var compatibleRid = EnvironmentInfo.GetCompatibleRid(testProject.TargetFrameworks);

            var runtimeIdentifiers = new[]
            {
                "win-x64",
                "linux-x64",
                compatibleRid
            };

            testProject.AdditionalProperties["RuntimeIdentifiers"] = string.Join(';', runtimeIdentifiers);

            //  Use a test-specific packages folder
            testProject.AdditionalProperties["RestorePackagesPath"] = @"$(MSBuildProjectDirectory)\..\pkg";

            var testAsset = _testAssetsManager.CreateTestProject(testProject, identifier: publishNoBuild ? "nobuild" : string.Empty);

            var buildCommand = new BuildCommand(testAsset);

            buildCommand
            .Execute()
            .Should()
            .Pass();

            foreach (var runtimeIdentifier in runtimeIdentifiers)
            {
                var publishArgs = new List <string>()
                {
                    $"/p:RuntimeIdentifier={runtimeIdentifier}"
                };
                if (publishNoBuild)
                {
                    publishArgs.Add("/p:NoBuild=true");
                }

                var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.Path, testProject.Name));
                publishCommand.Execute(publishArgs.ToArray())
                .Should()
                .Pass();

                if (runtimeIdentifier == compatibleRid)
                {
                    var    outputDirectory                 = publishCommand.GetOutputDirectory(testProject.TargetFrameworks, runtimeIdentifier: runtimeIdentifier);
                    var    selfContainedExecutable         = $"{testProject.Name}{Constants.ExeSuffix}";
                    string selfContainedExecutableFullPath = Path.Combine(outputDirectory.FullName, selfContainedExecutable);

                    new RunExeCommand(Log, selfContainedExecutableFullPath)
                    .Execute()
                    .Should()
                    .Pass()
                    .And
                    .HaveStdOutContaining("Hello World!");
                }
            }
        }
        public void Publish_standalone_post_netcoreapp2_arm_app(string runtimeIdentifier)
        {
            // Tests for existence of expected files when publishing an ARM project
            // See https://github.com/dotnet/sdk/issues/1239

            var targetFramework = "netcoreapp2.0";

            TestProject testProject = new TestProject()
            {
                Name              = "Hello",
                IsSdkProject      = true,
                TargetFrameworks  = targetFramework,
                RuntimeIdentifier = runtimeIdentifier,
                IsExe             = true,
            };

            testProject.AdditionalProperties["CopyLocalLockFileAssemblies"] = "true";
            testProject.SourceFiles["Program.cs"] = @"
using System;
public static class Program
{
    public static void Main()
    {
        Console.WriteLine(""Hello from an arm netcoreapp2.0 app!"");
    }
}
";
            var testProjectInstance = _testAssetsManager.CreateTestProject(testProject, identifier: runtimeIdentifier);

            testProjectInstance.Restore(Log, testProject.Name);
            var publishCommand = new PublishCommand(Log, Path.Combine(testProjectInstance.TestRoot, testProject.Name));
            var publishResult  = publishCommand.Execute();

            publishResult.Should().Pass();

            var publishDirectory = publishCommand.GetOutputDirectory(
                targetFramework: targetFramework,
                runtimeIdentifier: runtimeIdentifier);
            var outputDirectory = publishDirectory.Parent;

            // The name of the self contained executable depends on the runtime identifier.
            // For Windows family ARM publishing, it'll always be Hello.exe.
            // We shouldn't use "Constants.ExeSuffix" for the suffix here because that changes
            // depending on the RuntimeInformation
            var selfContainedExecutable = "Hello.exe";

            var filesPublished = new [] {
                selfContainedExecutable,
                "Hello.dll",
                "Hello.pdb",
                "Hello.deps.json",
                "Hello.runtimeconfig.json",
                "coreclr.dll",
                "hostfxr.dll",
                "hostpolicy.dll",
                "mscorlib.dll",
                "System.Private.CoreLib.dll",
            };

            outputDirectory.Should().HaveFiles(filesPublished);
            publishDirectory.Should().HaveFiles(filesPublished);
        }
Example #17
0
        public void It_publishes_the_project_with_a_refs_folder_and_correct_deps_file(string appTargetFramework, string libraryTargetFramework, bool withoutCopyingRefs)
        {
            if (appTargetFramework == "net46" && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                return;
            }

            var testLibraryProject = new TestProject()
            {
                Name             = "TestLibrary",
                IsSdkProject     = true,
                TargetFrameworks = libraryTargetFramework
            };

            var testProject = new TestProject()
            {
                Name              = "TestApp",
                IsSdkProject      = true,
                IsExe             = true,
                TargetFrameworks  = appTargetFramework,
                RuntimeIdentifier = "win7-x86"
            };

            testProject.AdditionalProperties["PreserveCompilationContext"] = "true";

            if (withoutCopyingRefs)
            {
                testProject.AdditionalProperties["PreserveCompilationReferences"] = "false";
            }

            testProject.ReferencedProjects.Add(testLibraryProject);
            testProject.PackageReferences.Add(new TestPackageReference("Newtonsoft.Json", "9.0.1"));
            testProject.PackageReferences.Add(new TestPackageReference("System.Data.SqlClient", "4.4.3"));

            var testAsset = _testAssetsManager.CreateTestProject(testProject, identifier: appTargetFramework + withoutCopyingRefs);

            testAsset.Restore(Log, "TestApp");

            var appProjectDirectory = Path.Combine(testAsset.TestRoot, "TestApp");
            var publishCommand      = new PublishCommand(Log, appProjectDirectory);

            publishCommand
            .Execute()
            .Should()
            .Pass();

            var publishDirectory = publishCommand.GetOutputDirectory(appTargetFramework, runtimeIdentifier: "win7-x86");

            publishDirectory.Should().HaveFiles(new[] {
                appTargetFramework == "net46" ? "TestApp.exe" : "TestApp.dll",
                "TestLibrary.dll",
                "Newtonsoft.Json.dll"
            });

            var refsDirectory = new DirectoryInfo(Path.Combine(publishDirectory.FullName, "refs"));

            if (withoutCopyingRefs)
            {
                refsDirectory.Should().NotExist();
            }
            else
            {
                // Should have compilation time assemblies
                refsDirectory.Should().HaveFile("System.IO.dll");
                // Libraries in which lib==ref should be deduped
                refsDirectory.Should().NotHaveFile("TestLibrary.dll");
                refsDirectory.Should().NotHaveFile("Newtonsoft.Json.dll");
            }

            using (var depsJsonFileStream = File.OpenRead(Path.Combine(publishDirectory.FullName, "TestApp.deps.json")))
            {
                var dependencyContext = new DependencyContextJsonReader().Read(depsJsonFileStream);

                string[] expectedDefines;
                if (appTargetFramework == "net46")
                {
                    expectedDefines = new[] { "DEBUG", "TRACE", "NETFRAMEWORK", "NET46" };
                }
                else
                {
                    expectedDefines = new[] { "DEBUG", "TRACE", "NETCOREAPP", appTargetFramework.ToUpperInvariant().Replace('.', '_') };
                }

                dependencyContext.CompilationOptions.Defines.Should().BeEquivalentTo(expectedDefines);
                dependencyContext.CompilationOptions.LanguageVersion.Should().BeOneOf("", "preview");
                dependencyContext.CompilationOptions.Platform.Should().Be("x86");
                dependencyContext.CompilationOptions.Optimize.Should().Be(false);
                dependencyContext.CompilationOptions.KeyFile.Should().Be("");
                dependencyContext.CompilationOptions.EmitEntryPoint.Should().Be(true);
                dependencyContext.CompilationOptions.DebugType.Should().Be("portable");

                var compileLibraryAssemblyNames = dependencyContext.CompileLibraries.SelectMany(cl => cl.Assemblies)
                                                  .Select(a => a.Split('/').Last())
                                                  .Distinct().ToList();
                var expectedCompileLibraryNames = CompileLibraryNames[appTargetFramework].Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

                var extraCompileLibraryNames   = compileLibraryAssemblyNames.Except(expectedCompileLibraryNames).ToList();
                var missingCompileLibraryNames = expectedCompileLibraryNames.Except(compileLibraryAssemblyNames).ToList();

                if (extraCompileLibraryNames.Any())
                {
                    Log.WriteLine("Unexpected compile libraries: " + string.Join(' ', extraCompileLibraryNames));
                }
                if (missingCompileLibraryNames.Any())
                {
                    Log.WriteLine("Missing compile libraries: " + string.Join(' ', missingCompileLibraryNames));
                }

                compileLibraryAssemblyNames.Should().BeEquivalentTo(expectedCompileLibraryNames);

                // Ensure P2P references are specified correctly
                var testLibrary = dependencyContext
                                  .CompileLibraries
                                  .FirstOrDefault(l => string.Equals(l.Name, "testlibrary", StringComparison.OrdinalIgnoreCase));

                testLibrary.Assemblies.Count.Should().Be(1);
                testLibrary.Assemblies[0].Should().Be("TestLibrary.dll");

                // Ensure framework references are specified correctly
                if (appTargetFramework == "net46")
                {
                    var mscorlibLibrary = dependencyContext
                                          .CompileLibraries
                                          .FirstOrDefault(l => string.Equals(l.Name, "mscorlib", StringComparison.OrdinalIgnoreCase));
                    mscorlibLibrary.Assemblies.Count.Should().Be(1);
                    mscorlibLibrary.Assemblies[0].Should().Be(".NETFramework/v4.6/mscorlib.dll");

                    var systemCoreLibrary = dependencyContext
                                            .CompileLibraries
                                            .FirstOrDefault(l => string.Equals(l.Name, "system.core", StringComparison.OrdinalIgnoreCase));
                    systemCoreLibrary.Assemblies.Count.Should().Be(1);
                    systemCoreLibrary.Assemblies[0].Should().Be(".NETFramework/v4.6/System.Core.dll");

                    var systemCollectionsLibrary = dependencyContext
                                                   .CompileLibraries
                                                   .FirstOrDefault(l => string.Equals(l.Name, "system.collections.reference", StringComparison.OrdinalIgnoreCase));
                    systemCollectionsLibrary.Assemblies.Count.Should().Be(1);
                    systemCollectionsLibrary.Assemblies[0].Should().Be(".NETFramework/v4.6/Facades/System.Collections.dll");
                }
            }
        }
Example #18
0
        public void It_excludes_runtime_store_packages_from_the_refs_folder()
        {
            var targetFramework = "netcoreapp2.0";

            var testAsset = _testAssetsManager
                            .CopyTestAsset("CompilationContext", "PreserveCompilationContextRefs")
                            .WithSource()
                            .WithProjectChanges((path, project) =>
            {
                if (Path.GetFileName(path).Equals("TestApp.csproj", StringComparison.OrdinalIgnoreCase))
                {
                    var ns = project.Root.Name.Namespace;

                    var targetFrameworkElement = project.Root.Elements(ns + "PropertyGroup").Elements(ns + "TargetFrameworks").Single();
                    targetFrameworkElement.SetValue(targetFramework);
                }
            })
                            .Restore(Log, "TestApp");

            var manifestFile = Path.Combine(testAsset.TestRoot, "manifest.xml");

            File.WriteAllLines(manifestFile, new[]
            {
                "<StoreArtifacts>",
                @"  <Package Id=""Newtonsoft.Json"" Version=""9.0.1"" />",
                @"  <Package Id=""System.Data.SqlClient"" Version=""4.3.0"" />",
                "</StoreArtifacts>",
            });

            var appProjectDirectory = Path.Combine(testAsset.TestRoot, "TestApp");

            var publishCommand = new PublishCommand(Log, appProjectDirectory);

            publishCommand
            .Execute($"/p:TargetFramework={targetFramework}", $"/p:TargetManifestFiles={manifestFile}")
            .Should()
            .Pass();

            var publishDirectory = publishCommand.GetOutputDirectory(targetFramework, runtimeIdentifier: "win7-x86");

            publishDirectory.Should().HaveFiles(new[] {
                "TestApp.dll",
                "TestLibrary.dll"
            });

            // excluded through TargetManifestFiles
            publishDirectory.Should().NotHaveFile("Newtonsoft.Json.dll");
            publishDirectory.Should().NotHaveFile("System.Data.SqlClient.dll");

            var refsDirectory = new DirectoryInfo(Path.Combine(publishDirectory.FullName, "refs"));

            // Should have compilation time assemblies
            refsDirectory.Should().HaveFile("System.IO.dll");
            // System.Data.SqlClient has separate compile and runtime assemblies, so the compile assembly
            // should be copied to refs even though the runtime assembly is listed in TargetManifestFiles
            refsDirectory.Should().HaveFile("System.Data.SqlClient.dll");

            // Libraries in which lib==ref should be deduped
            refsDirectory.Should().NotHaveFile("TestLibrary.dll");
            refsDirectory.Should().NotHaveFile("Newtonsoft.Json.dll");
        }
Example #19
0
        private (string coreDir, string publishDir, string immutableDir) TestConflictResult(
            Action <TestProject> testProjectChanges = null,
            Action <string> publishFolderChanges    = null,
            [CallerMemberName] string callingMethod = "")
        {
            var testProject = GetTestProject();

            testProject.SourceFiles["Program.cs"] = @"
using System;

static class Program
{
    public static void Main()
    {
        Console.WriteLine(typeof(object).Assembly.Location);
        Console.WriteLine(typeof(System.Collections.Immutable.ImmutableList).Assembly.Location);
    }
}
";
            if (testProjectChanges != null)
            {
                testProjectChanges(testProject);
            }


            var testAsset = _testAssetsManager.CreateTestProject(testProject, callingMethod: callingMethod)
                            .Restore(Log, testProject.Name);

            var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name));

            publishCommand.Execute()
            .Should()
            .Pass();

            var publishDirectory = publishCommand.GetOutputDirectory(testProject.TargetFrameworks, runtimeIdentifier: testProject.RuntimeIdentifier);

            if (publishFolderChanges != null)
            {
                publishFolderChanges(publishDirectory.FullName);
            }

            //  Assembly from package should be deployed, as it is newer than the in-box version for netcoreapp2.0,
            //  which is what the app targets
            publishDirectory.Should().HaveFile("System.Collections.Immutable.dll");

            var exePath = Path.Combine(publishDirectory.FullName, testProject.Name + ".dll");

            //  We want to test a .NET Core 2.0 app rolling forward to .NET Core 2.2.
            //  This wouldn't happen in our test environment as we also have the .NET Core 2.0 shared
            //  framework installed.  So we get the RuntimeFrameworkVersion of an app
            //  that targets .NET Core 2.1, and then use the --fx-version parameter to the host
            //  to force the .NET Core 2.0 app to run on that version
            string rollForwardVersion = GetRollForwardNetCoreAppVersion();

            var foo           = TestContext.Current.ToolsetUnderTest.CliVersionForBundledVersions;
            var runAppCommand = Command.Create(TestContext.Current.ToolsetUnderTest.DotNetHostPath,
                                               new string[] { "exec", "--fx-version", rollForwardVersion, exePath });

            var runAppResult = runAppCommand
                               .CaptureStdOut()
                               .CaptureStdErr()
                               .Execute();

            runAppResult
            .Should()
            .Pass();

            var stdOutLines = runAppResult.StdOut.Split(Environment.NewLine);

            string coreDir      = Path.GetDirectoryName(stdOutLines[0]);
            string immutableDir = Path.GetDirectoryName(stdOutLines[1]);

            return(coreDir, publishDirectory.FullName, immutableDir);
        }
        public void It_publishes_with_a_publish_profile(bool?selfContained, bool?useAppHost)
        {
            var tfm = "netcoreapp2.2";
            var rid = EnvironmentInfo.GetCompatibleRid(tfm);

            var testProject = new TestProject()
            {
                Name             = "ConsoleWithPublishProfile",
                TargetFrameworks = tfm,
                IsSdkProject     = true,
                ProjectSdk       = "Microsoft.NET.Sdk;Microsoft.NET.Sdk.Publish",
                IsExe            = true,
            };

            var testProjectInstance = _testAssetsManager.CreateTestProject(testProject);

            var projectDirectory         = Path.Combine(testProjectInstance.Path, testProject.Name);
            var publishProfilesDirectory = Path.Combine(projectDirectory, "Properties", "PublishProfiles");

            Directory.CreateDirectory(publishProfilesDirectory);

            File.WriteAllText(Path.Combine(publishProfilesDirectory, "test.pubxml"), $@"
<Project>
  <PropertyGroup>
    <RuntimeIdentifier>{rid}</RuntimeIdentifier>
    {(selfContained.HasValue ? $"<SelfContained>{selfContained}</SelfContained>" : "")}
    {((!(selfContained ?? true) && useAppHost.HasValue) ? $"<UseAppHost>{useAppHost}</UseAppHost>" : "")}
  </PropertyGroup>
</Project>
");

            var command = new PublishCommand(Log, projectDirectory);

            command
            .Execute("/restore", "/p:PublishProfile=test")
            .Should()
            .Pass();

            var output = command.GetOutputDirectory(targetFramework: tfm, runtimeIdentifier: rid);

            output.Should().HaveFiles(new[] {
                $"{testProject.Name}.dll",
                $"{testProject.Name}.pdb",
                $"{testProject.Name}.deps.json",
                $"{testProject.Name}.runtimeconfig.json",
            });

            if (selfContained ?? true)
            {
                output.Should().HaveFiles(new[] {
                    $"{FileConstants.DynamicLibPrefix}hostfxr{FileConstants.DynamicLibSuffix}",
                    $"{FileConstants.DynamicLibPrefix}hostpolicy{FileConstants.DynamicLibSuffix}",
                });
            }
            else
            {
                output.Should().NotHaveFiles(new[] {
                    $"{FileConstants.DynamicLibPrefix}hostfxr{FileConstants.DynamicLibSuffix}",
                    $"{FileConstants.DynamicLibPrefix}hostpolicy{FileConstants.DynamicLibSuffix}",
                });
            }

            if ((selfContained ?? true) || (useAppHost ?? true))
            {
                output.Should().HaveFile($"{testProject.Name}{Constants.ExeSuffix}");
            }
            else
            {
                output.Should().NotHaveFile($"{testProject.Name}{Constants.ExeSuffix}");
            }
        }
Example #21
0
        public void StaticWebAssets_BackCompatibilityPublish_Hosted_Works()
        {
            // Arrange
            var testAppName = "BlazorHosted";

            ProjectDirectory = CreateAspNetSdkTestAsset(testAppName);

            ProjectDirectory.WithProjectChanges((project, document) =>
            {
                if (Path.GetFileNameWithoutExtension(project) == "blazorwasm")
                {
                    document.Descendants("TargetFramework").Single().ReplaceNodes("net5");
                }
                if (Path.GetFileNameWithoutExtension(project) == "RazorClassLibrary")
                {
                    document.Descendants("TargetFramework").Single().ReplaceNodes("netstandard2.1");
                    document.Descendants("PropertyGroup").First().Add(new XElement("RazorLangVersion", "3.0"));
                }
                if (Path.GetFileNameWithoutExtension(project) == "classlibrarywithsatelliteassemblies")
                {
                    document.Descendants("TargetFramework").Single().ReplaceNodes("netstandard2.1");
                    document.Descendants("PropertyGroup").First().Add(new XElement("RazorLangVersion", "3.0"));
                }
            });

            // Check that static web assets is correctly configured by setting up a css file to triger css isolation.
            // The list of publish files should not include bundle.scp.css and should include blazorwasm.styles.css
            File.WriteAllText(Path.Combine(ProjectDirectory.TestRoot, "blazorwasm", "App.razor.css"), "h1 { font-size: 16px; }");

            var publish = new PublishCommand(ProjectDirectory, "blazorhosted");

            publish.WithWorkingDirectory(ProjectDirectory.TestRoot);
            var publishResult = publish.Execute("/bl");

            publishResult.Should().Pass();

            var publishPath            = publish.GetOutputDirectory(DefaultTfm).ToString();
            var intermediateOutputPath = publish.GetIntermediateDirectory(DefaultTfm, "Debug").ToString();

            // GenerateStaticWebAssetsManifest should generate the manifest file.
            var path = Path.Combine(intermediateOutputPath, "staticwebassets.publish.json");

            new FileInfo(path).Should().Exist();
            var manifest = StaticWebAssetsManifest.FromJsonBytes(File.ReadAllBytes(path));

            // We have to special case this test given we are forcing `blazorwasm` to be a `net5` project above.
            // Given this, the `dotnet.*.js` file produced will be a dotnet.5.*.*.js file in line with the TFM and not the SDK (which is .NET 6 or beyond).
            // This conflicts with our assumptions throughout the rest of the test suite that the SDK version matches the TFM.
            // To minimize special casing throughout the entire test suite, we just update this particular test's assets to reflect the SDK version.
            var numFilesUpdated      = 0;
            var frameworkFolder      = Path.Combine(publishPath, "wwwroot", "_framework");
            var frameworkFolderFiles = Directory.GetFiles(frameworkFolder, "*", new EnumerationOptions {
                RecurseSubdirectories = false
            });

            foreach (var f in frameworkFolderFiles)
            {
                if (Regex.Match(f, DotNet5JSRegexPattern).Success)
                {
                    File.Move(f, Regex.Replace(f, DotNet5JSRegexPattern, DotNet5JSTemplate));
                    numFilesUpdated++;
                }
            }
            Assert.Equal(3, numFilesUpdated);

            AssertManifest(manifest, LoadPublishManifest());

            AssertPublishAssets(
                StaticWebAssetsManifest.FromJsonBytes(File.ReadAllBytes(path)),
                publishPath,
                intermediateOutputPath);
        }
Example #22
0
        public void User_can_move_file_before_bundling()
        {
            var testProject = new TestProject()
            {
                Name             = "SingleFileTest",
                TargetFrameworks = ToolsetInfo.CurrentTargetFramework,
                IsExe            = true,
            };

            testProject.AdditionalProperties.Add("SelfContained", "true");

            var testAsset = _testAssetsManager.CreateTestProject(testProject)
                            .WithProjectChanges(project => VerifyPrepareForBundle(project));

            var publishCommand = new PublishCommand(testAsset);

            publishCommand
            .Execute(PublishSingleFile, RuntimeIdentifier)
            .Should()
            .Pass();

            void VerifyPrepareForBundle(XDocument project)
            {
                var ns         = project.Root.Name.Namespace;
                var targetName = "CheckPrepareForBundleData";

                var target = new XElement(ns + "Target",
                                          new XAttribute("Name", targetName),
                                          new XAttribute("BeforeTargets", "GenerateSingleFileBundle"),
                                          new XAttribute("DependsOnTargets", "PrepareForBundle"));

                project.Root.Add(target);

                // Rename SingleFileTest.dll --> SingleFileTest.dll.renamed
                //
                //     <Move
                //         SourceFiles="@(FilesToBundle)"
                //         DestinationFiles="@(FilesToBundle->'%(FullPath).renamed')"
                //         Condition = "'%(FilesToBundle.RelativePath)' == 'SingleFileTest.dll'" />

                target.Add(
                    new XElement(ns + "Move",
                                 new XAttribute("SourceFiles", "@(FilesToBundle)"),
                                 new XAttribute("DestinationFiles", "@(FilesToBundle->'%(FullPath).renamed')"),
                                 new XAttribute("Condition", "'%(FilesToBundle.RelativePath)' == 'SingleFileTest.dll'")));

                // Modify the FilesToBundle to not have SingleFileTest.dll, so that publish could pass.
                //
                //         <ItemGroup>
                //              <FilesToBundle Remove="@(FilesToBundle)"
                //              Condition="'%(FilesToBundle.RelativePath)' == 'SingleFileTest.dll'" />
                //         </ItemGroup >
                //

                target.Add(
                    new XElement(ns + "ItemGroup",
                                 new XElement(ns + "FilesToBundle",
                                              new XAttribute("Remove", "@(FilesToBundle)"),
                                              new XAttribute("Condition", "'%(FilesToBundle.RelativePath)' == 'SingleFileTest.dll'"))));
            }
        }
        void Conflicts_are_resolved_when_publishing(bool selfContained, bool ridSpecific, [CallerMemberName] string callingMethod = "")
        {
            if (selfContained && !ridSpecific)
            {
                throw new ArgumentException("Self-contained apps must be rid specific");
            }

            var targetFramework = "netcoreapp2.0";
            var rid             = ridSpecific ? EnvironmentInfo.GetCompatibleRid(targetFramework) : null;

            TestProject testProject = new TestProject()
            {
                Name = selfContained ? "SelfContainedWithConflicts" :
                       (ridSpecific ? "RidSpecificSharedConflicts" : "PortableWithConflicts"),
                IsSdkProject      = true,
                TargetFrameworks  = targetFramework,
                RuntimeIdentifier = rid,
                IsExe             = true,
            };

            string outputMessage = $"Hello from {testProject.Name}!";

            testProject.SourceFiles["Program.cs"] = @"
using System;
public static class Program
{
    public static void Main()
    {
        TestConflictResolution();
        Console.WriteLine(""" + outputMessage + @""");
    }
" + ConflictResolutionAssets.ConflictResolutionTestMethod + @"
}
";
            var testProjectInstance = _testAssetsManager.CreateTestProject(testProject, testProject.Name)
                                      .WithProjectChanges(p =>
            {
                var ns = p.Root.Name.Namespace;

                var itemGroup = new XElement(ns + "ItemGroup");
                p.Root.Add(itemGroup);

                foreach (var dependency in ConflictResolutionAssets.ConflictResolutionDependencies)
                {
                    itemGroup.Add(new XElement(ns + "PackageReference",
                                               new XAttribute("Include", dependency.Item1),
                                               new XAttribute("Version", dependency.Item2)));
                }

                if (!selfContained && ridSpecific)
                {
                    var propertyGroup = new XElement(ns + "PropertyGroup");
                    p.Root.Add(propertyGroup);

                    propertyGroup.Add(new XElement(ns + "SelfContained",
                                                   "false"));
                }
            })
                                      .Restore(Log, testProject.Name);

            var publishCommand = new PublishCommand(Log, Path.Combine(testProjectInstance.TestRoot, testProject.Name));
            var publishResult  = publishCommand.Execute();

            publishResult.Should().Pass();

            var publishDirectory = publishCommand.GetOutputDirectory(
                targetFramework: targetFramework,
                runtimeIdentifier: rid ?? string.Empty);

            DependencyContext dependencyContext;

            using (var depsJsonFileStream = File.OpenRead(Path.Combine(publishDirectory.FullName, $"{testProject.Name}.deps.json")))
            {
                dependencyContext = new DependencyContextJsonReader().Read(depsJsonFileStream);
            }

            dependencyContext.Should()
            .HaveNoDuplicateRuntimeAssemblies(rid ?? "")
            .And
            .HaveNoDuplicateNativeAssets(rid ?? "")
            .And
            .OnlyHavePackagesWithPathProperties();

            ICommand runCommand;

            if (selfContained)
            {
                var selfContainedExecutable = testProject.Name + Constants.ExeSuffix;

                string selfContainedExecutableFullPath = Path.Combine(publishDirectory.FullName, selfContainedExecutable);

                var libPrefix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "" : "lib";

                publishDirectory.Should().HaveFiles(new[] {
                    selfContainedExecutable,
                    $"{testProject.Name}.dll",
                    $"{testProject.Name}.pdb",
                    $"{testProject.Name}.deps.json",
                    $"{testProject.Name}.runtimeconfig.json",
                    $"{libPrefix}coreclr{FileConstants.DynamicLibSuffix}",
                    $"{libPrefix}hostfxr{FileConstants.DynamicLibSuffix}",
                    $"{libPrefix}hostpolicy{FileConstants.DynamicLibSuffix}",
                    $"mscorlib.dll",
                    $"System.Private.CoreLib.dll",
                });

                dependencyContext.Should()
                .OnlyHaveRuntimeAssembliesWhichAreInFolder(rid, publishDirectory.FullName)
                .And
                .OnlyHaveNativeAssembliesWhichAreInFolder(rid, publishDirectory.FullName, testProject.Name);

                runCommand = Command.Create(selfContainedExecutableFullPath, new string[] { });
            }
            else
            {
                publishDirectory.Should().OnlyHaveFiles(new[] {
                    $"{testProject.Name}.dll",
                    $"{testProject.Name}.pdb",
                    $"{testProject.Name}.deps.json",
                    $"{testProject.Name}.runtimeconfig.json"
                });

                dependencyContext.Should()
                .OnlyHaveRuntimeAssemblies(rid ?? "", testProject.Name);

                runCommand = Command.Create(TestContext.Current.ToolsetUnderTest.DotNetHostPath, new[] { Path.Combine(publishDirectory.FullName, $"{testProject.Name}.dll") });
            }

            runCommand
            .CaptureStdOut()
            .Execute()
            .Should()
            .Pass()
            .And
            .HaveStdOutContaining(outputMessage);
        }
Example #24
0
        private void TestProjectPublishing_Internal(string projectName,
                                                    string targetFramework,
                                                    bool makeExeProject    = true,
                                                    bool isSelfContained   = true,
                                                    bool emitNativeSymbols = false,
                                                    bool useCrossgen2      = false,
                                                    bool composite         = true,
                                                    [CallerMemberName] string callingMethod = "",
                                                    string identifier        = null,
                                                    string runtimeIdentifier = null)
        {
            var testProject = CreateTestProjectForR2RTesting(
                targetFramework,
                projectName,
                "ClassLib",
                isExeProject: makeExeProject,
                runtimeIdentifier: runtimeIdentifier);

            testProject.AdditionalProperties["PublishReadyToRun"]             = "True";
            testProject.AdditionalProperties["PublishReadyToRunEmitSymbols"]  = emitNativeSymbols ? "True" : "False";
            testProject.AdditionalProperties["PublishReadyToRunUseCrossgen2"] = useCrossgen2 ? "True" : "False";
            testProject.AdditionalProperties["PublishReadyToRunComposite"]    = composite ? "True" : "False";
            testProject.AdditionalProperties["SelfContained"] = isSelfContained ? "True" : "False";

            var testProjectInstance = _testAssetsManager.CreateTestProject(testProject, callingMethod, identifier);

            var publishCommand = new PublishCommand(testProjectInstance);

            publishCommand.Execute().Should().Pass();

            DirectoryInfo publishDirectory = publishCommand.GetOutputDirectory(
                targetFramework,
                "Debug",
                testProject.RuntimeIdentifier);

            var mainProjectDll = Path.Combine(publishDirectory.FullName, $"{projectName}.dll");
            var classLibDll    = Path.Combine(publishDirectory.FullName, $"ClassLib.dll");

            DoesImageHaveR2RInfo(mainProjectDll).Should().BeTrue();
            DoesImageHaveR2RInfo(classLibDll).Should().BeTrue();

            if (isSelfContained)
            {
                publishDirectory.Should().HaveFile("System.Private.CoreLib.dll");
            }
            else
            {
                publishDirectory.Should().NotHaveFile("System.Private.CoreLib.dll");
            }

            if (emitNativeSymbols && !IsTargetOsOsX(testProject.RuntimeIdentifier))
            {
                NuGetFramework framework = NuGetFramework.Parse(targetFramework);
                Log.WriteLine("Checking for symbol files");
                IEnumerable <string> pdbFiles;

                if (composite)
                {
                    pdbFiles = new[] { GetPDBFileName(Path.ChangeExtension(mainProjectDll, "r2r.dll"), framework, testProject.RuntimeIdentifier) };
                }
                else
                {
                    pdbFiles = new[] {
                        GetPDBFileName(mainProjectDll, framework, testProject.RuntimeIdentifier),
                        GetPDBFileName(classLibDll, framework, testProject.RuntimeIdentifier),
                    };
                }

                foreach (string s in pdbFiles)
                {
                    Log.WriteLine($"{publishDirectory.FullName} {s}");
                }

                publishDirectory.Should().HaveFiles(pdbFiles);
            }
        }
Example #25
0
        private void PushPackage(string packagePath, string source, string apiKey)
        {
            var gallery = new GalleryServer(source);

            // Push the package to the server
            var package = new ZipPackage(packagePath);

            bool complete = false;
            gallery.ProgressAvailable += (sender, e) =>
            {
                Console.Write("\r" + "Pushing: {0}", e.PercentComplete);

                if (e.PercentComplete == 100)
                {
                    Console.WriteLine();
                    complete = true;
                }
            };

            Console.WriteLine("Pushing {0} to {1}", package.GetFullName(), _sourceProvider.GetDisplayName(source));

            try
            {
                using (Stream stream = package.GetStream())
                {
                    gallery.CreatePackage(apiKey, stream);
                }
            }
            catch
            {
                if (!complete)
                {
                    Console.WriteLine();
                }
                throw;
            }

            // Publish the package on the server

            var cmd = new PublishCommand(_sourceProvider);
            cmd.Console = Console;
            cmd.Source = source;
            cmd.Arguments = new List<string>
                                {
                                    package.Id,
                                    package.Version.ToString(),
                                    apiKey
                                };
            cmd.Execute();
        }
        public void Publish_standalone_post_netcoreapp2_app_and_it_should_run()
        {
            var targetFramework = "netcoreapp2.0";
            var rid             = EnvironmentInfo.GetCompatibleRid(targetFramework);

            TestProject testProject = new TestProject()
            {
                Name              = "Hello",
                IsSdkProject      = true,
                TargetFrameworks  = targetFramework,
                RuntimeIdentifier = rid,
                IsExe             = true,
            };


            testProject.SourceFiles["Program.cs"] = @"
using System;
public static class Program
{
    public static void Main()
    {
        Console.WriteLine(""Hello from a netcoreapp2.0.!"");
    }
}
";
            var testProjectInstance = _testAssetsManager.CreateTestProject(testProject);

            testProjectInstance.Restore(Log, testProject.Name);
            var publishCommand = new PublishCommand(Log, Path.Combine(testProjectInstance.TestRoot, testProject.Name));
            var publishResult  = publishCommand.Execute();

            publishResult.Should().Pass();

            var publishDirectory = publishCommand.GetOutputDirectory(
                targetFramework: targetFramework,
                runtimeIdentifier: rid);
            var selfContainedExecutable = $"Hello{Constants.ExeSuffix}";

            string selfContainedExecutableFullPath = Path.Combine(publishDirectory.FullName, selfContainedExecutable);

            publishDirectory.Should().HaveFiles(new[] {
                selfContainedExecutable,
                "Hello.dll",
                "Hello.pdb",
                "Hello.deps.json",
                "Hello.runtimeconfig.json",
                $"{FileConstants.DynamicLibPrefix}coreclr{FileConstants.DynamicLibSuffix}",
                $"{FileConstants.DynamicLibPrefix}hostfxr{FileConstants.DynamicLibSuffix}",
                $"{FileConstants.DynamicLibPrefix}hostpolicy{FileConstants.DynamicLibSuffix}",
                $"mscorlib.dll",
                $"System.Private.CoreLib.dll",
            });

            Command.Create(selfContainedExecutableFullPath, new string[] { })
            .CaptureStdOut()
            .Execute()
            .Should()
            .Pass()
            .And
            .HaveStdOutContaining("Hello from a netcoreapp2.0.!");
        }
        public void It_publishes_with_a_publish_profile(bool?publishSingleFile)
        {
            var tfm = "netcoreapp3.1";
            var rid = EnvironmentInfo.GetCompatibleRid(tfm);

            var testProject = new TestProject()
            {
                Name             = "ConsoleWithPublishProfile",
                TargetFrameworks = tfm,
                ProjectSdk       = "Microsoft.NET.Sdk;Microsoft.NET.Sdk.Publish",
                IsExe            = true,
            };

            testProject.PackageReferences.Add(new TestPackageReference("NewtonSoft.Json", "9.0.1"));

            var testProjectInstance = _testAssetsManager.CreateTestProject(testProject);

            var projectDirectory         = Path.Combine(testProjectInstance.Path, testProject.Name);
            var publishProfilesDirectory = Path.Combine(projectDirectory, "Properties", "PublishProfiles");

            Directory.CreateDirectory(publishProfilesDirectory);

            File.WriteAllText(Path.Combine(publishProfilesDirectory, "test.pubxml"), $@"
<Project>
  <PropertyGroup>
    <PublishUrl>publish\</PublishUrl>
    <Install>true</Install>
    <InstallFrom>Disk</InstallFrom>
    <ApplicationRevision>4</ApplicationRevision>
    <ApplicationVersion>1.2.3.*</ApplicationVersion>
    <PublishProtocol>ClickOnce</PublishProtocol>
    <BootstrapperEnabled>True</BootstrapperEnabled>
    <UpdateEnabled>False</UpdateEnabled>
    <IsWebBootstrapper>false</IsWebBootstrapper>
    <CreateWebPageOnPublish>true</CreateWebPageOnPublish>
    <GenerateManifests>true</GenerateManifests>
    <PublishWizardCompleted>true</PublishWizardCompleted>
    <SelfContained>false</SelfContained>
    {(publishSingleFile.HasValue ? $"<PublishSingleFile>{publishSingleFile}</PublishSingleFile>" : "")}
    {(publishSingleFile ?? false ? $"<RuntimeIdentifier>{rid}</RuntimeIdentifier>" : "")}
  </PropertyGroup>
</Project>
");

            var command = new PublishCommand(testProjectInstance);

            command
            .Execute("/p:PublishProfile=test")
            .Should()
            .Pass();

            DirectoryInfo output = null;

            if (publishSingleFile ?? false)
            {
                output = command.GetOutputDirectory(targetFramework: tfm, runtimeIdentifier: rid);
            }
            else
            {
                output = command.GetOutputDirectory(targetFramework: tfm);
            }
            output = output.Parent;

            output.Should().HaveFiles(new[] {
                $"app.Publish\\setup.exe",
                $"app.Publish\\{testProject.Name}.application",
                $"app.Publish\\application files\\{testProject.Name}_1_2_3_4\\launcher{Constants.ExeSuffix}",
            });

            if (publishSingleFile ?? false)
            {
                output.Should().HaveFiles(new[] {
                    $"app.Publish\\application files\\{testProject.Name}_1_2_3_4\\{testProject.Name}{Constants.ExeSuffix}",
                    $"app.Publish\\application files\\{testProject.Name}_1_2_3_4\\{testProject.Name}.dll.manifest",
                });
                output.Should().NotHaveFiles(new[] {
                    $"app.Publish\\application files\\{testProject.Name}_1_2_3_4\\{testProject.Name}.dll",
                    $"app.Publish\\application files\\{testProject.Name}_1_2_3_4\\Newtonsoft.Json.dll",
                    $"app.Publish\\application files\\{testProject.Name}_1_2_3_4\\{testProject.Name}.deps.json",
                });
            }
            else
            {
                output.Should().HaveFiles(new[] {
                    $"app.Publish\\application files\\{testProject.Name}_1_2_3_4\\{testProject.Name}.dll",
                    $"app.Publish\\application files\\{testProject.Name}_1_2_3_4\\{testProject.Name}.dll.manifest",
                    $"app.Publish\\application files\\{testProject.Name}_1_2_3_4\\Newtonsoft.Json.dll",
                    $"app.Publish\\application files\\{testProject.Name}_1_2_3_4\\{testProject.Name}.deps.json",
                    $"app.Publish\\application files\\{testProject.Name}_1_2_3_4\\{testProject.Name}.runtimeconfig.json",
                    $"app.Publish\\application files\\{testProject.Name}_1_2_3_4\\{testProject.Name}{Constants.ExeSuffix}",
                });
            }
        }
Example #28
0
        public void It_appends_rid_to_outdir_correctly(string identifier, string rid, bool useAppendOption, bool shouldAppend)
        {
            foreach (bool multiTarget in new[] { false, true })
            {
                var testAsset = _testAssetsManager
                                .CopyTestAsset("DesktopMinusRid", identifier: Path.DirectorySeparatorChar + identifier + (multiTarget ? "Multi" : ""))
                                .WithSource()
                                .WithProjectChanges(project =>
                {
                    var ns            = project.Root.Name.Namespace;
                    var propertyGroup = project.Root.Elements(ns + "PropertyGroup").First();
                    propertyGroup.Add(new XElement(ns + "RuntimeIdentifier", rid));
                    propertyGroup.Add(new XElement(ns + "AppendRuntimeIdentifierToOutputPath", useAppendOption.ToString()));

                    if (multiTarget)
                    {
                        propertyGroup.Element(ns + "RuntimeIdentifier").Add(new XAttribute("Condition", "'$(TargetFramework)' == 'net46'"));
                        propertyGroup.Element(ns + "TargetFramework").Remove();
                        propertyGroup.Add(new XElement(ns + "TargetFrameworks", "net46;netcoreapp1.1"));
                    }
                })
                                .Restore(Log);

                var buildCommand = new BuildCommand(Log, testAsset.TestRoot);
                buildCommand
                .Execute()
                .Should()
                .Pass();

                var publishCommand = new PublishCommand(Log, testAsset.TestRoot);
                publishCommand
                .Execute(multiTarget ? new[] { "/p:TargetFramework=net46" } : Array.Empty <string>())
                .Should()
                .Pass();

                string expectedOutput;
                switch (rid)
                {
                case "":
                    expectedOutput = "Native code was not used (MSIL)";
                    break;

                case "win7-x86":
                    expectedOutput = "Native code was not used (X86)";
                    break;

                case "win7-x64":
                    expectedOutput = "Native code was not used (Amd64)";
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(rid));
                }

                var outputDirectory  = buildCommand.GetOutputDirectory("net46", runtimeIdentifier: shouldAppend ? rid : "");
                var publishDirectory = publishCommand.GetOutputDirectory("net46", runtimeIdentifier: rid);

                foreach (var directory in new[] { outputDirectory, publishDirectory })
                {
                    var exe = Path.Combine(directory.FullName, "DesktopMinusRid.exe");

                    var runCommand = Command.Create(exe, Array.Empty <string>());
                    runCommand
                    .CaptureStdOut()
                    .Execute()
                    .Should()
                    .Pass()
                    .And
                    .HaveStdOutContaining(expectedOutput);
                }
            }
        }
        public void PublishWebAppWithPublishProfile(bool?selfContained, bool?useAppHost)
        {
            var tfm = "netcoreapp2.2";
            var rid = EnvironmentInfo.GetCompatibleRid(tfm);

            var testProject = new TestProject()
            {
                Name             = "WebWithPublishProfile",
                TargetFrameworks = tfm,
                ProjectSdk       = "Microsoft.NET.Sdk.Web",
                IsExe            = true,
            };

            testProject.AdditionalProperties.Add("AspNetCoreHostingModel", "InProcess");
            testProject.PackageReferences.Add(new TestPackageReference("Microsoft.AspNetCore.App"));
            testProject.PackageReferences.Add(new TestPackageReference("Microsoft.AspNetCore.Razor.Design", version: "2.2.0", privateAssets: "all"));

            var identifier          = (selfContained == null ? "null" : selfContained.ToString()) + (useAppHost == null ? "null" : useAppHost.ToString());
            var testProjectInstance = _testAssetsManager.CreateTestProject(testProject, identifier: identifier);

            var projectDirectory         = Path.Combine(testProjectInstance.Path, testProject.Name);
            var publishProfilesDirectory = Path.Combine(projectDirectory, "Properties", "PublishProfiles");

            Directory.CreateDirectory(publishProfilesDirectory);

            File.WriteAllText(Path.Combine(publishProfilesDirectory, "test.pubxml"), $@"
<Project>
  <PropertyGroup>
    <RuntimeIdentifier>{rid}</RuntimeIdentifier>
    {(selfContained.HasValue ? $"<SelfContained>{selfContained}</SelfContained>" : "")}
    {((!(selfContained ?? true) && useAppHost.HasValue) ? $"<UseAppHost>{useAppHost}</UseAppHost>" : "")}
  </PropertyGroup>
</Project>
");

            var command = new PublishCommand(testProjectInstance);

            command
            .Execute("/p:PublishProfile=test")
            .Should()
            .Pass();

            var output = command.GetOutputDirectory(targetFramework: tfm, runtimeIdentifier: rid);

            output.Should().HaveFiles(new[] {
                $"{testProject.Name}.dll",
                $"{testProject.Name}.pdb",
                $"{testProject.Name}.deps.json",
                $"{testProject.Name}.runtimeconfig.json",
                "web.config",
            });

            if (selfContained ?? true)
            {
                output.Should().HaveFiles(new[] {
                    $"{FileConstants.DynamicLibPrefix}hostfxr{FileConstants.DynamicLibSuffix}",
                    $"{FileConstants.DynamicLibPrefix}hostpolicy{FileConstants.DynamicLibSuffix}",
                });
            }
            else
            {
                output.Should().NotHaveFiles(new[] {
                    $"{FileConstants.DynamicLibPrefix}hostfxr{FileConstants.DynamicLibSuffix}",
                    $"{FileConstants.DynamicLibPrefix}hostpolicy{FileConstants.DynamicLibSuffix}",
                });
            }

            if ((selfContained ?? true) || (useAppHost ?? true))
            {
                output.Should().HaveFile($"{testProject.Name}{Constants.ExeSuffix}");
            }
            else
            {
                output.Should().NotHaveFile($"{testProject.Name}{Constants.ExeSuffix}");
            }
        }
 private DirectoryInfo GetPublishDirectory(PublishCommand publishCommand, string targetFramework = "net5.0")
 {
     return(publishCommand.GetOutputDirectory(targetFramework: targetFramework,
                                              runtimeIdentifier: RuntimeInformation.RuntimeIdentifier));
 }
Example #31
0
        public void When_TargetPlatformVersion_is_set_higher_than_10_It_can_reference_cswinrt_api()
        {
            const string ProjectName = "WindowsDesktopSdkTest_without_ProjectSdk_set";

            const string tfm = "net5.0";

            var testProject = new TestProject()
            {
                Name             = ProjectName,
                TargetFrameworks = tfm,
                IsWinExe         = true,
            };

            testProject.SourceFiles.Add("Program.cs", _useCsWinrtApi);
            testProject.AdditionalProperties.Add("TargetPlatformIdentifier", "Windows");
            testProject.AdditionalProperties.Add("TargetPlatformVersion", "10.0.17763");

            var asset = _testAssetsManager.CreateTestProject(testProject);

            var buildCommand = new BuildCommand(Log, Path.Combine(asset.Path, ProjectName));

            buildCommand.Execute()
            .Should()
            .Pass();

            void Assert(DirectoryInfo outputDir)
            {
                outputDir.File("Microsoft.Windows.SDK.NET.dll").Exists.Should().BeTrue("The output has cswinrt dll");
                outputDir.File("WinRT.Runtime.dll").Exists.Should().BeTrue("The output has cswinrt dll");
                var runtimeconfigjson = File.ReadAllText(outputDir.File(ProjectName + ".runtimeconfig.json").FullName);

                runtimeconfigjson.Contains(@"""name"": ""Microsoft.NETCore.App""").Should().BeTrue("runtimeconfig.json only reference Microsoft.NETCore.App");
                runtimeconfigjson.Contains("Microsoft.Windows.SDK.NET").Should().BeFalse("runtimeconfig.json does not reference windows SDK");
            }

            Assert(buildCommand.GetOutputDirectory(tfm));

            var publishCommand    = new PublishCommand(asset);
            var runtimeIdentifier = "win-x64";

            publishCommand.Execute("-p:SelfContained=true", $"-p:RuntimeIdentifier={runtimeIdentifier}")
            .Should()
            .Pass();

            Assert(publishCommand.GetOutputDirectory(tfm, runtimeIdentifier: runtimeIdentifier));

            var command = new GetValuesCommand(
                Log,
                Path.Combine(asset.Path, testProject.Name),
                testProject.TargetFrameworks,
                "FilesCopiedToPublishDir",
                GetValuesCommand.ValueType.Item)
            {
                DependsOnTargets = "ComputeFilesCopiedToPublishDir",
                MetadataNames    = { "RelativePath" },
            };

            command.Execute().Should().Pass();
            var items = from item in command.GetValuesWithMetadata()
                        select new
            {
                Identity     = item.value,
                RelativePath = item.metadata["RelativePath"]
            };

            items
            .Should().Contain(i => i.RelativePath == "Microsoft.Windows.SDK.NET.dll" && Path.GetFileName(i.Identity) == "Microsoft.Windows.SDK.NET.dll",
                              because: "wapproj should copy cswinrt dlls");
            items
            .Should()
            .Contain(i => i.RelativePath == "WinRT.Runtime.dll" && Path.GetFileName(i.Identity) == "WinRT.Runtime.dll",
                     because: "wapproj should copy cswinrt dlls");

            // ready to run is supported
            publishCommand.Execute("-p:SelfContained=true", $"-p:RuntimeIdentifier={runtimeIdentifier}", $"-p:PublishReadyToRun=true")
            .Should()
            .Pass();

            // PublishSingleFile is supported
            publishCommand.Execute("-p:SelfContained=true", $"-p:RuntimeIdentifier={runtimeIdentifier}", $"-p:PublishSingleFile=true")
            .Should()
            .Pass();
        }