diff --git a/src/BenchmarkDotNet/Toolchains/CsProj/CsProjGenerator.cs b/src/BenchmarkDotNet/Toolchains/CsProj/CsProjGenerator.cs index 8de5a140e5..74a3016e86 100644 --- a/src/BenchmarkDotNet/Toolchains/CsProj/CsProjGenerator.cs +++ b/src/BenchmarkDotNet/Toolchains/CsProj/CsProjGenerator.cs @@ -35,8 +35,13 @@ public CsProjGenerator(string targetFrameworkMoniker, string cliPath, string pac protected override string GetBuildArtifactsDirectoryPath(BuildPartition buildPartition, string programName) { - string directoryName = Path.GetDirectoryName(buildPartition.AssemblyLocation) - ?? throw new DirectoryNotFoundException(buildPartition.AssemblyLocation); + string assemblyLocation = buildPartition.AssemblyLocation; + + //Assembles loaded from a stream will have an empty location (https://docs.microsoft.com/en-us/dotnet/api/system.reflection.assembly.location). + string directoryName = assemblyLocation.IsEmpty() ? + Path.Combine(Directory.GetCurrentDirectory(), "BenchmarkDotNet.Bin") : + Path.GetDirectoryName(buildPartition.AssemblyLocation); + return Path.Combine(directoryName, programName); } diff --git a/tests/BenchmarkDotNet.Tests/CsProjGeneratorTests.cs b/tests/BenchmarkDotNet.Tests/CsProjGeneratorTests.cs index 12b5e2f7b4..f2c817fd8f 100644 --- a/tests/BenchmarkDotNet.Tests/CsProjGeneratorTests.cs +++ b/tests/BenchmarkDotNet.Tests/CsProjGeneratorTests.cs @@ -1,7 +1,15 @@ using System.IO; +using System.Linq; +using System.Reflection; +using BenchmarkDotNet.Characteristics; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Jobs; +using BenchmarkDotNet.Running; +using BenchmarkDotNet.Tests.Mocks; using BenchmarkDotNet.Toolchains.CsProj; using JetBrains.Annotations; using Xunit; +using BenchmarkDotNet.Extensions; namespace BenchmarkDotNet.Tests { @@ -140,5 +148,63 @@ public void SettingsFromPropsFileImportedUsingRelativePathGetCopies() File.Delete(propsFilePath); } + + [Fact] + public void TheDefaultFilePathShouldBeUsedWhenAnAssemblyLocationIsEmpty() + { + const string programName = "testProgram"; + var config = ManualConfig.CreateEmpty().CreateImmutableConfig(); + var benchmarkMethod = + typeof(MockFactory.MockBenchmarkClass) + .GetTypeInfo() + .GetMethods() + .Single(method => method.Name == nameof(MockFactory.MockBenchmarkClass.Foo)); + + + //Simulate loading an assembly from a stream + var benchmarkDotNetAssembly = typeof(MockFactory.MockBenchmarkClass).GetTypeInfo().Assembly; + var streamLoadedAssembly = Assembly.Load(File.ReadAllBytes(benchmarkDotNetAssembly.Location)); + var assemblyType = streamLoadedAssembly.GetRunnableBenchmarks().Select(type => type).FirstOrDefault(); + + var target = new Descriptor(assemblyType, benchmarkMethod); + var benchmarkCase = BenchmarkCase.Create(target, Job.Default, null, config); + + var benchmarks = new[] { new BenchmarkBuildInfo(benchmarkCase, config.CreateImmutableConfig(), 999) }; + var projectGenerator = new SteamLoadedBuildPartition("netcoreapp3.0", null, null, null); + string binariesPath = projectGenerator.ResolvePathForBinaries(new BuildPartition(benchmarks, new Resolver()), programName); + + string expectedPath = Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), "BenchmarkDotNet.Bin"), programName); + Assert.Equal(expectedPath, binariesPath); + } + + [Fact] + public void TestAssemblyFilePathIsUsedWhenTheAssemblyLocationIsNotEmpty() + { + const string programName = "testProgram"; + var benchmarkMethod = + typeof(MockFactory.MockBenchmarkClass) + .GetTypeInfo() + .GetMethods() + .Single(method => method.Name == nameof(MockFactory.MockBenchmarkClass.Foo)); + var target = new Descriptor(typeof(MockFactory.MockBenchmarkClass), benchmarkMethod); + var benchmarkCase = BenchmarkCase.Create(target, Job.Default, null, ManualConfig.CreateEmpty().CreateImmutableConfig()); + var benchmarks = new[] { new BenchmarkBuildInfo(benchmarkCase, ManualConfig.CreateEmpty().CreateImmutableConfig(), 0) }; + var projectGenerator = new SteamLoadedBuildPartition("netcoreapp3.0", null, null, null); + var buildPartition = new BuildPartition(benchmarks, new Resolver()); + string binariesPath = projectGenerator.ResolvePathForBinaries(buildPartition, programName); + + string expectedPath = Path.Combine(Path.GetDirectoryName(buildPartition.AssemblyLocation), programName); + Assert.Equal(expectedPath, binariesPath); + } + + private class SteamLoadedBuildPartition : CsProjGenerator + { + internal string ResolvePathForBinaries(BuildPartition buildPartition, string programName) + { + return base.GetBuildArtifactsDirectoryPath(buildPartition, programName); + } + + public SteamLoadedBuildPartition(string targetFrameworkMoniker, string cliPath, string packagesPath, string runtimeFrameworkVersion) : base(targetFrameworkMoniker, cliPath, packagesPath, runtimeFrameworkVersion) { } + } } -} \ No newline at end of file +}