Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CycloneDX.Tests/CycloneDX.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<PackageReference Include="Moq" />
<PackageReference Include="RichardSzalay.MockHttp" />
<PackageReference Include="System.IO.Abstractions.TestingHelpers" />
<PackageReference Include="System.Text.Json" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
5 changes: 3 additions & 2 deletions CycloneDX.Tests/FunctionalTests/FunctionalTestHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ private static INugetServiceFactory CreateMockNugetServiceFactory()
It.IsAny<RunOptions>(),
It.IsAny<IFileSystem>(),
It.IsAny<IGithubService>(),
It.IsAny<List<string>>()))
It.IsAny<List<string>>(),
It.IsAny<HashSet<NugetInputModel>>()))
.Returns(nugetService);

return mockNugetServiceFactory.Object;
Expand Down Expand Up @@ -79,7 +80,7 @@ public static async Task<Bom> Test(RunOptions options, INugetServiceFactory nuge
options.SolutionOrProjectFile ??= MockUnixSupport.Path("c:/ProjectPath/Project.csproj");
options.disablePackageRestore = true;

Runner runner = new Runner(mockFileSystem, null, null, null, null, null, null, nugetService);
Runner runner = new Runner(mockFileSystem, null, null, null, null, null, null, null, nugetService);
int exitCode = await runner.HandleCommandAsync(options);

Assert.Equal((int)ExitCode.OK, exitCode);
Expand Down
3 changes: 2 additions & 1 deletion CycloneDX.Tests/FunctionalTests/Issue758.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ public Issue758()
It.IsAny<RunOptions>(),
It.IsAny<IFileSystem>(),
It.IsAny<IGithubService>(),
It.IsAny<List<string>>()))
It.IsAny<List<string>>(),
It.IsAny<HashSet<NugetInputModel>>()))
.Returns(nugetService);

nugetServiceFactory = mockNugetServiceFactory.Object;
Expand Down
18 changes: 18 additions & 0 deletions CycloneDX.Tests/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,24 @@ public static MockFileData GetPackagesFileWithPackageReferences(IEnumerable<Dotn

}

