github.com/jfrog/jfrog-cli-go@v1.22.1-0.20200318093948-4826ef344ffd/go_test.go (about) 1 package main 2 3 import ( 4 "github.com/stretchr/testify/assert" 5 "github.com/stretchr/testify/require" 6 "io/ioutil" 7 "os" 8 "os/exec" 9 "path/filepath" 10 "testing" 11 12 "github.com/jfrog/gocmd/executers" 13 "github.com/jfrog/jfrog-cli-go/inttestutils" 14 "github.com/jfrog/jfrog-cli-go/utils/cliutils" 15 "github.com/jfrog/jfrog-cli-go/utils/tests" 16 _go "github.com/jfrog/jfrog-client-go/artifactory/services/go" 17 "github.com/jfrog/jfrog-client-go/utils/io/fileutils" 18 "github.com/jfrog/jfrog-client-go/utils/log" 19 "github.com/jfrog/jfrog-client-go/utils/version" 20 ) 21 22 // Testing build info capabilities for go project. 23 // Build project using go without Artifactory -> 24 // Publish dependencies to Artifactory -> 25 // Publish project to Artifactory-> 26 // Publish and validate build-info 27 func TestGoBuildInfo(t *testing.T) { 28 initGoTest(t) 29 wd, err := os.Getwd() 30 assert.NoError(t, err) 31 project1Path := createGoProject(t, "project1", false) 32 testsdataTarget := filepath.Join(tests.Out, "testsdata") 33 testsdataSrc := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "go", "testsdata") 34 assert.NoError(t, fileutils.CopyDir(testsdataSrc, testsdataTarget, true)) 35 assert.NoError(t, os.Chdir(project1Path)) 36 defer os.Chdir(wd) 37 38 log.Info("Using Go project located at ", project1Path) 39 40 buildName := "go-build" 41 42 // 1. Download dependencies. 43 // 2. Publish build-info. 44 // 3. Validate the total count of dependencies added to the build-info. 45 buildNumber := "1" 46 47 artifactoryCli.Exec("go", "build", tests.GoLocalRepo, "--build-name="+buildName, "--build-number="+buildNumber) 48 cleanGoCache(t) 49 50 artifactoryCli.Exec("bp", buildName, buildNumber) 51 module := "github.com/jfrog/dependency" 52 buildInfo := inttestutils.GetBuildInfo(artifactoryDetails.Url, buildName, buildNumber, t, artHttpDetails) 53 artifactoryVersion, err := artAuth.GetVersion() 54 assert.NoError(t, err) 55 56 // Since Artifactory doesn't support info file before version 6.10.0, the artifacts count in the build info is different between versions 57 version := version.NewVersion(artifactoryVersion) 58 expectedDependencies := 8 59 expectedArtifacts := 2 60 if version.AtLeast(_go.ArtifactoryMinSupportedVersionForInfoFile) { 61 expectedDependencies = 4 62 expectedArtifacts = 3 63 } 64 validateBuildInfo(buildInfo, t, expectedDependencies, 0, module) 65 66 // Now, using a new build number, do the following: 67 // 1. Build the project again. 68 // 2. Publish the go package. 69 // 3. Validate the total count of dependencies and artifacts added to the build-info. 70 // 4. Validate that the artifacts are tagged with the build.name and build.number properties. 71 buildNumber = "2" 72 73 artifactoryCli.Exec("go", "build", tests.GoLocalRepo, "--build-name="+buildName, "--build-number="+buildNumber, "--module="+ModuleNameJFrogTest) 74 cleanGoCache(t) 75 76 artifactoryCli.Exec("gp", tests.GoLocalRepo, "v1.0.0", "--build-name="+buildName, "--build-number="+buildNumber, "--deps=rsc.io/quote:v1.5.2", "--module="+ModuleNameJFrogTest) 77 cleanGoCache(t) 78 79 artifactoryCli.Exec("bp", buildName, buildNumber) 80 buildInfo = inttestutils.GetBuildInfo(artifactoryDetails.Url, buildName, buildNumber, t, artHttpDetails) 81 validateBuildInfo(buildInfo, t, expectedDependencies, expectedArtifacts, ModuleNameJFrogTest) 82 83 assert.NoError(t, os.Chdir(filepath.Join(wd, "testsdata", "go"))) 84 85 resultItems := getResultItemsFromArtifactory(tests.SearchGo, t) 86 assert.Equal(t, len(buildInfo.Modules[0].Artifacts), len(resultItems), "Incorrect number of artifacts were uploaded") 87 propsMap := map[string]string{ 88 "build.name": buildName, 89 "build.number": buildNumber, 90 "go.version": "v1.0.0", 91 } 92 validateArtifactsProperties(resultItems, t, propsMap) 93 94 assert.NoError(t, os.Chdir(wd)) 95 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 96 cleanGoTest() 97 } 98 99 func TestGoConfigWithModuleNameChange(t *testing.T) { 100 initGoTest(t) 101 buildName := "go-build" 102 buildNumber := "1" 103 oldHomeDir, newHomeDir := prepareHomeDir(t) 104 defer os.Setenv(cliutils.HomeDir, oldHomeDir) 105 defer os.RemoveAll(newHomeDir) 106 107 wd, err := os.Getwd() 108 assert.NoError(t, err) 109 110 prepareGoProject("", t, true) 111 runGo(ModuleNameJFrogTest, buildName, buildNumber, t, "go", "build", "--build-name="+buildName, "--build-number="+buildNumber, "--module="+ModuleNameJFrogTest) 112 113 assert.NoError(t, os.Chdir(wd)) 114 115 cleanGoTest() 116 } 117 118 func TestGoConfigWithoutModuleChange(t *testing.T) { 119 initGoTest(t) 120 buildName := "go-build" 121 buildNumber := "1" 122 oldHomeDir, newHomeDir := prepareHomeDir(t) 123 defer os.Setenv(cliutils.HomeDir, oldHomeDir) 124 defer os.RemoveAll(newHomeDir) 125 126 wd, err := os.Getwd() 127 assert.NoError(t, err) 128 129 prepareGoProject("", t, true) 130 runGo("", buildName, buildNumber, t, "go", "build", "--build-name="+buildName, "--build-number="+buildNumber) 131 132 assert.NoError(t, os.Chdir(wd)) 133 134 cleanGoTest() 135 } 136 137 func TestGoWithGlobalConfig(t *testing.T) { 138 initGoTest(t) 139 buildName := "go-build" 140 buildNumber := "1" 141 oldHomeDir, newHomeDir := prepareHomeDir(t) 142 143 defer os.Setenv(cliutils.HomeDir, oldHomeDir) 144 defer os.RemoveAll(newHomeDir) 145 146 wd, err := os.Getwd() 147 assert.NoError(t, err) 148 149 prepareGoProject(newHomeDir, t, false) 150 runGo(ModuleNameJFrogTest, buildName, buildNumber, t, "go", "build", "--build-name="+buildName, "--build-number="+buildNumber, "--module="+ModuleNameJFrogTest) 151 152 assert.NoError(t, os.Chdir(wd)) 153 154 cleanGoTest() 155 } 156 157 func runGo(module, buildName, buildNumber string, t *testing.T, args ...string) { 158 artifactoryGoCli := tests.NewJfrogCli(execMain, "jfrog rt", "") 159 assert.NoError(t, artifactoryGoCli.Exec(args...)) 160 cleanGoCache(t) 161 artifactoryCli.Exec("bp", buildName, buildNumber) 162 buildInfo := inttestutils.GetBuildInfo(artifactoryDetails.Url, buildName, buildNumber, t, artHttpDetails) 163 if module == "" { 164 module = "github.com/jfrog/dependency" 165 } 166 artifactoryVersion, err := artAuth.GetVersion() 167 assert.NoError(t, err) 168 169 // Since Artifactory doesn't support info file before version 6.10.0, the artifacts count in the build info is different between versions 170 version := version.NewVersion(artifactoryVersion) 171 if version.AtLeast(_go.ArtifactoryMinSupportedVersionForInfoFile) { 172 validateBuildInfo(buildInfo, t, 4, 0, module) 173 } else { 174 validateBuildInfo(buildInfo, t, 8, 0, module) 175 } 176 177 inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails) 178 } 179 180 func prepareGoProject(configDestDir string, t *testing.T, copyDirs bool) { 181 project1Path := createGoProject(t, "project1", copyDirs) 182 testsdataTarget := filepath.Join(tests.Out, "testsdata") 183 testsdataSrc := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "go", "testsdata") 184 err := fileutils.CopyDir(testsdataSrc, testsdataTarget, copyDirs) 185 assert.NoError(t, err) 186 if configDestDir == "" { 187 configDestDir = filepath.Join(project1Path, ".jfrog") 188 } 189 configFileDir := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "go", "project1", ".jfrog", "projects") 190 configFileDir, err = tests.ReplaceTemplateVariables(filepath.Join(configFileDir, "go.yaml"), filepath.Join(configDestDir, "projects")) 191 assert.NoError(t, err) 192 assert.NoError(t, os.Chdir(project1Path)) 193 log.Info("Using Go project located at ", project1Path) 194 } 195 196 // Testing publishing and resolution capabilities for go projects. 197 // Build first project using go without Artifactory -> 198 // Publish dependencies to Artifactory -> 199 // Publish first project to Artifactory -> 200 // Set go to resolve from Artifactory (set GOPROXY) -> 201 // Build second project using go resolving from Artifactory, should download project1 as dependency. 202 func TestGoPublishResolve(t *testing.T) { 203 initGoTest(t) 204 205 wd, err := os.Getwd() 206 assert.NoError(t, err) 207 project1Path := createGoProject(t, "project1", false) 208 project2Path := createGoProject(t, "project2", false) 209 assert.NoError(t, os.Chdir(project1Path)) 210 211 // Download dependencies without Artifactory 212 artifactoryCli.Exec("go", "build", tests.GoLocalRepo) 213 cleanGoCache(t) 214 215 // Publish dependency project to Artifactory 216 artifactoryCli.Exec("gp", tests.GoLocalRepo, "v1.0.0") 217 cleanGoCache(t) 218 219 assert.NoError(t, os.Chdir(project2Path)) 220 221 // Build the second project, download dependencies from Artifactory 222 artifactoryCli.Exec("go", "build", tests.GoLocalRepo) 223 cleanGoCache(t) 224 225 // Restore workspace 226 assert.NoError(t, os.Chdir(wd)) 227 cleanGoTest() 228 } 229 230 // Testing the fallback mechanism 231 // 1. Building a project with a dependency that doesn't exists not in Artifactory and not in VCS. 232 // 2. The fallback mechanism will try to download from both VCS and Artifactory and then fail with an error 233 // 3. Testing that the error that is returned is the right error of the fallback. 234 func TestGoFallback(t *testing.T) { 235 initGoTest(t) 236 237 wd, err := os.Getwd() 238 assert.NoError(t, err) 239 240 projectBuild := createGoProject(t, "projectbuild", false) 241 242 assert.NoError(t, os.Chdir(projectBuild)) 243 244 err = artifactoryCli.Exec("go", "build", tests.GoLocalRepo) 245 if err != nil { 246 log.Warn(err) 247 assert.Contains(t, err.Error(), executers.FailedToRetrieve) 248 assert.Contains(t, err.Error(), executers.FromBothArtifactoryAndVcs) 249 } else { 250 assert.Fail(t, "Expected error but got success") 251 } 252 253 assert.NoError(t, os.Chdir(wd)) 254 cleanGoTest() 255 } 256 257 // Builds a project with a dependency of gofrog that is missing a mod file. 258 // Test the recursive overwrite capability. 259 // 1. Upload dependency. 260 // 2. Upload a project that is using that dependency 261 // 3. Build with recursive-tidy-overwrite set to true so the gofrog dependency will be downloaded from VCS 262 // 4. Check mod file (in Artifactory) of the dependency gofrog that populated. 263 // 5. Check mod file (in Artifactory) of the gofrog dependency (pkg/errors) that exists with the right content 264 func TestGoRecursivePublish(t *testing.T) { 265 initGoTest(t) 266 wd, err := os.Getwd() 267 assert.NoError(t, err) 268 269 testsdataTarget := filepath.Join(tests.Out, "testsdata") 270 testsdataSrc := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "go", "testsdata") 271 assert.NoError(t, fileutils.CopyDir(testsdataSrc, testsdataTarget, true)) 272 project1Path := createGoProject(t, "dependency", false) 273 projectMissingDependency := createGoProject(t, "projectmissingdependency", false) 274 projectBuild := createGoProject(t, "projectbuild", false) 275 276 uploadGoProject(project1Path, t) 277 uploadGoProject(projectMissingDependency, t) 278 279 assert.NoError(t, os.Chdir(projectBuild)) 280 defer os.Chdir(wd) 281 282 assert.NoError(t, artifactoryCli.Exec("grp", tests.GoLocalRepo)) 283 sumFileExists, err := fileutils.IsFileExists("go.sum", false) 284 assert.NoError(t, err) 285 if sumFileExists { 286 assert.NoError(t, os.Remove("go.sum")) 287 } 288 cleanGoCache(t) 289 290 assert.NoError(t, os.Chdir(filepath.Join(wd, "testsdata", "go"))) 291 292 // Need to check the mod file within Artifactory of the gofrog dependency. 293 content := downloadModFile(tests.DownloadModFileGo, wd, "gofrog", t) 294 295 // Check that the file was signed: 296 assert.NotContains(t, string(content), "// Generated by JFrog", "Expected file to be not signed") 297 // Check that the mod file was populated with the dependency 298 assert.NotContains(t, string(content), "require github.com/pkg/errors", "Expected to get empty mod file") 299 300 assert.NoError(t, os.Chdir(filepath.Join(wd, "testsdata", "go"))) 301 302 // Need to check the mod file within Artifactory of the dependency of gofrog => pkg/errors. 303 content = downloadModFile(tests.DownloadModOfDependencyGo, wd, "errors", t) 304 305 // Check that the file was signed: 306 assert.NotContains(t, string(content), "// Generated by JFrog", "Expected file to be not signed") 307 // Check that the mod file contains dependency module. 308 assert.Contains(t, string(content), "module github.com/pkg/errors", "Expected to get module github.com/pkg/errors") 309 310 assert.NoError(t, os.Chdir(wd)) 311 312 cleanGoTest() 313 } 314 315 // Publish also the missing dependencies to Artifactory with the publishDeps flag. 316 // Checks that the dependency exists in Artifactory. 317 func TestGoWithPublishDeps(t *testing.T) { 318 initGoTest(t) 319 wd, err := os.Getwd() 320 assert.NoError(t, err) 321 project1Path := createGoProject(t, "project1", false) 322 testsdataTarget := filepath.Join(tests.Out, "testsdata") 323 testsdataSrc := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "go", "testsdata") 324 assert.NoError(t, fileutils.CopyDir(testsdataSrc, testsdataTarget, true)) 325 assert.NoError(t, os.Chdir(project1Path)) 326 defer os.Chdir(wd) 327 328 log.Info("Using Go project located at ", project1Path) 329 artifactoryCli.Exec("go", "build", tests.GoLocalRepo, "--publish-deps=true") 330 cleanGoCache(t) 331 332 assert.NoError(t, os.Chdir(filepath.Join(wd, "testsdata", "go"))) 333 334 content := downloadModFile(tests.DownloadModOfDependencyGo, wd, "errors", t) 335 assert.NotContains(t, string(content), " module github.com/pkg/errors", "Wrong mod content was downloaded") 336 337 assert.NoError(t, os.Chdir(wd)) 338 339 cleanGoTest() 340 } 341 342 func initGoTest(t *testing.T) { 343 if !*tests.TestGo { 344 t.Skip("Skipping go test. To run go test add the '-test.go=true' option.") 345 } 346 347 os.Setenv("GONOSUMDB", "github.com/jfrog") 348 349 // Move when go will be supported and check Artifactory version. 350 if !isRepoExist(tests.GoLocalRepo) { 351 repoConfig := filepath.FromSlash(tests.GetTestResourcesPath()) + tests.GoLocalRepositoryConfig 352 repoConfig, err := tests.ReplaceTemplateVariables(repoConfig, "") 353 require.NoError(t, err) 354 execCreateRepoRest(repoConfig, tests.GoLocalRepo) 355 } 356 authenticate() 357 } 358 359 func cleanGoTest() { 360 os.Unsetenv("GONOSUMDB") 361 if isRepoExist(tests.GoLocalRepo) { 362 execDeleteRepoRest(tests.GoLocalRepo) 363 } 364 cleanBuildToolsTest() 365 } 366 367 func uploadGoProject(projectPath string, t *testing.T) { 368 assert.NoError(t, os.Chdir(projectPath)) 369 // Publish project to Artifactory 370 assert.NoError(t, artifactoryCli.Exec("gp", tests.GoLocalRepo, "v1.0.0")) 371 cleanGoCache(t) 372 } 373 374 func cleanGoCache(t *testing.T) { 375 log.Info("Cleaning go cache by running: 'go clean -modcache'") 376 377 cmd := exec.Command("go", "clean", "-modcache") 378 assert.NoError(t, cmd.Run()) 379 } 380 381 func createGoProject(t *testing.T, projectName string, includeDirs bool) string { 382 projectSrc := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "go", projectName) 383 projectTarget := filepath.Join(tests.Out, projectName) 384 err := fileutils.CopyDir(projectSrc, projectTarget, includeDirs) 385 assert.NoError(t, err) 386 projectTarget, err = filepath.Abs(projectTarget) 387 assert.NoError(t, err) 388 return projectTarget 389 } 390 391 func downloadModFile(specName, wd, subDir string, t *testing.T) []byte { 392 specFile, err := tests.CreateSpec(specName) 393 assert.NoError(t, err) 394 395 modDir := filepath.Join(wd, tests.Out, subDir) 396 assert.NoError(t, os.MkdirAll(modDir, 0777)) 397 398 assert.NoError(t, os.Chdir(modDir)) 399 artifactoryCli.Exec("download", "--spec="+specFile, "--flat=true") 400 files, err := fileutils.ListFiles(modDir, false) 401 assert.NoError(t, err) 402 assert.Len(t, files, 1, "Expected to get one mod file") 403 404 content, err := ioutil.ReadFile(files[0]) 405 assert.NoError(t, err) 406 return content 407 }