github.com/jfrog/jfrog-cli@v1.54.1/nuget_test.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/xml"
     5  	"os"
     6  	"path/filepath"
     7  	"strconv"
     8  	"testing"
     9  
    10  	"github.com/jfrog/jfrog-cli-core/utils/coreutils"
    11  
    12  	"github.com/jfrog/jfrog-cli-core/artifactory/commands/dotnet"
    13  	"github.com/jfrog/jfrog-cli-core/artifactory/utils"
    14  	dotnetutils "github.com/jfrog/jfrog-cli-core/artifactory/utils/dotnet"
    15  	"github.com/jfrog/jfrog-cli-core/utils/config"
    16  	"github.com/jfrog/jfrog-cli/inttestutils"
    17  	"github.com/jfrog/jfrog-cli/utils/tests"
    18  	"github.com/jfrog/jfrog-client-go/artifactory/buildinfo"
    19  	"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
    20  	"github.com/stretchr/testify/assert"
    21  	"github.com/stretchr/testify/require"
    22  )
    23  
    24  func initNugetTest(t *testing.T) {
    25  	if !*tests.TestNuget {
    26  		t.Skip("Skipping NuGet test. To run Nuget test add the '-test.nuget=true' option.")
    27  	}
    28  
    29  	// This is due to Artifactory bug, we cant create remote repository with REST API.
    30  	require.True(t, isRepoExist(tests.NugetRemoteRepo), "Create nuget remote repository:", tests.NugetRemoteRepo, "in order to run nuget tests")
    31  	createJfrogHomeConfig(t, true)
    32  }
    33  
    34  type testDescriptor struct {
    35  	name                 string
    36  	project              string
    37  	args                 []string
    38  	expectedModules      []string
    39  	expectedDependencies []int
    40  }
    41  
    42  func TestNugetResolve(t *testing.T) {
    43  	initNugetTest(t)
    44  	projects := []testDescriptor{
    45  		{"packagesconfigwithoutmodulechnage", "packagesconfig", []string{"nuget", "restore", tests.NugetRemoteRepo}, []string{"packagesconfig"}, []int{6}},
    46  		{"packagesconfigwithmodulechnage", "packagesconfig", []string{"nuget", "restore", tests.NugetRemoteRepo, "--module=" + ModuleNameJFrogTest}, []string{ModuleNameJFrogTest}, []int{6}},
    47  		{"referencewithoutmodulechnage", "reference", []string{"nuget", "restore", tests.NugetRemoteRepo}, []string{"reference"}, []int{6}},
    48  		{"referencewithmodulechnage", "reference", []string{"nuget", "restore", tests.NugetRemoteRepo, "--module=" + ModuleNameJFrogTest}, []string{ModuleNameJFrogTest}, []int{6}},
    49  	}
    50  	for buildNumber, test := range projects {
    51  		t.Run(test.project, func(t *testing.T) {
    52  			testNugetCmd(t, createNugetProject(t, test.project), tests.DotnetBuildName, strconv.Itoa(buildNumber), test.expectedModules, test.args, test.expectedDependencies, false)
    53  		})
    54  	}
    55  	cleanBuildToolsTest()
    56  }
    57  
    58  func TestNativeNugetResolve(t *testing.T) {
    59  	uniqueNugetTests := []testDescriptor{
    60  		{"nugetargswithspaces", "packagesconfig", []string{dotnetutils.Nuget.String(), "restore", "-PackagesDirectory", "./packages dir with spaces"}, []string{"packagesconfig"}, []int{6}},
    61  		{"packagesconfigwithoutmodulechnage", "packagesconfig", []string{dotnetutils.Nuget.String(), "restore"}, []string{"packagesconfig"}, []int{6}},
    62  		{"packagesconfigwithmodulechnage", "packagesconfig", []string{dotnetutils.Nuget.String(), "restore", "--module=" + ModuleNameJFrogTest}, []string{ModuleNameJFrogTest}, []int{6}},
    63  		{"packagesconfigwithconfigpath", "packagesconfig", []string{dotnetutils.Nuget.String(), "restore", "./packages.config", "-SolutionDirectory", "."}, []string{"packagesconfig"}, []int{6}},
    64  		{"multipackagesconfigwithoutmodulechnage", "multipackagesconfig", []string{dotnetutils.Nuget.String(), "restore"}, []string{"proj1", "proj2", "proj3"}, []int{4, 3, 2}},
    65  		{"multipackagesconfigwithmodulechnage", "multipackagesconfig", []string{dotnetutils.Nuget.String(), "restore", "--module=" + ModuleNameJFrogTest}, []string{ModuleNameJFrogTest}, []int{8}},
    66  		{"multipackagesconfigwithslnPath", "multipackagesconfig", []string{dotnetutils.Nuget.String(), "restore", "./multipackagesconfig.sln"}, []string{"proj1", "proj2", "proj3"}, []int{4, 3, 2}},
    67  		{"multipackagesconfigsingleprojectdir", "multipackagesconfig", []string{dotnetutils.Nuget.String(), "restore", "./proj2/", "-SolutionDirectory", "."}, []string{"proj2"}, []int{3}},
    68  		{"multipackagesconfigsingleprojectconfig", "multipackagesconfig", []string{dotnetutils.Nuget.String(), "restore", "./proj1/packages.config", "-SolutionDirectory", "."}, []string{"proj1"}, []int{4}},
    69  	}
    70  	testNativeNugetDotnetResolve(t, uniqueNugetTests, tests.NuGetBuildName, utils.Nuget)
    71  }
    72  
    73  func TestDotnetResolve(t *testing.T) {
    74  	uniqueDotnetTests := []testDescriptor{
    75  		{"dotnetargswithspaces", "multireference", []string{dotnetutils.DotnetCore.String(), "restore", "src/multireference.proj1/", "--packages", "./packages dir with spaces"}, []string{"proj1"}, []int{5}},
    76  		{"multireferencesingleprojectdir", "multireference", []string{dotnetutils.DotnetCore.String(), "restore", "src/multireference.proj1/"}, []string{"proj1"}, []int{5}},
    77  	}
    78  	testNativeNugetDotnetResolve(t, uniqueDotnetTests, tests.DotnetBuildName, utils.Dotnet)
    79  }
    80  
    81  func testNativeNugetDotnetResolve(t *testing.T, uniqueTests []testDescriptor, buildName string, projectType utils.ProjectType) {
    82  	initNugetTest(t)
    83  	testDescriptors := append(uniqueTests, []testDescriptor{
    84  		{"referencewithoutmodulechnage", "reference", []string{projectType.String(), "restore"}, []string{"reference"}, []int{6}},
    85  		{"referencewithmodulechnage", "reference", []string{projectType.String(), "restore", "--module=" + ModuleNameJFrogTest}, []string{ModuleNameJFrogTest}, []int{6}},
    86  		{"multireferencewithoutmodulechnage", "multireference", []string{projectType.String(), "restore"}, []string{"proj1", "proj2"}, []int{5, 3}},
    87  		{"multireferencewithmodulechnage", "multireference", []string{projectType.String(), "restore", "--module=" + ModuleNameJFrogTest}, []string{ModuleNameJFrogTest}, []int{6}},
    88  		{"multireferencewithslnpath", "multireference", []string{projectType.String(), "restore", "src/multireference.sln"}, []string{"proj1", "proj2"}, []int{5, 3}},
    89  		{"multireferencewithslndir", "multireference", []string{projectType.String(), "restore", "src/"}, []string{"proj1", "proj2"}, []int{5, 3}},
    90  		{"multireferencesingleprojectcsproj", "multireference", []string{projectType.String(), "restore", "src/multireference.proj2/proj2.csproj"}, []string{"proj2"}, []int{3}},
    91  	}...)
    92  	for buildNumber, test := range testDescriptors {
    93  		projectPath := createNugetProject(t, test.project)
    94  		err := createConfigFileForTest([]string{projectPath}, tests.NugetRemoteRepo, "", t, projectType, false)
    95  		if err != nil {
    96  			assert.NoError(t, err)
    97  			return
    98  		}
    99  		t.Run(test.name, func(t *testing.T) {
   100  			testNugetCmd(t, projectPath, buildName, strconv.Itoa(buildNumber), test.expectedModules, test.args, test.expectedDependencies, true)
   101  		})
   102  	}
   103  	cleanBuildToolsTest()
   104  }
   105  
   106  func createNugetProject(t *testing.T, projectName string) string {
   107  	projectSrc := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "nuget", projectName)
   108  	projectTarget := filepath.Join(tests.Out, projectName)
   109  	err := fileutils.CreateDirIfNotExist(projectTarget)
   110  	assert.NoError(t, err)
   111  
   112  	err = fileutils.CopyDir(projectSrc, projectTarget, true, nil)
   113  	assert.NoError(t, err)
   114  	return projectTarget
   115  }
   116  
   117  func TestNuGetWithGlobalConfig(t *testing.T) {
   118  	initNugetTest(t)
   119  	projectPath := createNugetProject(t, "packagesconfig")
   120  	jfrogHomeDir, err := coreutils.GetJfrogHomeDir()
   121  	assert.NoError(t, err)
   122  	err = createConfigFileForTest([]string{jfrogHomeDir}, tests.NugetRemoteRepo, "", t, utils.Nuget, true)
   123  	assert.NoError(t, err)
   124  	testNugetCmd(t, projectPath, tests.NuGetBuildName, "1", []string{"packagesconfig"}, []string{"nuget", "restore"}, []int{6}, true)
   125  
   126  	cleanBuildToolsTest()
   127  }
   128  
   129  func testNugetCmd(t *testing.T, projectPath, buildName, buildNumber string, expectedModule, args []string, expectedDependencies []int, native bool) {
   130  	wd, err := os.Getwd()
   131  	assert.NoError(t, err)
   132  	err = os.Chdir(projectPath)
   133  	assert.NoError(t, err)
   134  	args = append(args, "--build-name="+buildName, "--build-number="+buildNumber)
   135  	if native {
   136  		err = runNuGet(t, args...)
   137  		if err != nil {
   138  			return
   139  		}
   140  	} else {
   141  		assert.NoError(t, artifactoryCli.Exec(args...))
   142  	}
   143  	inttestutils.ValidateGeneratedBuildInfoModule(t, buildName, buildNumber, "", expectedModule, buildinfo.Nuget)
   144  	assert.NoError(t, artifactoryCli.Exec("bp", buildName, buildNumber))
   145  
   146  	publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, buildName, buildNumber)
   147  	if err != nil {
   148  		assert.NoError(t, err)
   149  		return
   150  	}
   151  	if !found {
   152  		assert.True(t, found, "build info was expected to be found")
   153  		return
   154  	}
   155  	buildInfo := publishedBuildInfo.BuildInfo
   156  	require.NotEmpty(t, buildInfo.Modules, buildName+" build info was not generated correctly, no modules were created.")
   157  	for i, module := range buildInfo.Modules {
   158  		assert.Equal(t, expectedModule[i], buildInfo.Modules[i].Id, "Unexpected module name")
   159  		assert.Len(t, module.Dependencies, expectedDependencies[i], "Incorrect number of artifacts found in the build-info")
   160  	}
   161  	assert.NoError(t, os.Chdir(wd))
   162  
   163  	// cleanup
   164  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails)
   165  }
   166  
   167  func runNuGet(t *testing.T, args ...string) error {
   168  	artifactoryNuGetCli := tests.NewJfrogCli(execMain, "jfrog rt", "")
   169  	err := artifactoryNuGetCli.Exec(args...)
   170  	assert.NoError(t, err)
   171  	return err
   172  }
   173  
   174  type testInitNewConfigDescriptor struct {
   175  	testName          string
   176  	useNugetAddSource bool
   177  	useNugetV2        bool
   178  	expectedSourceUrl string
   179  }
   180  
   181  func TestInitNewConfig(t *testing.T) {
   182  	baseRtUrl := "http://some/url"
   183  	expectedV2Url := baseRtUrl + "/api/nuget"
   184  	expectedV3Url := baseRtUrl + "/api/nuget/v3"
   185  	testsSuites := []testInitNewConfigDescriptor{
   186  		{"useNugetAddSourceV2", true, true, expectedV2Url},
   187  		{"useNugetAddSourceV3", true, false, expectedV3Url},
   188  		{"doNotUseNugetAddSourceV2", false, true, expectedV2Url},
   189  		{"doNotUseNugetAddSourceV3", false, false, expectedV3Url},
   190  	}
   191  
   192  	for _, test := range testsSuites {
   193  		t.Run(test.testName, func(t *testing.T) {
   194  			runInitNewConfig(t, test, baseRtUrl)
   195  		})
   196  	}
   197  }
   198  
   199  func runInitNewConfig(t *testing.T, testSuite testInitNewConfigDescriptor, baseRtUrl string) {
   200  	initNugetTest(t)
   201  
   202  	tempDirPath, err := fileutils.CreateTempDir()
   203  	if err != nil {
   204  		assert.NoError(t, err)
   205  		return
   206  	}
   207  	defer fileutils.RemoveTempDir(tempDirPath)
   208  
   209  	params := &dotnet.DotnetCommand{}
   210  	params.SetServerDetails(&config.ServerDetails{ArtifactoryUrl: baseRtUrl, User: "user", Password: "password"}).
   211  		SetUseNugetAddSource(testSuite.useNugetAddSource).SetUseNugetV2(testSuite.useNugetV2)
   212  	// Prepare the config file with NuGet authentication
   213  	configFile, err := params.InitNewConfig(tempDirPath)
   214  	if err != nil {
   215  		assert.NoError(t, err)
   216  		return
   217  	}
   218  
   219  	content, err := os.ReadFile(configFile.Name())
   220  	if err != nil {
   221  		assert.NoError(t, err)
   222  		return
   223  	}
   224  
   225  	nugetConfig := NugetConfig{}
   226  	err = xml.Unmarshal(content, &nugetConfig)
   227  	if err != nil {
   228  		assert.NoError(t, err, "unmarshalling failed with an error")
   229  		return
   230  	}
   231  
   232  	assert.Len(t, nugetConfig.PackageSources, 1)
   233  
   234  	for _, packageSource := range nugetConfig.PackageSources {
   235  		assert.Equal(t, dotnet.SourceName, packageSource.Key)
   236  		assert.Equal(t, testSuite.expectedSourceUrl, packageSource.Value)
   237  	}
   238  	assert.Len(t, nugetConfig.PackageSourceCredentials, 1)
   239  	assert.Len(t, nugetConfig.PackageSourceCredentials[0].JFrogCli, 2)
   240  }
   241  
   242  type NugetConfig struct {
   243  	XMLName                  xml.Name                   `xml:"configuration"`
   244  	PackageSources           []PackageSources           `xml:"packageSources>add"`
   245  	PackageSourceCredentials []PackageSourceCredentials `xml:"packageSourceCredentials"`
   246  	Apikeys                  []PackageSources           `xml:"apikeys>add"`
   247  }
   248  
   249  type PackageSources struct {
   250  	Key   string `xml:"key,attr"`
   251  	Value string `xml:"value,attr"`
   252  }
   253  
   254  type PackageSourceCredentials struct {
   255  	JFrogCli []PackageSources `xml:">add"`
   256  }