gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. // Copyright 2021 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package integration
  4. import (
  5. "archive/zip"
  6. "bytes"
  7. "fmt"
  8. "net/http"
  9. neturl "net/url"
  10. "testing"
  11. "code.gitea.io/gitea/models/packages"
  12. repo_model "code.gitea.io/gitea/models/repo"
  13. "code.gitea.io/gitea/models/unittest"
  14. user_model "code.gitea.io/gitea/models/user"
  15. composer_module "code.gitea.io/gitea/modules/packages/composer"
  16. "code.gitea.io/gitea/modules/setting"
  17. "code.gitea.io/gitea/routers/api/packages/composer"
  18. "code.gitea.io/gitea/tests"
  19. "github.com/stretchr/testify/assert"
  20. )
  21. func TestPackageComposer(t *testing.T) {
  22. defer tests.PrepareTestEnv(t)()
  23. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
  24. vendorName := "gitea"
  25. projectName := "composer-package"
  26. packageName := vendorName + "/" + projectName
  27. packageVersion := "1.0.3"
  28. packageDescription := "Package Description"
  29. packageType := "composer-plugin"
  30. packageAuthor := "Gitea Authors"
  31. packageLicense := "MIT"
  32. packageBin := "./bin/script"
  33. var buf bytes.Buffer
  34. archive := zip.NewWriter(&buf)
  35. w, _ := archive.Create("composer.json")
  36. w.Write([]byte(`{
  37. "name": "` + packageName + `",
  38. "description": "` + packageDescription + `",
  39. "type": "` + packageType + `",
  40. "license": "` + packageLicense + `",
  41. "authors": [
  42. {
  43. "name": "` + packageAuthor + `"
  44. }
  45. ],
  46. "bin": [
  47. "` + packageBin + `"
  48. ]
  49. }`))
  50. archive.Close()
  51. content := buf.Bytes()
  52. url := fmt.Sprintf("%sapi/packages/%s/composer", setting.AppURL, user.Name)
  53. t.Run("ServiceIndex", func(t *testing.T) {
  54. defer tests.PrintCurrentTest(t)()
  55. req := NewRequest(t, "GET", url+"/packages.json").
  56. AddBasicAuth(user.Name)
  57. resp := MakeRequest(t, req, http.StatusOK)
  58. var result composer.ServiceIndexResponse
  59. DecodeJSON(t, resp, &result)
  60. assert.Equal(t, url+"/search.json?q=%query%&type=%type%", result.SearchTemplate)
  61. assert.Equal(t, url+"/p2/%package%.json", result.MetadataTemplate)
  62. assert.Equal(t, url+"/list.json", result.PackageList)
  63. })
  64. t.Run("Upload", func(t *testing.T) {
  65. t.Run("MissingVersion", func(t *testing.T) {
  66. defer tests.PrintCurrentTest(t)()
  67. req := NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)).
  68. AddBasicAuth(user.Name)
  69. MakeRequest(t, req, http.StatusBadRequest)
  70. })
  71. t.Run("Valid", func(t *testing.T) {
  72. defer tests.PrintCurrentTest(t)()
  73. uploadURL := url + "?version=" + packageVersion
  74. req := NewRequestWithBody(t, "PUT", uploadURL, bytes.NewReader(content)).
  75. AddBasicAuth(user.Name)
  76. MakeRequest(t, req, http.StatusCreated)
  77. pvs, err := packages.GetVersionsByPackageType(t.Context(), user.ID, packages.TypeComposer)
  78. assert.NoError(t, err)
  79. assert.Len(t, pvs, 1)
  80. pd, err := packages.GetPackageDescriptor(t.Context(), pvs[0])
  81. assert.NoError(t, err)
  82. assert.NotNil(t, pd.SemVer)
  83. assert.IsType(t, &composer_module.Metadata{}, pd.Metadata)
  84. assert.Equal(t, packageName, pd.Package.Name)
  85. assert.Equal(t, packageVersion, pd.Version.Version)
  86. pfs, err := packages.GetFilesByVersionID(t.Context(), pvs[0].ID)
  87. assert.NoError(t, err)
  88. assert.Len(t, pfs, 1)
  89. assert.Equal(t, fmt.Sprintf("%s-%s.%s.zip", vendorName, projectName, packageVersion), pfs[0].Name)
  90. assert.True(t, pfs[0].IsLead)
  91. pb, err := packages.GetBlobByID(t.Context(), pfs[0].BlobID)
  92. assert.NoError(t, err)
  93. assert.Equal(t, int64(len(content)), pb.Size)
  94. req = NewRequestWithBody(t, "PUT", uploadURL, bytes.NewReader(content)).
  95. AddBasicAuth(user.Name)
  96. MakeRequest(t, req, http.StatusConflict)
  97. })
  98. })
  99. t.Run("Download", func(t *testing.T) {
  100. defer tests.PrintCurrentTest(t)()
  101. pvs, err := packages.GetVersionsByPackageType(t.Context(), user.ID, packages.TypeComposer)
  102. assert.NoError(t, err)
  103. assert.Len(t, pvs, 1)
  104. assert.Equal(t, int64(0), pvs[0].DownloadCount)
  105. pfs, err := packages.GetFilesByVersionID(t.Context(), pvs[0].ID)
  106. assert.NoError(t, err)
  107. assert.Len(t, pfs, 1)
  108. req := NewRequest(t, "GET", fmt.Sprintf("%s/files/%s/%s/%s", url, neturl.PathEscape(packageName), neturl.PathEscape(pvs[0].LowerVersion), neturl.PathEscape(pfs[0].LowerName))).
  109. AddBasicAuth(user.Name)
  110. resp := MakeRequest(t, req, http.StatusOK)
  111. assert.Equal(t, content, resp.Body.Bytes())
  112. pvs, err = packages.GetVersionsByPackageType(t.Context(), user.ID, packages.TypeComposer)
  113. assert.NoError(t, err)
  114. assert.Len(t, pvs, 1)
  115. assert.Equal(t, int64(1), pvs[0].DownloadCount)
  116. })
  117. t.Run("SearchService", func(t *testing.T) {
  118. defer tests.PrintCurrentTest(t)()
  119. cases := []struct {
  120. Query string
  121. Type string
  122. Page int
  123. PerPage int
  124. ExpectedTotal int64
  125. ExpectedResults int
  126. }{
  127. {"", "", 0, 0, 1, 1},
  128. {"", "", 1, 1, 1, 1},
  129. {"test", "", 1, 0, 0, 0},
  130. {"gitea", "", 1, 1, 1, 1},
  131. {"gitea", "", 2, 1, 1, 0},
  132. {"", packageType, 1, 1, 1, 1},
  133. {"gitea", packageType, 1, 1, 1, 1},
  134. {"gitea", "dummy", 1, 1, 0, 0},
  135. }
  136. for i, c := range cases {
  137. req := NewRequest(t, "GET", fmt.Sprintf("%s/search.json?q=%s&type=%s&page=%d&per_page=%d", url, c.Query, c.Type, c.Page, c.PerPage)).
  138. AddBasicAuth(user.Name)
  139. resp := MakeRequest(t, req, http.StatusOK)
  140. var result composer.SearchResultResponse
  141. DecodeJSON(t, resp, &result)
  142. assert.Equal(t, c.ExpectedTotal, result.Total, "case %d: unexpected total hits", i)
  143. assert.Len(t, result.Results, c.ExpectedResults, "case %d: unexpected result count", i)
  144. }
  145. })
  146. t.Run("EnumeratePackages", func(t *testing.T) {
  147. defer tests.PrintCurrentTest(t)()
  148. req := NewRequest(t, "GET", url+"/list.json").
  149. AddBasicAuth(user.Name)
  150. resp := MakeRequest(t, req, http.StatusOK)
  151. var result map[string][]string
  152. DecodeJSON(t, resp, &result)
  153. assert.Contains(t, result, "packageNames")
  154. names := result["packageNames"]
  155. assert.Len(t, names, 1)
  156. assert.Equal(t, packageName, names[0])
  157. })
  158. t.Run("PackageMetadata", func(t *testing.T) {
  159. defer tests.PrintCurrentTest(t)()
  160. req := NewRequest(t, "GET", fmt.Sprintf("%s/p2/%s/%s.json", url, vendorName, projectName)).
  161. AddBasicAuth(user.Name)
  162. resp := MakeRequest(t, req, http.StatusOK)
  163. var result composer.PackageMetadataResponse
  164. DecodeJSON(t, resp, &result)
  165. assert.Contains(t, result.Packages, packageName)
  166. pkgs := result.Packages[packageName]
  167. assert.Len(t, pkgs, 1)
  168. assert.Equal(t, packageName, pkgs[0].Name)
  169. assert.Equal(t, packageVersion, pkgs[0].Version)
  170. assert.Equal(t, packageType, pkgs[0].Type)
  171. assert.Equal(t, packageDescription, pkgs[0].Description)
  172. assert.Len(t, pkgs[0].Authors, 1)
  173. assert.Equal(t, packageAuthor, pkgs[0].Authors[0].Name)
  174. assert.Equal(t, "zip", pkgs[0].Dist.Type)
  175. assert.Equal(t, "4f5fa464c3cb808a1df191dbf6cb75363f8b7072", pkgs[0].Dist.Checksum)
  176. assert.Len(t, pkgs[0].Bin, 1)
  177. assert.Equal(t, packageBin, pkgs[0].Bin[0])
  178. // Test package linked to repository
  179. repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
  180. userPkgs, err := packages.GetPackagesByType(t.Context(), user.ID, packages.TypeComposer)
  181. assert.NoError(t, err)
  182. assert.Len(t, userPkgs, 1)
  183. assert.EqualValues(t, 0, userPkgs[0].RepoID)
  184. err = packages.SetRepositoryLink(t.Context(), userPkgs[0].ID, repo1.ID)
  185. assert.NoError(t, err)
  186. req = NewRequest(t, "GET", fmt.Sprintf("%s/p2/%s/%s.json", url, vendorName, projectName)).
  187. AddBasicAuth(user.Name)
  188. resp = MakeRequest(t, req, http.StatusOK)
  189. result = composer.PackageMetadataResponse{}
  190. DecodeJSON(t, resp, &result)
  191. assert.Contains(t, result.Packages, packageName)
  192. pkgs = result.Packages[packageName]
  193. assert.Len(t, pkgs, 1)
  194. assert.Equal(t, packageName, pkgs[0].Name)
  195. assert.Equal(t, packageVersion, pkgs[0].Version)
  196. assert.Equal(t, packageType, pkgs[0].Type)
  197. assert.Equal(t, packageDescription, pkgs[0].Description)
  198. assert.Len(t, pkgs[0].Authors, 1)
  199. assert.Equal(t, packageAuthor, pkgs[0].Authors[0].Name)
  200. assert.Equal(t, "zip", pkgs[0].Dist.Type)
  201. assert.Equal(t, "4f5fa464c3cb808a1df191dbf6cb75363f8b7072", pkgs[0].Dist.Checksum)
  202. assert.Len(t, pkgs[0].Bin, 1)
  203. assert.Equal(t, packageBin, pkgs[0].Bin[0])
  204. assert.Equal(t, repo1.HTMLURL(), pkgs[0].Source.URL)
  205. assert.Equal(t, "git", pkgs[0].Source.Type)
  206. assert.Equal(t, packageVersion, pkgs[0].Source.Reference)
  207. })
  208. }