public static MockFileData GetNugetConfigFileWithSources(IEnumerable<NugetInputModel> sources)
{
var sb = new StringBuilder();

sb.Append( "<configuration><packageSources>" );
foreach (var source in sources)
{
sb.Append(@"<add key=""");
sb.Append(source.nugetFeedName);
sb.Append(@""" value=""");
sb.Append(source.nugetFeedUrl);
sb.Append(@""" />");
}
sb.Append( "</packageSources></configuration>" );
return new MockFileData(sb.ToString());

}

public static DotnetCommandResult GetDotnetListPackagesResult(IEnumerable<(string projectName, (string packageName, string version)[] packages)> projects)
{
StringBuilder stdout = new StringBuilder();
Expand Down
86 changes: 86 additions & 0 deletions CycloneDX.Tests/NugetConfigFileServiceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// This file is part of CycloneDX Tool for .NET
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) OWASP Foundation. All Rights Reserved.

using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;
using System.IO.Abstractions.TestingHelpers;
using XFS = System.IO.Abstractions.TestingHelpers.MockUnixSupport;
using CycloneDX.Models;
using CycloneDX.Services;
using System.Linq;

namespace CycloneDX.Tests
{
public class NugetConfigFileServiceTests
{
[Fact]
public async Task GetDotnetDependencys_ReturnsDotnetDependency()
{
var mockFileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ XFS.Path(@"c:\Project\nuget.config"), Helpers.GetNugetConfigFileWithSources(
new List<NugetInputModel> {
new NugetInputModel( "https://www.contoso.com" ) { nugetFeedName = "Contoso" }
})
},
});
var configFileService = new NugetConfigFileService(mockFileSystem);

var sources = await configFileService.GetPackageSourcesAsync(XFS.Path(@"c:\Project\nuget.config")).ConfigureAwait(true);

Assert.Collection(sources,
item => {
Assert.Equal("https://www.contoso.com", item.nugetFeedUrl);
});
Assert.Collection(sources,
item => {
Assert.Equal("Contoso", item.nugetFeedName);
});
}

[Fact]
public async Task GetDotnetDependencys_ReturnsMultipleDotnetDependencys()
{
var mockFileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ XFS.Path(@"c:\Project\nuget.config"), Helpers.GetNugetConfigFileWithSources(
new List<NugetInputModel> {
new NugetInputModel( "https://www.contoso.com" ) { nugetFeedName = "Contoso" },
new NugetInputModel( "https://www.contoso2.com" ) { nugetFeedName = "Contoso2" },
new NugetInputModel( "https://www.contoso3.com" ) { nugetFeedName = "Contoso3" },
})
},
});
var configFileService = new NugetConfigFileService(mockFileSystem);

var sources = await configFileService.GetPackageSourcesAsync(XFS.Path(@"c:\Project\nuget.config")).ConfigureAwait(true);
var sortedPackages = new List<NugetInputModel>(sources);
sortedPackages.OrderBy(nim => nim.nugetFeedName);

Assert.Collection(sortedPackages,
item => Assert.Equal("https://www.contoso.com", item.nugetFeedUrl),
item => Assert.Equal("https://www.contoso2.com", item.nugetFeedUrl),
item => Assert.Equal("https://www.contoso3.com", item.nugetFeedUrl));
Assert.Collection(sortedPackages,
item => Assert.Equal("Contoso", item.nugetFeedName),
item => Assert.Equal("Contoso2", item.nugetFeedName),
item => Assert.Equal("Contoso3", item.nugetFeedName));
}

}
}
6 changes: 3 additions & 3 deletions CycloneDX.Tests/ProgramTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public async Task CallingCycloneDX_CreatesOutputDirectory()
.Setup(s => s.GetSolutionDotnetDependencys(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(new HashSet<DotnetDependency>());

Runner runner = new Runner(fileSystem: mockFileSystem, null, null, null, null, null, solutionFileService: mockSolutionFileService.Object, null);
Runner runner = new Runner(fileSystem: mockFileSystem, null, null, null, null, null, null, solutionFileService: mockSolutionFileService.Object, null);

RunOptions runOptions = new RunOptions
{
Expand All @@ -75,7 +75,7 @@ public async Task CallingCycloneDX_WithOutputFilename_CreatesOutputFilename()
.Setup(s => s.GetSolutionDotnetDependencys(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(new HashSet<DotnetDependency>());

Runner runner = new Runner(fileSystem: mockFileSystem, null, null, null, null, null, solutionFileService: mockSolutionFileService.Object, null);
Runner runner = new Runner(fileSystem: mockFileSystem, null, null, null, null, null, null, solutionFileService: mockSolutionFileService.Object, null);

RunOptions runOptions = new RunOptions
{
Expand Down Expand Up @@ -116,7 +116,7 @@ public async Task CallingCycloneDX_WithSolutionOrProjectFileThatDoesntExistsRetu
.Setup(s => s.GetSolutionDotnetDependencys(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(new HashSet<DotnetDependency>());

Runner runner = new Runner(fileSystem: mockFileSystem, null, null, null, null, null, solutionFileService: mockSolutionFileService.Object, null);
Runner runner = new Runner(fileSystem: mockFileSystem, null, null, null, null, null, null, solutionFileService: mockSolutionFileService.Object, null);

RunOptions runOptions = new RunOptions
{
Expand Down
2 changes: 1 addition & 1 deletion CycloneDX.Tests/ValidationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public async Task Validation(string fileFormat, bool disableGitHubLicenses)
mock.GetProjectDotnetDependencysAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<string>(), It.IsAny<string>())
).ReturnsAsync(packages);

Runner runner = new Runner(fileSystem: mockFileSystem, null, null, null, null, projectFileService: mockProjectFileService.Object, solutionFileService: null, null);
Runner runner = new Runner(fileSystem: mockFileSystem, null, null, null, null, null, projectFileService: mockProjectFileService.Object, solutionFileService: null, null);


RunOptions runOptions = new RunOptions
Expand Down
2 changes: 2 additions & 0 deletions CycloneDX/CycloneDX.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<ToolCommandName>dotnet-CycloneDX</ToolCommandName>
<_SkipUpgradeNetAnalyzersNuGetWarning>true</_SkipUpgradeNetAnalyzersNuGetWarning>
<TargetFrameworks>net8.0;net7.0;net6.0</TargetFrameworks>
<BuildInParallel Condition="$([MSBuild]::IsOSPlatform('Windows'))">false</BuildInParallel>

<!-- Always run on the latest runtime installed. -->
<RollForward>Major</RollForward>
Expand Down Expand Up @@ -38,6 +39,7 @@
<PackageReference Include="NuGet.ProjectModel" />
<PackageReference Include="System.IO.Abstractions" />
<PackageReference Include="System.CommandLine" />
<PackageReference Include="System.Text.Json" />
</ItemGroup>

<ItemGroup>
Expand Down
29 changes: 29 additions & 0 deletions CycloneDX/Interfaces/INugetConfigFileService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// This file is part of CycloneDX Tool for .NET
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) OWASP Foundation. All Rights Reserved.

using System.Collections.Generic;
using System.Threading.Tasks;
using CycloneDX.Models;

namespace CycloneDX.Interfaces
{
public interface INugetConfigFileService
{
Task<HashSet<NugetInputModel>> GetPackageSourcesAsync(string configFilePath);
Task<HashSet<NugetInputModel>> RecursivelyGetPackageSourcesAsync(string directoryPath);
}
}
2 changes: 1 addition & 1 deletion CycloneDX/Interfaces/INugetServiceFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ namespace CycloneDX.Interfaces
{
public interface INugetServiceFactory
{
INugetService Create(RunOptions option, IFileSystem fileSystem, IGithubService githubService, List<string> packageCachePaths);
INugetService Create(RunOptions option, IFileSystem fileSystem, IGithubService githubService, List<string> packageCachePaths, HashSet<NugetInputModel> nugetInputModels);
}
}
14 changes: 12 additions & 2 deletions CycloneDX/Models/NugetInputModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,20 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) OWASP Foundation. All Rights Reserved.

using System.Transactions;

namespace CycloneDX.Models
{
public static class NugetInputFactory
{
public static NugetInputModel Create(string baseUrl, string baseUrlUserName, string baseUrlUserPassword,
bool isPasswordClearText)
{
return Create(baseUrl, baseUrlUserName, baseUrlUserPassword, isPasswordClearText, "Unnamed Source");
}

public static NugetInputModel Create(string baseUrl, string baseUrlUserName, string baseUrlUserPassword,
bool isPasswordClearText, string feedName )
{
if (string.IsNullOrEmpty(baseUrl))
{
Expand All @@ -29,7 +37,7 @@ public static NugetInputModel Create(string baseUrl, string baseUrlUserName, str

if (!string.IsNullOrEmpty(baseUrlUserName) && !string.IsNullOrEmpty(baseUrlUserPassword))
{
return new NugetInputModel(baseUrl, baseUrlUserName, baseUrlUserPassword, isPasswordClearText);
return new NugetInputModel(baseUrl, baseUrlUserName, baseUrlUserPassword, isPasswordClearText, feedName);
}

return new NugetInputModel(baseUrl);
Expand All @@ -39,6 +47,7 @@ public static NugetInputModel Create(string baseUrl, string baseUrlUserName, str

public class NugetInputModel
{
public string nugetFeedName { get; set; }
public string nugetFeedUrl { get; set; }
public string nugetUsername { get; set; }
public string nugetPassword { get; set; }
Expand All @@ -50,12 +59,13 @@ public NugetInputModel(string baseUrl)
}

public NugetInputModel(string baseUrl, string baseUrlUserName, string baseUrlUserPassword,
bool isPasswordClearText)
bool isPasswordClearText, string feedName)
{
nugetFeedUrl = baseUrl;
nugetUsername = baseUrlUserName;
nugetPassword = baseUrlUserPassword;
IsPasswordClearText = isPasswordClearText;
nugetFeedName = feedName;
}
}
}
Loading