gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. // Package contexttest provides utilities for testing Web/API contexts with models.
  4. package contexttest
  5. import (
  6. gocontext "context"
  7. "io"
  8. "maps"
  9. "net/http"
  10. "net/http/httptest"
  11. "net/url"
  12. "strings"
  13. "testing"
  14. "time"
  15. access_model "code.gitea.io/gitea/models/perm/access"
  16. repo_model "code.gitea.io/gitea/models/repo"
  17. "code.gitea.io/gitea/models/unittest"
  18. user_model "code.gitea.io/gitea/models/user"
  19. "code.gitea.io/gitea/modules/cache"
  20. git_module "code.gitea.io/gitea/modules/git"
  21. "code.gitea.io/gitea/modules/gitrepo"
  22. "code.gitea.io/gitea/modules/reqctx"
  23. "code.gitea.io/gitea/modules/session"
  24. "code.gitea.io/gitea/modules/templates"
  25. "code.gitea.io/gitea/modules/translation"
  26. "code.gitea.io/gitea/modules/web/middleware"
  27. "code.gitea.io/gitea/services/context"
  28. "github.com/go-chi/chi/v5"
  29. "github.com/stretchr/testify/assert"
  30. "github.com/stretchr/testify/require"
  31. )
  32. func mockRequest(t *testing.T, reqPath string) *http.Request {
  33. method, path, found := strings.Cut(reqPath, " ")
  34. if !found {
  35. method = "GET"
  36. path = reqPath
  37. }
  38. requestURL, err := url.Parse(path)
  39. assert.NoError(t, err)
  40. req := &http.Request{Method: method, Host: requestURL.Host, URL: requestURL, Form: maps.Clone(requestURL.Query()), Header: http.Header{}}
  41. req = req.WithContext(reqctx.NewRequestContextForTest(req.Context()))
  42. return req
  43. }
  44. type MockContextOption struct {
  45. Render context.Render
  46. SessionStore session.Store
  47. }
  48. // MockContext mock context for unit tests
  49. func MockContext(t *testing.T, reqPath string, opts ...MockContextOption) (*context.Context, *httptest.ResponseRecorder) {
  50. var opt MockContextOption
  51. if len(opts) > 0 {
  52. opt = opts[0]
  53. }
  54. if opt.Render == nil {
  55. opt.Render = &MockRender{}
  56. }
  57. resp := httptest.NewRecorder()
  58. req := mockRequest(t, reqPath)
  59. base := context.NewBaseContext(resp, req)
  60. base.Data = middleware.GetContextData(req.Context())
  61. base.Locale = &translation.MockLocale{}
  62. chiCtx := chi.NewRouteContext()
  63. ctx := context.NewWebContext(base, opt.Render, nil)
  64. ctx.SetContextValue(chi.RouteCtxKey, chiCtx)
  65. if opt.SessionStore != nil {
  66. ctx.SetContextValue(session.MockStoreContextKey, opt.SessionStore)
  67. ctx.Session = opt.SessionStore
  68. }
  69. ctx.Cache = cache.GetCache()
  70. ctx.PageData = map[string]any{}
  71. ctx.Data["PageStartTime"] = time.Now()
  72. return ctx, resp
  73. }
  74. // MockAPIContext mock context for unit tests
  75. func MockAPIContext(t *testing.T, reqPath string) (*context.APIContext, *httptest.ResponseRecorder) {
  76. resp := httptest.NewRecorder()
  77. req := mockRequest(t, reqPath)
  78. base := context.NewBaseContext(resp, req)
  79. base.Data = middleware.GetContextData(req.Context())
  80. base.Locale = &translation.MockLocale{}
  81. ctx := &context.APIContext{Base: base, Repo: &context.Repository{}}
  82. chiCtx := chi.NewRouteContext()
  83. ctx.SetContextValue(chi.RouteCtxKey, chiCtx)
  84. return ctx, resp
  85. }
  86. func MockPrivateContext(t *testing.T, reqPath string) (*context.PrivateContext, *httptest.ResponseRecorder) {
  87. resp := httptest.NewRecorder()
  88. req := mockRequest(t, reqPath)
  89. base := context.NewBaseContext(resp, req)
  90. base.Data = middleware.GetContextData(req.Context())
  91. base.Locale = &translation.MockLocale{}
  92. ctx := &context.PrivateContext{Base: base}
  93. chiCtx := chi.NewRouteContext()
  94. ctx.SetContextValue(chi.RouteCtxKey, chiCtx)
  95. return ctx, resp
  96. }
  97. // LoadRepo load a repo into a test context.
  98. func LoadRepo(t *testing.T, ctx gocontext.Context, repoID int64) {
  99. var doer *user_model.User
  100. var repo *context.Repository
  101. switch ctx := ctx.(type) {
  102. case *context.Context:
  103. repo = ctx.Repo
  104. doer = ctx.Doer
  105. case *context.APIContext:
  106. repo = ctx.Repo
  107. doer = ctx.Doer
  108. default:
  109. assert.FailNow(t, "context is not *context.Context or *context.APIContext")
  110. }
  111. repo.Repository = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID})
  112. var err error
  113. repo.Owner, err = user_model.GetUserByID(ctx, repo.Repository.OwnerID)
  114. assert.NoError(t, err)
  115. repo.RepoLink = repo.Repository.Link()
  116. repo.Permission, err = access_model.GetUserRepoPermission(ctx, repo.Repository, doer)
  117. assert.NoError(t, err)
  118. }
  119. // LoadRepoCommit loads a repo's commit into a test context.
  120. func LoadRepoCommit(t *testing.T, ctx gocontext.Context) {
  121. var repo *context.Repository
  122. switch ctx := ctx.(type) {
  123. case *context.Context:
  124. repo = ctx.Repo
  125. case *context.APIContext:
  126. repo = ctx.Repo
  127. default:
  128. assert.FailNow(t, "context is not *context.Context or *context.APIContext")
  129. }
  130. gitRepo, err := gitrepo.OpenRepository(ctx, repo.Repository)
  131. require.NoError(t, err)
  132. defer gitRepo.Close()
  133. if repo.RefFullName == "" {
  134. repo.RefFullName = git_module.RefNameFromBranch(repo.Repository.DefaultBranch)
  135. }
  136. if repo.RefFullName.IsPull() {
  137. repo.BranchName = repo.RefFullName.ShortName()
  138. }
  139. repo.Commit, err = gitRepo.GetCommit(repo.RefFullName.String())
  140. require.NoError(t, err)
  141. }
  142. // LoadUser load a user into a test context
  143. func LoadUser(t *testing.T, ctx gocontext.Context, userID int64) {
  144. doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID})
  145. switch ctx := ctx.(type) {
  146. case *context.Context:
  147. ctx.Doer = doer
  148. case *context.APIContext:
  149. ctx.Doer = doer
  150. default:
  151. assert.FailNow(t, "context is not *context.Context or *context.APIContext")
  152. }
  153. }
  154. // LoadGitRepo load a git repo into a test context. Requires that ctx.Repo has
  155. // already been populated.
  156. func LoadGitRepo(t *testing.T, ctx gocontext.Context) {
  157. var repo *context.Repository
  158. switch ctx := any(ctx).(type) {
  159. case *context.Context:
  160. repo = ctx.Repo
  161. case *context.APIContext:
  162. repo = ctx.Repo
  163. default:
  164. assert.FailNow(t, "context is not *context.Context or *context.APIContext")
  165. }
  166. assert.NoError(t, repo.Repository.LoadOwner(ctx))
  167. var err error
  168. repo.GitRepo, err = gitrepo.OpenRepository(ctx, repo.Repository)
  169. assert.NoError(t, err)
  170. }
  171. type MockRender struct{}
  172. func (tr *MockRender) TemplateLookup(tmpl string, _ gocontext.Context) (templates.TemplateExecutor, error) {
  173. return nil, nil
  174. }
  175. func (tr *MockRender) HTML(w io.Writer, status int, _ templates.TplName, _ any, _ gocontext.Context) error {
  176. if resp, ok := w.(http.ResponseWriter); ok {
  177. resp.WriteHeader(status)
  178. }
  179. return nil
  180. }