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.

test_utils.go 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package tests
  4. import (
  5. "context"
  6. "database/sql"
  7. "fmt"
  8. "os"
  9. "path"
  10. "path/filepath"
  11. "runtime"
  12. "testing"
  13. "code.gitea.io/gitea/models/unittest"
  14. "code.gitea.io/gitea/modules/base"
  15. "code.gitea.io/gitea/modules/git"
  16. "code.gitea.io/gitea/modules/graceful"
  17. "code.gitea.io/gitea/modules/log"
  18. "code.gitea.io/gitea/modules/queue"
  19. repo_module "code.gitea.io/gitea/modules/repository"
  20. "code.gitea.io/gitea/modules/setting"
  21. "code.gitea.io/gitea/modules/storage"
  22. "code.gitea.io/gitea/modules/util"
  23. "code.gitea.io/gitea/routers"
  24. "github.com/stretchr/testify/assert"
  25. )
  26. func InitTest(requireGitea bool) {
  27. giteaRoot := base.SetupGiteaRoot()
  28. if giteaRoot == "" {
  29. fmt.Println("Environment variable $GITEA_ROOT not set")
  30. os.Exit(1)
  31. }
  32. if requireGitea {
  33. giteaBinary := "gitea"
  34. if runtime.GOOS == "windows" {
  35. giteaBinary += ".exe"
  36. }
  37. setting.AppPath = path.Join(giteaRoot, giteaBinary)
  38. if _, err := os.Stat(setting.AppPath); err != nil {
  39. fmt.Printf("Could not find gitea binary at %s\n", setting.AppPath)
  40. os.Exit(1)
  41. }
  42. }
  43. giteaConf := os.Getenv("GITEA_CONF")
  44. if giteaConf == "" {
  45. fmt.Println("Environment variable $GITEA_CONF not set")
  46. os.Exit(1)
  47. } else if !path.IsAbs(giteaConf) {
  48. setting.CustomConf = path.Join(giteaRoot, giteaConf)
  49. } else {
  50. setting.CustomConf = giteaConf
  51. }
  52. setting.SetCustomPathAndConf("", "", "")
  53. setting.LoadForTest()
  54. setting.Repository.DefaultBranch = "master" // many test code still assume that default branch is called "master"
  55. _ = util.RemoveAll(repo_module.LocalCopyPath())
  56. if err := git.InitFull(context.Background()); err != nil {
  57. log.Fatal("git.InitOnceWithSync: %v", err)
  58. }
  59. setting.InitDBConfig()
  60. if err := storage.Init(); err != nil {
  61. fmt.Printf("Init storage failed: %v", err)
  62. os.Exit(1)
  63. }
  64. switch {
  65. case setting.Database.UseMySQL:
  66. connType := "tcp"
  67. if len(setting.Database.Host) > 0 && setting.Database.Host[0] == '/' { // looks like a unix socket
  68. connType = "unix"
  69. }
  70. db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@%s(%s)/",
  71. setting.Database.User, setting.Database.Passwd, connType, setting.Database.Host))
  72. defer db.Close()
  73. if err != nil {
  74. log.Fatal("sql.Open: %v", err)
  75. }
  76. if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", setting.Database.Name)); err != nil {
  77. log.Fatal("db.Exec: %v", err)
  78. }
  79. case setting.Database.UsePostgreSQL:
  80. var db *sql.DB
  81. var err error
  82. if setting.Database.Host[0] == '/' {
  83. db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@/%s?sslmode=%s&host=%s",
  84. setting.Database.User, setting.Database.Passwd, setting.Database.Name, setting.Database.SSLMode, setting.Database.Host))
  85. } else {
  86. db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
  87. setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode))
  88. }
  89. defer db.Close()
  90. if err != nil {
  91. log.Fatal("sql.Open: %v", err)
  92. }
  93. dbrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM pg_database WHERE datname = '%s'", setting.Database.Name))
  94. if err != nil {
  95. log.Fatal("db.Query: %v", err)
  96. }
  97. defer dbrows.Close()
  98. if !dbrows.Next() {
  99. if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", setting.Database.Name)); err != nil {
  100. log.Fatal("db.Exec: CREATE DATABASE: %v", err)
  101. }
  102. }
  103. // Check if we need to setup a specific schema
  104. if len(setting.Database.Schema) == 0 {
  105. break
  106. }
  107. db.Close()
  108. if setting.Database.Host[0] == '/' {
  109. db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@/%s?sslmode=%s&host=%s",
  110. setting.Database.User, setting.Database.Passwd, setting.Database.Name, setting.Database.SSLMode, setting.Database.Host))
  111. } else {
  112. db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
  113. setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode))
  114. }
  115. // This is a different db object; requires a different Close()
  116. defer db.Close()
  117. if err != nil {
  118. log.Fatal("sql.Open: %v", err)
  119. }
  120. schrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM information_schema.schemata WHERE schema_name = '%s'", setting.Database.Schema))
  121. if err != nil {
  122. log.Fatal("db.Query: %v", err)
  123. }
  124. defer schrows.Close()
  125. if !schrows.Next() {
  126. // Create and setup a DB schema
  127. if _, err = db.Exec(fmt.Sprintf("CREATE SCHEMA %s", setting.Database.Schema)); err != nil {
  128. log.Fatal("db.Exec: CREATE SCHEMA: %v", err)
  129. }
  130. }
  131. case setting.Database.UseMSSQL:
  132. host, port := setting.ParseMSSQLHostPort(setting.Database.Host)
  133. db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
  134. host, port, "master", setting.Database.User, setting.Database.Passwd))
  135. if err != nil {
  136. log.Fatal("sql.Open: %v", err)
  137. }
  138. if _, err := db.Exec(fmt.Sprintf("If(db_id(N'%s') IS NULL) BEGIN CREATE DATABASE %s; END;", setting.Database.Name, setting.Database.Name)); err != nil {
  139. log.Fatal("db.Exec: %v", err)
  140. }
  141. defer db.Close()
  142. }
  143. routers.GlobalInitInstalled(graceful.GetManager().HammerContext())
  144. }
  145. func PrepareTestEnv(t testing.TB, skip ...int) func() {
  146. t.Helper()
  147. ourSkip := 2
  148. if len(skip) > 0 {
  149. ourSkip += skip[0]
  150. }
  151. deferFn := PrintCurrentTest(t, ourSkip)
  152. // load database fixtures
  153. assert.NoError(t, unittest.LoadFixtures())
  154. // load git repo fixtures
  155. assert.NoError(t, util.RemoveAll(setting.RepoRootPath))
  156. assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "tests/gitea-repositories-meta"), setting.RepoRootPath))
  157. ownerDirs, err := os.ReadDir(setting.RepoRootPath)
  158. if err != nil {
  159. assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
  160. }
  161. for _, ownerDir := range ownerDirs {
  162. if !ownerDir.Type().IsDir() {
  163. continue
  164. }
  165. repoDirs, err := os.ReadDir(filepath.Join(setting.RepoRootPath, ownerDir.Name()))
  166. if err != nil {
  167. assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
  168. }
  169. for _, repoDir := range repoDirs {
  170. _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "pack"), 0o755)
  171. _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "info"), 0o755)
  172. _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "heads"), 0o755)
  173. _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "tag"), 0o755)
  174. }
  175. }
  176. // load LFS object fixtures
  177. // (LFS storage can be on any of several backends, including remote servers, so we init it with the storage API)
  178. lfsFixtures, err := storage.NewStorage("", storage.LocalStorageConfig{Path: path.Join(filepath.Dir(setting.AppPath), "tests/gitea-lfs-meta")})
  179. assert.NoError(t, err)
  180. assert.NoError(t, storage.Clean(storage.LFS))
  181. assert.NoError(t, lfsFixtures.IterateObjects(func(path string, _ storage.Object) error {
  182. _, err := storage.Copy(storage.LFS, path, lfsFixtures, path)
  183. return err
  184. }))
  185. return deferFn
  186. }
  187. // resetFixtures flushes queues, reloads fixtures and resets test repositories within a single test.
  188. // Most tests should call defer tests.PrepareTestEnv(t)() (or have onGiteaRun do that for them) but sometimes
  189. // within a single test this is required
  190. func ResetFixtures(t *testing.T) {
  191. assert.NoError(t, queue.GetManager().FlushAll(context.Background(), -1))
  192. // load database fixtures
  193. assert.NoError(t, unittest.LoadFixtures())
  194. // load git repo fixtures
  195. assert.NoError(t, util.RemoveAll(setting.RepoRootPath))
  196. assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "tests/gitea-repositories-meta"), setting.RepoRootPath))
  197. ownerDirs, err := os.ReadDir(setting.RepoRootPath)
  198. if err != nil {
  199. assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
  200. }
  201. for _, ownerDir := range ownerDirs {
  202. if !ownerDir.Type().IsDir() {
  203. continue
  204. }
  205. repoDirs, err := os.ReadDir(filepath.Join(setting.RepoRootPath, ownerDir.Name()))
  206. if err != nil {
  207. assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
  208. }
  209. for _, repoDir := range repoDirs {
  210. _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "pack"), 0o755)
  211. _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "info"), 0o755)
  212. _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "heads"), 0o755)
  213. _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "tag"), 0o755)
  214. }
  215. }
  216. // load LFS object fixtures
  217. // (LFS storage can be on any of several backends, including remote servers, so we init it with the storage API)
  218. lfsFixtures, err := storage.NewStorage("", storage.LocalStorageConfig{Path: path.Join(filepath.Dir(setting.AppPath), "tests/gitea-lfs-meta")})
  219. assert.NoError(t, err)
  220. assert.NoError(t, storage.Clean(storage.LFS))
  221. assert.NoError(t, lfsFixtures.IterateObjects(func(path string, _ storage.Object) error {
  222. _, err := storage.Copy(storage.LFS, path, lfsFixtures, path)
  223. return err
  224. }))
  225. }