You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

api_repo_lfs_locks_test.go 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package integrations
  5. import (
  6. "fmt"
  7. "net/http"
  8. "testing"
  9. "time"
  10. "code.gitea.io/gitea/models"
  11. "code.gitea.io/gitea/modules/lfs"
  12. "code.gitea.io/gitea/modules/setting"
  13. api "code.gitea.io/gitea/modules/structs"
  14. "github.com/stretchr/testify/assert"
  15. )
  16. func TestAPILFSLocksNotStarted(t *testing.T) {
  17. defer prepareTestEnv(t)()
  18. setting.LFS.StartServer = false
  19. user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
  20. repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
  21. req := NewRequestf(t, "GET", "/%s/%s.git/info/lfs/locks", user.Name, repo.Name)
  22. MakeRequest(t, req, http.StatusNotFound)
  23. req = NewRequestf(t, "POST", "/%s/%s.git/info/lfs/locks", user.Name, repo.Name)
  24. MakeRequest(t, req, http.StatusNotFound)
  25. req = NewRequestf(t, "GET", "/%s/%s.git/info/lfs/locks/verify", user.Name, repo.Name)
  26. MakeRequest(t, req, http.StatusNotFound)
  27. req = NewRequestf(t, "GET", "/%s/%s.git/info/lfs/locks/10/unlock", user.Name, repo.Name)
  28. MakeRequest(t, req, http.StatusNotFound)
  29. }
  30. func TestAPILFSLocksNotLogin(t *testing.T) {
  31. defer prepareTestEnv(t)()
  32. setting.LFS.StartServer = true
  33. user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
  34. repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
  35. req := NewRequestf(t, "GET", "/%s/%s.git/info/lfs/locks", user.Name, repo.Name)
  36. req.Header.Set("Accept", lfs.MediaType)
  37. resp := MakeRequest(t, req, http.StatusUnauthorized)
  38. var lfsLockError api.LFSLockError
  39. DecodeJSON(t, resp, &lfsLockError)
  40. assert.Equal(t, "You must have pull access to list locks", lfsLockError.Message)
  41. }
  42. func TestAPILFSLocksLogged(t *testing.T) {
  43. defer prepareTestEnv(t)()
  44. setting.LFS.StartServer = true
  45. user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) //in org 3
  46. user4 := models.AssertExistsAndLoadBean(t, &models.User{ID: 4}).(*models.User) //in org 3
  47. repo1 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
  48. repo3 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 3}).(*models.Repository) // own by org 3
  49. tests := []struct {
  50. user *models.User
  51. repo *models.Repository
  52. path string
  53. httpResult int
  54. addTime []int
  55. }{
  56. {user: user2, repo: repo1, path: "foo/bar.zip", httpResult: http.StatusCreated, addTime: []int{0}},
  57. {user: user2, repo: repo1, path: "path/test", httpResult: http.StatusCreated, addTime: []int{0}},
  58. {user: user2, repo: repo1, path: "path/test", httpResult: http.StatusConflict},
  59. {user: user2, repo: repo1, path: "Foo/BaR.zip", httpResult: http.StatusConflict},
  60. {user: user2, repo: repo1, path: "Foo/Test/../subFOlder/../Relative/../BaR.zip", httpResult: http.StatusConflict},
  61. {user: user4, repo: repo1, path: "FoO/BaR.zip", httpResult: http.StatusUnauthorized},
  62. {user: user4, repo: repo1, path: "path/test-user4", httpResult: http.StatusUnauthorized},
  63. {user: user2, repo: repo1, path: "patH/Test-user4", httpResult: http.StatusCreated, addTime: []int{0}},
  64. {user: user2, repo: repo1, path: "some/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/path", httpResult: http.StatusCreated, addTime: []int{0}},
  65. {user: user2, repo: repo3, path: "test/foo/bar.zip", httpResult: http.StatusCreated, addTime: []int{1, 2}},
  66. {user: user4, repo: repo3, path: "test/foo/bar.zip", httpResult: http.StatusConflict},
  67. {user: user4, repo: repo3, path: "test/foo/bar.bin", httpResult: http.StatusCreated, addTime: []int{1, 2}},
  68. }
  69. resultsTests := []struct {
  70. user *models.User
  71. repo *models.Repository
  72. totalCount int
  73. oursCount int
  74. theirsCount int
  75. locksOwners []*models.User
  76. locksTimes []time.Time
  77. }{
  78. {user: user2, repo: repo1, totalCount: 4, oursCount: 4, theirsCount: 0, locksOwners: []*models.User{user2, user2, user2, user2}, locksTimes: []time.Time{}},
  79. {user: user2, repo: repo3, totalCount: 2, oursCount: 1, theirsCount: 1, locksOwners: []*models.User{user2, user4}, locksTimes: []time.Time{}},
  80. {user: user4, repo: repo3, totalCount: 2, oursCount: 1, theirsCount: 1, locksOwners: []*models.User{user2, user4}, locksTimes: []time.Time{}},
  81. }
  82. deleteTests := []struct {
  83. user *models.User
  84. repo *models.Repository
  85. lockID string
  86. }{}
  87. //create locks
  88. for _, test := range tests {
  89. session := loginUser(t, test.user.Name)
  90. req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/%s.git/info/lfs/locks", test.repo.FullName()), map[string]string{"path": test.path})
  91. req.Header.Set("Accept", lfs.MediaType)
  92. req.Header.Set("Content-Type", lfs.MediaType)
  93. resp := session.MakeRequest(t, req, test.httpResult)
  94. if len(test.addTime) > 0 {
  95. var lfsLock api.LFSLockResponse
  96. DecodeJSON(t, resp, &lfsLock)
  97. assert.EqualValues(t, lfsLock.Lock.LockedAt.Format(time.RFC3339), lfsLock.Lock.LockedAt.Format(time.RFC3339Nano)) //locked at should be rounded to second
  98. for _, id := range test.addTime {
  99. resultsTests[id].locksTimes = append(resultsTests[id].locksTimes, time.Now())
  100. }
  101. }
  102. }
  103. //check creation
  104. for _, test := range resultsTests {
  105. session := loginUser(t, test.user.Name)
  106. req := NewRequestf(t, "GET", "/%s.git/info/lfs/locks", test.repo.FullName())
  107. req.Header.Set("Accept", lfs.MediaType)
  108. resp := session.MakeRequest(t, req, http.StatusOK)
  109. var lfsLocks api.LFSLockList
  110. DecodeJSON(t, resp, &lfsLocks)
  111. assert.Len(t, lfsLocks.Locks, test.totalCount)
  112. for i, lock := range lfsLocks.Locks {
  113. assert.EqualValues(t, test.locksOwners[i].DisplayName(), lock.Owner.Name)
  114. assert.WithinDuration(t, test.locksTimes[i], lock.LockedAt, 10*time.Second)
  115. assert.EqualValues(t, lock.LockedAt.Format(time.RFC3339), lock.LockedAt.Format(time.RFC3339Nano)) //locked at should be rounded to second
  116. }
  117. req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/%s.git/info/lfs/locks/verify", test.repo.FullName()), map[string]string{})
  118. req.Header.Set("Accept", lfs.MediaType)
  119. req.Header.Set("Content-Type", lfs.MediaType)
  120. resp = session.MakeRequest(t, req, http.StatusOK)
  121. var lfsLocksVerify api.LFSLockListVerify
  122. DecodeJSON(t, resp, &lfsLocksVerify)
  123. assert.Len(t, lfsLocksVerify.Ours, test.oursCount)
  124. assert.Len(t, lfsLocksVerify.Theirs, test.theirsCount)
  125. for _, lock := range lfsLocksVerify.Ours {
  126. assert.EqualValues(t, test.user.DisplayName(), lock.Owner.Name)
  127. deleteTests = append(deleteTests, struct {
  128. user *models.User
  129. repo *models.Repository
  130. lockID string
  131. }{test.user, test.repo, lock.ID})
  132. }
  133. for _, lock := range lfsLocksVerify.Theirs {
  134. assert.NotEqual(t, test.user.DisplayName(), lock.Owner.Name)
  135. }
  136. }
  137. //remove all locks
  138. for _, test := range deleteTests {
  139. session := loginUser(t, test.user.Name)
  140. req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/%s.git/info/lfs/locks/%s/unlock", test.repo.FullName(), test.lockID), map[string]string{})
  141. req.Header.Set("Accept", lfs.MediaType)
  142. req.Header.Set("Content-Type", lfs.MediaType)
  143. resp := session.MakeRequest(t, req, http.StatusOK)
  144. var lfsLockRep api.LFSLockResponse
  145. DecodeJSON(t, resp, &lfsLockRep)
  146. assert.Equal(t, test.lockID, lfsLockRep.Lock.ID)
  147. assert.Equal(t, test.user.DisplayName(), lfsLockRep.Lock.Owner.Name)
  148. }
  149. // check that we don't have any lock
  150. for _, test := range resultsTests {
  151. session := loginUser(t, test.user.Name)
  152. req := NewRequestf(t, "GET", "/%s.git/info/lfs/locks", test.repo.FullName())
  153. req.Header.Set("Accept", lfs.MediaType)
  154. resp := session.MakeRequest(t, req, http.StatusOK)
  155. var lfsLocks api.LFSLockList
  156. DecodeJSON(t, resp, &lfsLocks)
  157. assert.Len(t, lfsLocks.Locks, 0)
  158. }
  159. }