gitea源码

lfs_getobject_test.go 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package integration
  4. import (
  5. "archive/zip"
  6. "bytes"
  7. "io"
  8. "net/http"
  9. "net/http/httptest"
  10. "testing"
  11. "code.gitea.io/gitea/models/auth"
  12. git_model "code.gitea.io/gitea/models/git"
  13. repo_model "code.gitea.io/gitea/models/repo"
  14. "code.gitea.io/gitea/modules/json"
  15. "code.gitea.io/gitea/modules/lfs"
  16. "code.gitea.io/gitea/modules/setting"
  17. "code.gitea.io/gitea/routers/web"
  18. "code.gitea.io/gitea/tests"
  19. gzipp "github.com/klauspost/compress/gzip"
  20. "github.com/stretchr/testify/assert"
  21. )
  22. func storeObjectInRepo(t *testing.T, repositoryID int64, content *[]byte) string {
  23. pointer, err := lfs.GeneratePointer(bytes.NewReader(*content))
  24. assert.NoError(t, err)
  25. _, err = git_model.NewLFSMetaObject(t.Context(), repositoryID, pointer)
  26. assert.NoError(t, err)
  27. contentStore := lfs.NewContentStore()
  28. exist, err := contentStore.Exists(pointer)
  29. assert.NoError(t, err)
  30. if !exist {
  31. err := contentStore.Put(pointer, bytes.NewReader(*content))
  32. assert.NoError(t, err)
  33. }
  34. return pointer.Oid
  35. }
  36. func storeAndGetLfsToken(t *testing.T, content *[]byte, extraHeader *http.Header, expectedStatus int, ts ...auth.AccessTokenScope) *httptest.ResponseRecorder {
  37. repo, err := repo_model.GetRepositoryByOwnerAndName(t.Context(), "user2", "repo1")
  38. assert.NoError(t, err)
  39. oid := storeObjectInRepo(t, repo.ID, content)
  40. defer git_model.RemoveLFSMetaObjectByOid(t.Context(), repo.ID, oid)
  41. token := getUserToken(t, "user2", ts...)
  42. // Request OID
  43. req := NewRequest(t, "GET", "/user2/repo1.git/info/lfs/objects/"+oid+"/test")
  44. req.Header.Set("Accept-Encoding", "gzip")
  45. req.SetBasicAuth("user2", token)
  46. if extraHeader != nil {
  47. for key, values := range *extraHeader {
  48. for _, value := range values {
  49. req.Header.Add(key, value)
  50. }
  51. }
  52. }
  53. resp := MakeRequest(t, req, expectedStatus)
  54. return resp
  55. }
  56. func storeAndGetLfs(t *testing.T, content *[]byte, extraHeader *http.Header, expectedStatus int) *httptest.ResponseRecorder {
  57. repo, err := repo_model.GetRepositoryByOwnerAndName(t.Context(), "user2", "repo1")
  58. assert.NoError(t, err)
  59. oid := storeObjectInRepo(t, repo.ID, content)
  60. defer git_model.RemoveLFSMetaObjectByOid(t.Context(), repo.ID, oid)
  61. session := loginUser(t, "user2")
  62. // Request OID
  63. req := NewRequest(t, "GET", "/user2/repo1.git/info/lfs/objects/"+oid+"/test")
  64. req.Header.Set("Accept-Encoding", "gzip")
  65. if extraHeader != nil {
  66. for key, values := range *extraHeader {
  67. for _, value := range values {
  68. req.Header.Add(key, value)
  69. }
  70. }
  71. }
  72. resp := session.MakeRequest(t, req, expectedStatus)
  73. return resp
  74. }
  75. func checkResponseTestContentEncoding(t *testing.T, content *[]byte, resp *httptest.ResponseRecorder, expectGzip bool) {
  76. contentEncoding := resp.Header().Get("Content-Encoding")
  77. if !expectGzip || !setting.EnableGzip {
  78. assert.NotContains(t, contentEncoding, "gzip")
  79. result := resp.Body.Bytes()
  80. assert.Equal(t, *content, result)
  81. } else {
  82. assert.Contains(t, contentEncoding, "gzip")
  83. gzippReader, err := gzipp.NewReader(resp.Body)
  84. assert.NoError(t, err)
  85. result, err := io.ReadAll(gzippReader)
  86. assert.NoError(t, err)
  87. assert.Equal(t, *content, result)
  88. }
  89. }
  90. func TestGetLFSSmall(t *testing.T) {
  91. defer tests.PrepareTestEnv(t)()
  92. content := []byte("A very small file\n")
  93. resp := storeAndGetLfs(t, &content, nil, http.StatusOK)
  94. checkResponseTestContentEncoding(t, &content, resp, false)
  95. }
  96. func TestGetLFSSmallToken(t *testing.T) {
  97. defer tests.PrepareTestEnv(t)()
  98. content := []byte("A very small file\n")
  99. resp := storeAndGetLfsToken(t, &content, nil, http.StatusOK, auth.AccessTokenScopePublicOnly, auth.AccessTokenScopeReadRepository)
  100. checkResponseTestContentEncoding(t, &content, resp, false)
  101. }
  102. func TestGetLFSSmallTokenFail(t *testing.T) {
  103. defer tests.PrepareTestEnv(t)()
  104. content := []byte("A very small file\n")
  105. storeAndGetLfsToken(t, &content, nil, http.StatusForbidden, auth.AccessTokenScopeReadNotification)
  106. }
  107. func TestGetLFSLarge(t *testing.T) {
  108. defer tests.PrepareTestEnv(t)()
  109. content := make([]byte, web.GzipMinSize*10)
  110. for i := range content {
  111. content[i] = byte(i % 256)
  112. }
  113. resp := storeAndGetLfs(t, &content, nil, http.StatusOK)
  114. checkResponseTestContentEncoding(t, &content, resp, true)
  115. }
  116. func TestGetLFSGzip(t *testing.T) {
  117. defer tests.PrepareTestEnv(t)()
  118. b := make([]byte, web.GzipMinSize*10)
  119. for i := range b {
  120. b[i] = byte(i % 256)
  121. }
  122. outputBuffer := bytes.NewBuffer([]byte{})
  123. gzippWriter := gzipp.NewWriter(outputBuffer)
  124. gzippWriter.Write(b)
  125. gzippWriter.Close()
  126. content := outputBuffer.Bytes()
  127. resp := storeAndGetLfs(t, &content, nil, http.StatusOK)
  128. checkResponseTestContentEncoding(t, &content, resp, false)
  129. }
  130. func TestGetLFSZip(t *testing.T) {
  131. defer tests.PrepareTestEnv(t)()
  132. b := make([]byte, web.GzipMinSize*10)
  133. for i := range b {
  134. b[i] = byte(i % 256)
  135. }
  136. outputBuffer := bytes.NewBuffer([]byte{})
  137. zipWriter := zip.NewWriter(outputBuffer)
  138. fileWriter, err := zipWriter.Create("default")
  139. assert.NoError(t, err)
  140. fileWriter.Write(b)
  141. zipWriter.Close()
  142. content := outputBuffer.Bytes()
  143. resp := storeAndGetLfs(t, &content, nil, http.StatusOK)
  144. checkResponseTestContentEncoding(t, &content, resp, false)
  145. }
  146. func TestGetLFSRangeNo(t *testing.T) {
  147. defer tests.PrepareTestEnv(t)()
  148. content := []byte("123456789\n")
  149. resp := storeAndGetLfs(t, &content, nil, http.StatusOK)
  150. assert.Equal(t, content, resp.Body.Bytes())
  151. }
  152. func TestGetLFSRange(t *testing.T) {
  153. defer tests.PrepareTestEnv(t)()
  154. content := []byte("123456789\n")
  155. tests := []struct {
  156. in string
  157. out string
  158. status int
  159. }{
  160. {"bytes=0-0", "1", http.StatusPartialContent},
  161. {"bytes=0-1", "12", http.StatusPartialContent},
  162. {"bytes=1-1", "2", http.StatusPartialContent},
  163. {"bytes=1-3", "234", http.StatusPartialContent},
  164. {"bytes=1-", "23456789\n", http.StatusPartialContent},
  165. // end-range smaller than start-range is ignored
  166. {"bytes=1-0", "23456789\n", http.StatusPartialContent},
  167. {"bytes=0-10", "123456789\n", http.StatusPartialContent},
  168. // end-range bigger than length-1 is ignored
  169. {"bytes=0-11", "123456789\n", http.StatusPartialContent},
  170. {"bytes=11-", "Requested Range Not Satisfiable", http.StatusRequestedRangeNotSatisfiable},
  171. // incorrect header value cause whole header to be ignored
  172. {"bytes=-", "123456789\n", http.StatusOK},
  173. {"foobar", "123456789\n", http.StatusOK},
  174. }
  175. for _, tt := range tests {
  176. t.Run(tt.in, func(t *testing.T) {
  177. h := http.Header{
  178. "Range": []string{tt.in},
  179. }
  180. resp := storeAndGetLfs(t, &content, &h, tt.status)
  181. if tt.status == http.StatusPartialContent || tt.status == http.StatusOK {
  182. assert.Equal(t, tt.out, resp.Body.String())
  183. } else {
  184. var er lfs.ErrorResponse
  185. err := json.Unmarshal(resp.Body.Bytes(), &er)
  186. assert.NoError(t, err)
  187. assert.Equal(t, tt.out, er.Message)
  188. }
  189. })
  190. }
  191. }