github.com/anchore/syft@v1.38.2/syft/format/internal/spdxutil/helpers/download_location_test.go (about)

     1  package helpers
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/assert"
     7  
     8  	"github.com/anchore/syft/syft/pkg"
     9  )
    10  
    11  func Test_DownloadLocation(t *testing.T) {
    12  	tests := []struct {
    13  		name     string
    14  		input    pkg.Package
    15  		expected string
    16  	}{
    17  		{
    18  			name:     "no metadata",
    19  			input:    pkg.Package{},
    20  			expected: NOASSERTION,
    21  		},
    22  		{
    23  			name: "from apk",
    24  			input: pkg.Package{
    25  				Metadata: pkg.ApkDBEntry{
    26  					URL: "http://a-place.gov",
    27  				},
    28  			},
    29  			expected: "http://a-place.gov",
    30  		},
    31  		{
    32  			name: "from npm",
    33  			input: pkg.Package{
    34  				Metadata: pkg.NpmPackage{
    35  					URL: "http://a-place.gov",
    36  				},
    37  			},
    38  			expected: "http://a-place.gov",
    39  		},
    40  		{
    41  			name: "empty",
    42  			input: pkg.Package{
    43  				Metadata: pkg.NpmPackage{
    44  					URL: "",
    45  				},
    46  			},
    47  			expected: NOASSERTION,
    48  		},
    49  		{
    50  			name: "from npm package-lock should include resolved",
    51  			input: pkg.Package{
    52  				Metadata: pkg.NpmPackageLockEntry{
    53  					Resolved: "http://package-lock.test",
    54  				},
    55  			},
    56  			expected: "http://package-lock.test",
    57  		},
    58  		{
    59  			name: "from npm package-lock empty should be NONE",
    60  			input: pkg.Package{
    61  				Metadata: pkg.NpmPackageLockEntry{
    62  					Resolved: "",
    63  				},
    64  			},
    65  			expected: NOASSERTION,
    66  		},
    67  		{
    68  			name: "from php installed.json",
    69  			input: pkg.Package{
    70  				Metadata: pkg.PhpComposerInstalledEntry{
    71  					Dist: pkg.PhpComposerExternalReference{
    72  						URL: "http://package-lock.test",
    73  					},
    74  				},
    75  			},
    76  			expected: "http://package-lock.test",
    77  		},
    78  		{
    79  			name: "empty",
    80  			input: pkg.Package{
    81  				Metadata: pkg.PhpComposerInstalledEntry{
    82  					Dist: pkg.PhpComposerExternalReference{
    83  						URL: "",
    84  					},
    85  				},
    86  			},
    87  			expected: NOASSERTION,
    88  		},
    89  		{
    90  			name: "from php composer.lock",
    91  			input: pkg.Package{
    92  				Metadata: pkg.PhpComposerLockEntry{
    93  					Dist: pkg.PhpComposerExternalReference{
    94  						URL: "http://package-lock.test",
    95  					},
    96  				},
    97  			},
    98  			expected: "http://package-lock.test",
    99  		},
   100  		{
   101  			name: "empty",
   102  			input: pkg.Package{
   103  				Metadata: pkg.PhpComposerLockEntry{
   104  					Dist: pkg.PhpComposerExternalReference{
   105  						URL: "",
   106  					},
   107  				},
   108  			},
   109  			expected: NOASSERTION,
   110  		},
   111  		{
   112  			name: "none",
   113  			input: pkg.Package{
   114  				Metadata: pkg.PhpComposerLockEntry{
   115  					Dist: pkg.PhpComposerExternalReference{
   116  						URL: "none",
   117  					},
   118  				},
   119  			},
   120  			expected: NONE,
   121  		},
   122  		{
   123  			name: "none uppercase",
   124  			input: pkg.Package{
   125  				Metadata: pkg.PhpComposerLockEntry{
   126  					Dist: pkg.PhpComposerExternalReference{
   127  						URL: "NONE",
   128  					},
   129  				},
   130  			},
   131  			expected: NONE,
   132  		},
   133  		{
   134  			name: "invalid uri",
   135  			input: pkg.Package{
   136  				Metadata: pkg.PhpComposerLockEntry{
   137  					Dist: pkg.PhpComposerExternalReference{
   138  						URL: "example/package",
   139  					},
   140  				},
   141  			},
   142  			expected: NOASSERTION,
   143  		},
   144  		{
   145  			name: "Basic Git Protocol URL",
   146  			input: pkg.Package{
   147  				Metadata: pkg.PhpComposerLockEntry{
   148  					Dist: pkg.PhpComposerExternalReference{
   149  						URL: "git://git.myproject.org/MyProject",
   150  					},
   151  				},
   152  			},
   153  			expected: "git://git.myproject.org/MyProject",
   154  		},
   155  		{
   156  			name: "Git HTTPS URL with .git Extension",
   157  			input: pkg.Package{
   158  				Metadata: pkg.PhpComposerLockEntry{
   159  					Dist: pkg.PhpComposerExternalReference{
   160  						URL: "git+https://git.myproject.org/MyProject.git",
   161  					},
   162  				},
   163  			},
   164  			expected: "git+https://git.myproject.org/MyProject.git",
   165  		},
   166  		{
   167  			name: "Git HTTP URL",
   168  			input: pkg.Package{
   169  				Metadata: pkg.PhpComposerLockEntry{
   170  					Dist: pkg.PhpComposerExternalReference{
   171  						URL: "git+http://git.myproject.org/MyProject",
   172  					},
   173  				},
   174  			},
   175  			expected: "git+http://git.myproject.org/MyProject",
   176  		},
   177  		{
   178  			name: "Git SSH URL with .git Extension",
   179  			input: pkg.Package{
   180  				Metadata: pkg.PhpComposerLockEntry{
   181  					Dist: pkg.PhpComposerExternalReference{
   182  						URL: "git+ssh://git.myproject.org/MyProject.git",
   183  					},
   184  				},
   185  			},
   186  			expected: "git+ssh://git.myproject.org/MyProject.git",
   187  		},
   188  		{
   189  			name: "Git Protocol with Prefix",
   190  			input: pkg.Package{
   191  				Metadata: pkg.PhpComposerLockEntry{
   192  					Dist: pkg.PhpComposerExternalReference{
   193  						URL: "git+git://git.myproject.org/MyProject",
   194  					},
   195  				},
   196  			},
   197  			expected: "git+git://git.myproject.org/MyProject",
   198  		},
   199  		{
   200  			name: "Git URL with C File Fragment",
   201  			input: pkg.Package{
   202  				Metadata: pkg.PhpComposerLockEntry{
   203  					Dist: pkg.PhpComposerExternalReference{
   204  						URL: "git://git.myproject.org/MyProject#src/somefile.c",
   205  					},
   206  				},
   207  			},
   208  			expected: "git://git.myproject.org/MyProject#src/somefile.c",
   209  		},
   210  		{
   211  			name: "Git HTTPS URL with Java File Fragment",
   212  			input: pkg.Package{
   213  				Metadata: pkg.PhpComposerLockEntry{
   214  					Dist: pkg.PhpComposerExternalReference{
   215  						URL: "git+https://git.myproject.org/MyProject#src/Class.java",
   216  					},
   217  				},
   218  			},
   219  			expected: "git+https://git.myproject.org/MyProject#src/Class.java",
   220  		},
   221  		{
   222  			name: "Git URL with Master Branch",
   223  			input: pkg.Package{
   224  				Metadata: pkg.PhpComposerLockEntry{
   225  					Dist: pkg.PhpComposerExternalReference{
   226  						URL: "git://git.myproject.org/MyProject.git@master",
   227  					},
   228  				},
   229  			},
   230  			expected: "git://git.myproject.org/MyProject.git@master",
   231  		},
   232  		{
   233  			name: "Git HTTPS URL with Version Tag",
   234  			input: pkg.Package{
   235  				Metadata: pkg.PhpComposerLockEntry{
   236  					Dist: pkg.PhpComposerExternalReference{
   237  						URL: "git+https://git.myproject.org/MyProject.git@v1.0",
   238  					},
   239  				},
   240  			},
   241  			expected: "git+https://git.myproject.org/MyProject.git@v1.0",
   242  		},
   243  		{
   244  			name: "Git URL with Full Commit Hash",
   245  			input: pkg.Package{
   246  				Metadata: pkg.PhpComposerLockEntry{
   247  					Dist: pkg.PhpComposerExternalReference{
   248  						URL: "git://git.myproject.org/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709",
   249  					},
   250  				},
   251  			},
   252  			expected: "git://git.myproject.org/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709",
   253  		},
   254  		{
   255  			name: "Git HTTPS URL with Branch and CPP File Path",
   256  			input: pkg.Package{
   257  				Metadata: pkg.PhpComposerLockEntry{
   258  					Dist: pkg.PhpComposerExternalReference{
   259  						URL: "git+https://git.myproject.org/MyProject.git@master#/src/MyClass.cpp",
   260  					},
   261  				},
   262  			},
   263  			expected: "git+https://git.myproject.org/MyProject.git@master#/src/MyClass.cpp",
   264  		},
   265  		{
   266  			name: "Git HTTPS URL with Commit Hash and Ruby File",
   267  			input: pkg.Package{
   268  				Metadata: pkg.PhpComposerLockEntry{
   269  					Dist: pkg.PhpComposerExternalReference{
   270  						URL: "git+https://git.myproject.org/MyProject@da39a3ee5e6b4b0d3255bfef95601890afd80709#lib/variable.rb",
   271  					},
   272  				},
   273  			},
   274  			expected: "git+https://git.myproject.org/MyProject@da39a3ee5e6b4b0d3255bfef95601890afd80709#lib/variable.rb",
   275  		},
   276  		{
   277  			name: "Basic Mercurial HTTP URL",
   278  			input: pkg.Package{
   279  				Metadata: pkg.PhpComposerLockEntry{
   280  					Dist: pkg.PhpComposerExternalReference{
   281  						URL: "hg+http://hg.myproject.org/MyProject",
   282  					},
   283  				},
   284  			},
   285  			expected: "hg+http://hg.myproject.org/MyProject",
   286  		},
   287  		{
   288  			name: "Basic Mercurial HTTPS URL",
   289  			input: pkg.Package{
   290  				Metadata: pkg.PhpComposerLockEntry{
   291  					Dist: pkg.PhpComposerExternalReference{
   292  						URL: "hg+https://hg.myproject.org/MyProject",
   293  					},
   294  				},
   295  			},
   296  			expected: "hg+https://hg.myproject.org/MyProject",
   297  		},
   298  		{
   299  			name: "Basic Mercurial SSH URL",
   300  			input: pkg.Package{
   301  				Metadata: pkg.PhpComposerLockEntry{
   302  					Dist: pkg.PhpComposerExternalReference{
   303  						URL: "hg+ssh://hg.myproject.org/MyProject",
   304  					},
   305  				},
   306  			},
   307  			expected: "hg+ssh://hg.myproject.org/MyProject",
   308  		},
   309  		{
   310  			name: "Mercurial URL with File Fragment",
   311  			input: pkg.Package{
   312  				Metadata: pkg.PhpComposerLockEntry{
   313  					Dist: pkg.PhpComposerExternalReference{
   314  						URL: "hg+https://hg.myproject.org/MyProject#src/somefile.c",
   315  					},
   316  				},
   317  			},
   318  			expected: "hg+https://hg.myproject.org/MyProject#src/somefile.c",
   319  		},
   320  		{
   321  			name: "Mercurial URL with Java Class Fragment",
   322  			input: pkg.Package{
   323  				Metadata: pkg.PhpComposerLockEntry{
   324  					Dist: pkg.PhpComposerExternalReference{
   325  						URL: "hg+https://hg.myproject.org/MyProject#src/Class.java",
   326  					},
   327  				},
   328  			},
   329  			expected: "hg+https://hg.myproject.org/MyProject#src/Class.java",
   330  		},
   331  		{
   332  			name: "Mercurial URL with Commit Hash",
   333  			input: pkg.Package{
   334  				Metadata: pkg.PhpComposerLockEntry{
   335  					Dist: pkg.PhpComposerExternalReference{
   336  						URL: "hg+https://hg.myproject.org/MyProject@da39a3ee5e6b",
   337  					},
   338  				},
   339  			},
   340  			expected: "hg+https://hg.myproject.org/MyProject@da39a3ee5e6b",
   341  		},
   342  		{
   343  			name: "Mercurial URL with Year Reference",
   344  			input: pkg.Package{
   345  				Metadata: pkg.PhpComposerLockEntry{
   346  					Dist: pkg.PhpComposerExternalReference{
   347  						URL: "hg+https://hg.myproject.org/MyProject@2019",
   348  					},
   349  				},
   350  			},
   351  			expected: "hg+https://hg.myproject.org/MyProject@2019",
   352  		},
   353  		{
   354  			name: "Mercurial URL with Version Tag",
   355  			input: pkg.Package{
   356  				Metadata: pkg.PhpComposerLockEntry{
   357  					Dist: pkg.PhpComposerExternalReference{
   358  						URL: "hg+https://hg.myproject.org/MyProject@v1.0",
   359  					},
   360  				},
   361  			},
   362  			expected: "hg+https://hg.myproject.org/MyProject@v1.0",
   363  		},
   364  		{
   365  			name: "Mercurial URL with Feature Branch",
   366  			input: pkg.Package{
   367  				Metadata: pkg.PhpComposerLockEntry{
   368  					Dist: pkg.PhpComposerExternalReference{
   369  						URL: "hg+https://hg.myproject.org/MyProject@special_feature",
   370  					},
   371  				},
   372  			},
   373  			expected: "hg+https://hg.myproject.org/MyProject@special_feature",
   374  		},
   375  		{
   376  			name: "Mercurial URL with Branch and File Path",
   377  			input: pkg.Package{
   378  				Metadata: pkg.PhpComposerLockEntry{
   379  					Dist: pkg.PhpComposerExternalReference{
   380  						URL: "hg+https://hg.myproject.org/MyProject@master#/src/MyClass.cpp",
   381  					},
   382  				},
   383  			},
   384  			expected: "hg+https://hg.myproject.org/MyProject@master#/src/MyClass.cpp",
   385  		},
   386  		{
   387  			name: "Mercurial URL with Commit Hash and Ruby File",
   388  			input: pkg.Package{
   389  				Metadata: pkg.PhpComposerLockEntry{
   390  					Dist: pkg.PhpComposerExternalReference{
   391  						URL: "hg+https://hg.myproject.org/MyProject@da39a3ee5e6b#lib/variable.rb",
   392  					},
   393  				},
   394  			},
   395  			expected: "hg+https://hg.myproject.org/MyProject@da39a3ee5e6b#lib/variable.rb",
   396  		},
   397  
   398  		// Test cases for Subversion (svn) URLs
   399  		{
   400  			name: "Basic SVN URL",
   401  			input: pkg.Package{
   402  				Metadata: pkg.PhpComposerLockEntry{
   403  					Dist: pkg.PhpComposerExternalReference{
   404  						URL: "svn://svn.myproject.org/svn/MyProject",
   405  					},
   406  				},
   407  			},
   408  			expected: "svn://svn.myproject.org/svn/MyProject",
   409  		},
   410  		{
   411  			name: "SVN URL with Protocol Prefix",
   412  			input: pkg.Package{
   413  				Metadata: pkg.PhpComposerLockEntry{
   414  					Dist: pkg.PhpComposerExternalReference{
   415  						URL: "svn+svn://svn.myproject.org/svn/MyProject",
   416  					},
   417  				},
   418  			},
   419  			expected: "svn+svn://svn.myproject.org/svn/MyProject",
   420  		},
   421  		{
   422  			name: "SVN HTTP URL with Trunk",
   423  			input: pkg.Package{
   424  				Metadata: pkg.PhpComposerLockEntry{
   425  					Dist: pkg.PhpComposerExternalReference{
   426  						URL: "svn+http://svn.myproject.org/svn/MyProject/trunk",
   427  					},
   428  				},
   429  			},
   430  			expected: "svn+http://svn.myproject.org/svn/MyProject/trunk",
   431  		},
   432  		{
   433  			name: "SVN HTTPS URL with Trunk",
   434  			input: pkg.Package{
   435  				Metadata: pkg.PhpComposerLockEntry{
   436  					Dist: pkg.PhpComposerExternalReference{
   437  						URL: "svn+https://svn.myproject.org/svn/MyProject/trunk",
   438  					},
   439  				},
   440  			},
   441  			expected: "svn+https://svn.myproject.org/svn/MyProject/trunk",
   442  		},
   443  		{
   444  			name: "SVN URL with C File Fragment",
   445  			input: pkg.Package{
   446  				Metadata: pkg.PhpComposerLockEntry{
   447  					Dist: pkg.PhpComposerExternalReference{
   448  						URL: "svn+https://svn.myproject.org/MyProject#src/somefile.c",
   449  					},
   450  				},
   451  			},
   452  			expected: "svn+https://svn.myproject.org/MyProject#src/somefile.c",
   453  		},
   454  		{
   455  			name: "SVN URL with Java Class Fragment",
   456  			input: pkg.Package{
   457  				Metadata: pkg.PhpComposerLockEntry{
   458  					Dist: pkg.PhpComposerExternalReference{
   459  						URL: "svn+https://svn.myproject.org/MyProject#src/Class.java",
   460  					},
   461  				},
   462  			},
   463  			expected: "svn+https://svn.myproject.org/MyProject#src/Class.java",
   464  		},
   465  		{
   466  			name: "SVN URL with Trunk and C File Fragment",
   467  			input: pkg.Package{
   468  				Metadata: pkg.PhpComposerLockEntry{
   469  					Dist: pkg.PhpComposerExternalReference{
   470  						URL: "svn+https://svn.myproject.org/MyProject/trunk#src/somefile.c",
   471  					},
   472  				},
   473  			},
   474  			expected: "svn+https://svn.myproject.org/MyProject/trunk#src/somefile.c",
   475  		},
   476  		{
   477  			name: "SVN URL with Full File Path",
   478  			input: pkg.Package{
   479  				Metadata: pkg.PhpComposerLockEntry{
   480  					Dist: pkg.PhpComposerExternalReference{
   481  						URL: "svn+https://svn.myproject.org/MyProject/trunk/src/somefile.c",
   482  					},
   483  				},
   484  			},
   485  			expected: "svn+https://svn.myproject.org/MyProject/trunk/src/somefile.c",
   486  		},
   487  		{
   488  			name: "SVN URL with Revision Number",
   489  			input: pkg.Package{
   490  				Metadata: pkg.PhpComposerLockEntry{
   491  					Dist: pkg.PhpComposerExternalReference{
   492  						URL: "svn+https://svn.myproject.org/svn/MyProject/trunk@2019",
   493  					},
   494  				},
   495  			},
   496  			expected: "svn+https://svn.myproject.org/svn/MyProject/trunk@2019",
   497  		},
   498  		{
   499  			name: "SVN URL with Revision and CPP File Path",
   500  			input: pkg.Package{
   501  				Metadata: pkg.PhpComposerLockEntry{
   502  					Dist: pkg.PhpComposerExternalReference{
   503  						URL: "svn+https://svn.myproject.org/MyProject@123#/src/MyClass.cpp",
   504  					},
   505  				},
   506  			},
   507  			expected: "svn+https://svn.myproject.org/MyProject@123#/src/MyClass.cpp",
   508  		},
   509  		{
   510  			name: "SVN URL with Trunk, Revision and Ruby File Path",
   511  			input: pkg.Package{
   512  				Metadata: pkg.PhpComposerLockEntry{
   513  					Dist: pkg.PhpComposerExternalReference{
   514  						URL: "svn+https://svn.myproject.org/MyProject/trunk@1234#lib/variable/variable.rb",
   515  					},
   516  				},
   517  			},
   518  			expected: "svn+https://svn.myproject.org/MyProject/trunk@1234#lib/variable/variable.rb",
   519  		},
   520  
   521  		// Test cases for Bazaar (bzr) URLs
   522  		{
   523  			name: "Bazaar HTTPS URL with Trunk",
   524  			input: pkg.Package{
   525  				Metadata: pkg.PhpComposerLockEntry{
   526  					Dist: pkg.PhpComposerExternalReference{
   527  						URL: "bzr+https://bzr.myproject.org/MyProject/trunk",
   528  					},
   529  				},
   530  			},
   531  			expected: "bzr+https://bzr.myproject.org/MyProject/trunk",
   532  		},
   533  		{
   534  			name: "Bazaar HTTP URL with Trunk",
   535  			input: pkg.Package{
   536  				Metadata: pkg.PhpComposerLockEntry{
   537  					Dist: pkg.PhpComposerExternalReference{
   538  						URL: "bzr+http://bzr.myproject.org/MyProject/trunk",
   539  					},
   540  				},
   541  			},
   542  			expected: "bzr+http://bzr.myproject.org/MyProject/trunk",
   543  		},
   544  		{
   545  			name: "Bazaar SFTP URL with Trunk",
   546  			input: pkg.Package{
   547  				Metadata: pkg.PhpComposerLockEntry{
   548  					Dist: pkg.PhpComposerExternalReference{
   549  						URL: "bzr+sftp://myproject.org/MyProject/trunk",
   550  					},
   551  				},
   552  			},
   553  			expected: "bzr+sftp://myproject.org/MyProject/trunk",
   554  		},
   555  		{
   556  			name: "Bazaar SSH URL with Trunk",
   557  			input: pkg.Package{
   558  				Metadata: pkg.PhpComposerLockEntry{
   559  					Dist: pkg.PhpComposerExternalReference{
   560  						URL: "bzr+ssh://myproject.org/MyProject/trunk",
   561  					},
   562  				},
   563  			},
   564  			expected: "bzr+ssh://myproject.org/MyProject/trunk",
   565  		},
   566  		{
   567  			name: "Bazaar FTP URL with Trunk",
   568  			input: pkg.Package{
   569  				Metadata: pkg.PhpComposerLockEntry{
   570  					Dist: pkg.PhpComposerExternalReference{
   571  						URL: "bzr+ftp://myproject.org/MyProject/trunk",
   572  					},
   573  				},
   574  			},
   575  			expected: "bzr+ftp://myproject.org/MyProject/trunk",
   576  		},
   577  		{
   578  			name: "Bazaar Launchpad URL",
   579  			input: pkg.Package{
   580  				Metadata: pkg.PhpComposerLockEntry{
   581  					Dist: pkg.PhpComposerExternalReference{
   582  						URL: "bzr+lp:MyProject",
   583  					},
   584  				},
   585  			},
   586  			expected: "bzr+lp:MyProject",
   587  		},
   588  		{
   589  			name: "Bazaar URL with C File Fragment",
   590  			input: pkg.Package{
   591  				Metadata: pkg.PhpComposerLockEntry{
   592  					Dist: pkg.PhpComposerExternalReference{
   593  						URL: "bzr+https://bzr.myproject.org/MyProject/trunk#src/somefile.c",
   594  					},
   595  				},
   596  			},
   597  			expected: "bzr+https://bzr.myproject.org/MyProject/trunk#src/somefile.c",
   598  		},
   599  		{
   600  			name: "Bazaar URL with Java Class Fragment",
   601  			input: pkg.Package{
   602  				Metadata: pkg.PhpComposerLockEntry{
   603  					Dist: pkg.PhpComposerExternalReference{
   604  						URL: "bzr+https://bzr.myproject.org/MyProject/trunk#src/Class.java",
   605  					},
   606  				},
   607  			},
   608  			expected: "bzr+https://bzr.myproject.org/MyProject/trunk#src/Class.java",
   609  		},
   610  		{
   611  			name: "Bazaar URL with Revision",
   612  			input: pkg.Package{
   613  				Metadata: pkg.PhpComposerLockEntry{
   614  					Dist: pkg.PhpComposerExternalReference{
   615  						URL: "bzr+https://bzr.myproject.org/MyProject/trunk@2019",
   616  					},
   617  				},
   618  			},
   619  			expected: "bzr+https://bzr.myproject.org/MyProject/trunk@2019",
   620  		},
   621  		{
   622  			name: "Bazaar URL with Version Tag",
   623  			input: pkg.Package{
   624  				Metadata: pkg.PhpComposerLockEntry{
   625  					Dist: pkg.PhpComposerExternalReference{
   626  						URL: "bzr+http://bzr.myproject.org/MyProject/trunk@v1.0",
   627  					},
   628  				},
   629  			},
   630  			expected: "bzr+http://bzr.myproject.org/MyProject/trunk@v1.0",
   631  		},
   632  		{
   633  			name: "Bazaar URL with Revision and C File Fragment",
   634  			input: pkg.Package{
   635  				Metadata: pkg.PhpComposerLockEntry{
   636  					Dist: pkg.PhpComposerExternalReference{
   637  						URL: "bzr+https://bzr.myproject.org/MyProject/trunk@2019#src/somefile.c",
   638  					},
   639  				},
   640  			},
   641  			expected: "bzr+https://bzr.myproject.org/MyProject/trunk@2019#src/somefile.c",
   642  		},
   643  	}
   644  	for _, test := range tests {
   645  		t.Run(test.name, func(t *testing.T) {
   646  			assert.Equal(t, test.expected, DownloadLocation(test.input))
   647  		})
   648  	}
   649  }