diff --git a/CycloneDX.Tests/CycloneDX.Tests.csproj b/CycloneDX.Tests/CycloneDX.Tests.csproj
index 47a8424c..c6bf58f8 100644
--- a/CycloneDX.Tests/CycloneDX.Tests.csproj
+++ b/CycloneDX.Tests/CycloneDX.Tests.csproj
@@ -48,6 +48,9 @@
Always
+
+ Always
+
Always
diff --git a/CycloneDX.Tests/FunctionalTests/FunctionalTestHelper.cs b/CycloneDX.Tests/FunctionalTests/FunctionalTestHelper.cs
index 81b401c6..f2efb0c5 100644
--- a/CycloneDX.Tests/FunctionalTests/FunctionalTestHelper.cs
+++ b/CycloneDX.Tests/FunctionalTests/FunctionalTestHelper.cs
@@ -99,14 +99,14 @@ public static async Task Test(RunOptions options, INugetServiceFactory nuge
}
else
{
- validationResult = Xml.Validator.Validate(mockBomFileStream, SpecificationVersion.v1_5);
+ validationResult = Xml.Validator.Validate(mockBomFileStream, SpecificationVersion.v1_5);
}
Assert.True(validationResult.Valid);
return runner.LastGeneratedBom;
}
- private const string CsprojContents =
+ public const string CsprojContents =
"\n\n " +
"\n " +
"Exe\n " +
diff --git a/CycloneDX.Tests/FunctionalTests/MetaData.cs b/CycloneDX.Tests/FunctionalTests/MetaData.cs
new file mode 100644
index 00000000..643d7995
--- /dev/null
+++ b/CycloneDX.Tests/FunctionalTests/MetaData.cs
@@ -0,0 +1,136 @@
+using System;
+using System.Collections.Generic;
+using System.CommandLine;
+using System.IO;
+using System.IO.Abstractions;
+using System.IO.Abstractions.TestingHelpers;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CycloneDX.Models;
+using Xunit;
+
+namespace CycloneDX.Tests.FunctionalTests
+{
+ public class MetaData
+ {
+ private MockFileSystem getMockFS()
+ {
+ return new MockFileSystem(new Dictionary
+ {
+ { MockUnixSupport.Path("c:/ProjectPath/obj/project.assets.json"),
+ new MockFileData(
+ File.ReadAllText(Path.Combine("FunctionalTests", "TestcaseFiles", "SimpleNET6.0Library.json"))) },
+ { MockUnixSupport.Path("c:/ProjectPath/Project.csproj"), new MockFileData(FunctionalTestHelper.CsprojContents) },
+ { MockUnixSupport.Path("c:/ProjectPath/metadata.xml"),
+ new MockFileData(
+ File.ReadAllText(Path.Combine("FunctionalTests", "TestcaseFiles", "metadata.xml"))) }
+ });
+ }
+
+ [Fact]
+ public async Task ImportedMetaDataAreInBomOutput()
+ {
+ var options = new RunOptions
+ {
+ importMetadataPath = MockUnixSupport.Path("c:/ProjectPath/metadata.xml")
+ };
+
+ var bom = await FunctionalTestHelper.Test(options, getMockFS());
+
+ Assert.Equal("CycloneDX", bom.Metadata.Component.Name);
+ Assert.Equal("1.3.0", bom.Metadata.Component.Version);
+ Assert.Equal(Component.Classification.Application, bom.Metadata.Component.Type);
+ Assert.False(string.IsNullOrEmpty(bom.Metadata.Component.Description));
+ Assert.Equal("Apache License 2.0", bom.Metadata.Component.Licenses.First().License.Name);
+ Assert.Equal("Apache-2.0", bom.Metadata.Component.Licenses.First().License.Id);
+ Assert.Equal("pkg:nuget/CycloneDX@1.3.0", bom.Metadata.Component.Purl);
+ }
+
+ [Fact]
+ public async Task IfNoMetadataIsImportedTimestampIsSetAutomatically()
+ {
+ var options = new RunOptions
+ {
+ };
+
+ var bom = await FunctionalTestHelper.Test(options, getMockFS());
+ Assert.True(bom.Metadata.Timestamp.Value > DateTime.UtcNow.AddMinutes(-10));
+ }
+
+ [Fact]
+ public async Task IfMetadataWithoutTimestampIsImportedTimestampStillGetsSet()
+ {
+ var options = new RunOptions
+ {
+ importMetadataPath = MockUnixSupport.Path("c:/ProjectPath/metadata.xml")
+ };
+
+ var bom = await FunctionalTestHelper.Test(options, getMockFS());
+ Assert.True(bom.Metadata.Timestamp.Value > DateTime.UtcNow.AddMinutes(-10));
+ }
+
+ [Fact(Skip ="Test schlägt fehl #821")]
+ public async Task SetVersionOverwritesVersionWhenMetadataAreProvided()
+ {
+ var options = new RunOptions
+ {
+ importMetadataPath = MockUnixSupport.Path("c:/ProjectPath/metadata.xml"),
+ setVersion = "3.0.4"
+
+ };
+
+ var bom = await FunctionalTestHelper.Test(options, getMockFS());
+
+ Assert.Equal("CycloneDX", bom.Metadata.Component.Name);
+ Assert.Equal("3.0.4", bom.Metadata.Component.Version);
+ Assert.Equal(Component.Classification.Application, bom.Metadata.Component.Type);
+ Assert.False(string.IsNullOrEmpty(bom.Metadata.Component.Description));
+ Assert.Equal("Apache License 2.0", bom.Metadata.Component.Licenses.First().License.Name);
+ Assert.Equal("Apache-2.0", bom.Metadata.Component.Licenses.First().License.Id);
+ Assert.Equal("pkg:nuget/CycloneDX@1.3.0", bom.Metadata.Component.Purl);
+ }
+
+ [Fact(Skip = "Test schlägt fehl #821")]
+ public async Task SetNameOverwritesNameWhenMetadataAreProvided()
+ {
+ var options = new RunOptions
+ {
+ importMetadataPath = MockUnixSupport.Path("c:/ProjectPath/metadata.xml"),
+ setName = "Foo"
+
+ };
+
+ var bom = await FunctionalTestHelper.Test(options, getMockFS());
+
+ Assert.Equal("Foo", bom.Metadata.Component.Name);
+ Assert.Equal("1.3.0", bom.Metadata.Component.Version);
+ Assert.Equal(Component.Classification.Application, bom.Metadata.Component.Type);
+ Assert.False(string.IsNullOrEmpty(bom.Metadata.Component.Description));
+ Assert.Equal("Apache License 2.0", bom.Metadata.Component.Licenses.First().License.Name);
+ Assert.Equal("Apache-2.0", bom.Metadata.Component.Licenses.First().License.Id);
+ Assert.Equal("pkg:nuget/CycloneDX@1.3.0", bom.Metadata.Component.Purl);
+ }
+
+ [Fact(Skip = "Test schlägt fehl #821")]
+ public async Task SetTypeOverwritesTypeWhenMetadataAreProvided()
+ {
+ var options = new RunOptions
+ {
+ importMetadataPath = MockUnixSupport.Path("c:/ProjectPath/metadata.xml"),
+ setType = Component.Classification.Container
+
+ };
+
+ var bom = await FunctionalTestHelper.Test(options, getMockFS());
+
+ Assert.Equal("CycloneDX", bom.Metadata.Component.Name);
+ Assert.Equal("1.3.0", bom.Metadata.Component.Version);
+ Assert.Equal(Component.Classification.Container, bom.Metadata.Component.Type);
+ Assert.False(string.IsNullOrEmpty(bom.Metadata.Component.Description));
+ Assert.Equal("Apache License 2.0", bom.Metadata.Component.Licenses.First().License.Name);
+ Assert.Equal("Apache-2.0", bom.Metadata.Component.Licenses.First().License.Id);
+ Assert.Equal("pkg:nuget/CycloneDX@1.3.0", bom.Metadata.Component.Purl);
+ }
+ }
+}
diff --git a/CycloneDX.Tests/FunctionalTests/TestcaseFiles/metadata.xml b/CycloneDX.Tests/FunctionalTests/TestcaseFiles/metadata.xml
new file mode 100644
index 00000000..cc101df3
--- /dev/null
+++ b/CycloneDX.Tests/FunctionalTests/TestcaseFiles/metadata.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ CycloneDX
+ 1.3.0
+
+
+
+
+
+ Apache License 2.0
+ Apache-2.0
+
+
+ pkg:nuget/CycloneDX@1.3.0
+
+
+
diff --git a/CycloneDX.Tests/ProgramTests.cs b/CycloneDX.Tests/ProgramTests.cs
index 7817fffd..d713f729 100755
--- a/CycloneDX.Tests/ProgramTests.cs
+++ b/CycloneDX.Tests/ProgramTests.cs
@@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.IO.Abstractions;
using System.IO.Abstractions.TestingHelpers;
using System.Threading.Tasks;
using CycloneDX.Interfaces;
@@ -95,7 +96,7 @@ public void CheckMetaDataTemplate()
{
var bom = new Bom();
string resourcePath = Path.Join(AppContext.BaseDirectory, "Resources", "metadata");
- bom = Runner.ReadMetaDataFromFile(bom, Path.Join(resourcePath, "cycloneDX-metadata-template.xml"));
+ bom = Runner.ReadMetaDataFromFile(bom, Path.Join(resourcePath, "cycloneDX-metadata-template.xml"), new FileSystem());
Assert.NotNull(bom.Metadata);
Assert.Matches("CycloneDX", bom.Metadata.Component.Name);
Assert.NotEmpty(bom.Metadata.Tools.Tools);
diff --git a/CycloneDX/Runner.cs b/CycloneDX/Runner.cs
index 1c4276fd..92a5ac7e 100644
--- a/CycloneDX/Runner.cs
+++ b/CycloneDX/Runner.cs
@@ -350,14 +350,14 @@ public async Task HandleCommandAsync(RunOptions options)
if (!string.IsNullOrEmpty(importMetadataPath))
{
- if (!File.Exists(importMetadataPath))
+ if (!fileSystem.File.Exists(importMetadataPath))
{
Console.Error.WriteLine($"Metadata template '{importMetadataPath}' does not exist.");
return (int)ExitCode.InvalidOptions;
}
else
{
- bom = ReadMetaDataFromFile(bom, importMetadataPath);
+ bom = ReadMetaDataFromFile(bom, importMetadataPath, fileSystem);
}
}
SetMetadataComponentIfNecessary(bom, topLevelComponent);
@@ -448,11 +448,11 @@ private static void SetMetadataComponentIfNecessary(Bom bom, Component topLevelC
}
- internal static Bom ReadMetaDataFromFile(Bom bom, string templatePath)
+ internal static Bom ReadMetaDataFromFile(Bom bom, string templatePath, IFileSystem fileSystem)
{
try
{
- return Xml.Serializer.Deserialize(File.ReadAllText(templatePath));
+ return Xml.Serializer.Deserialize(fileSystem.File.ReadAllText(templatePath));
}
catch (IOException ex)
{