gitea源码

main_test.go 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. // Copyright 2022 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package cmd
  4. import (
  5. "context"
  6. "errors"
  7. "fmt"
  8. "io"
  9. "path/filepath"
  10. "strings"
  11. "testing"
  12. "code.gitea.io/gitea/models/unittest"
  13. "code.gitea.io/gitea/modules/setting"
  14. "code.gitea.io/gitea/modules/test"
  15. "github.com/stretchr/testify/assert"
  16. "github.com/urfave/cli/v3"
  17. )
  18. func TestMain(m *testing.M) {
  19. unittest.MainTest(m)
  20. }
  21. func makePathOutput(workPath, customPath, customConf string) string {
  22. return fmt.Sprintf("WorkPath=%s\nCustomPath=%s\nCustomConf=%s", workPath, customPath, customConf)
  23. }
  24. func newTestApp(testCmdAction cli.ActionFunc) *cli.Command {
  25. app := NewMainApp(AppVersion{})
  26. testCmd := &cli.Command{Name: "test-cmd", Action: testCmdAction}
  27. prepareSubcommandWithGlobalFlags(testCmd)
  28. app.Commands = append(app.Commands, testCmd)
  29. app.DefaultCommand = testCmd.Name
  30. return app
  31. }
  32. type runResult struct {
  33. Stdout string
  34. Stderr string
  35. ExitCode int
  36. }
  37. func runTestApp(app *cli.Command, args ...string) (runResult, error) {
  38. outBuf := new(strings.Builder)
  39. errBuf := new(strings.Builder)
  40. app.Writer = outBuf
  41. app.ErrWriter = errBuf
  42. exitCode := -1
  43. defer test.MockVariableValue(&cli.ErrWriter, app.ErrWriter)()
  44. defer test.MockVariableValue(&cli.OsExiter, func(code int) {
  45. if exitCode == -1 {
  46. exitCode = code // save the exit code once and then reset the writer (to simulate the exit)
  47. app.Writer, app.ErrWriter, cli.ErrWriter = io.Discard, io.Discard, io.Discard
  48. }
  49. })()
  50. err := RunMainApp(app, args...)
  51. return runResult{outBuf.String(), errBuf.String(), exitCode}, err
  52. }
  53. func TestCliCmd(t *testing.T) {
  54. defaultWorkPath := filepath.Dir(setting.AppPath)
  55. defaultCustomPath := filepath.Join(defaultWorkPath, "custom")
  56. defaultCustomConf := filepath.Join(defaultCustomPath, "conf/app.ini")
  57. cli.CommandHelpTemplate = "(command help template)"
  58. cli.RootCommandHelpTemplate = "(app help template)"
  59. cli.SubcommandHelpTemplate = "(subcommand help template)"
  60. cases := []struct {
  61. env map[string]string
  62. cmd string
  63. exp string
  64. }{
  65. // help commands
  66. {
  67. cmd: "./gitea -h",
  68. exp: "DEFAULT CONFIGURATION:",
  69. },
  70. {
  71. cmd: "./gitea help",
  72. exp: "DEFAULT CONFIGURATION:",
  73. },
  74. {
  75. cmd: "./gitea -c /dev/null -h",
  76. exp: "ConfigFile: /dev/null",
  77. },
  78. {
  79. cmd: "./gitea -c /dev/null help",
  80. exp: "ConfigFile: /dev/null",
  81. },
  82. {
  83. cmd: "./gitea help -c /dev/null",
  84. exp: "ConfigFile: /dev/null",
  85. },
  86. {
  87. cmd: "./gitea -c /dev/null test-cmd -h",
  88. exp: "ConfigFile: /dev/null",
  89. },
  90. {
  91. cmd: "./gitea test-cmd -c /dev/null -h",
  92. exp: "ConfigFile: /dev/null",
  93. },
  94. {
  95. cmd: "./gitea test-cmd -h -c /dev/null",
  96. exp: "ConfigFile: /dev/null",
  97. },
  98. {
  99. cmd: "./gitea -c /dev/null test-cmd help",
  100. exp: "ConfigFile: /dev/null",
  101. },
  102. {
  103. cmd: "./gitea test-cmd -c /dev/null help",
  104. exp: "ConfigFile: /dev/null",
  105. },
  106. {
  107. cmd: "./gitea test-cmd help -c /dev/null",
  108. exp: "ConfigFile: /dev/null",
  109. },
  110. // parse paths
  111. {
  112. cmd: "./gitea test-cmd",
  113. exp: makePathOutput(defaultWorkPath, defaultCustomPath, defaultCustomConf),
  114. },
  115. {
  116. cmd: "./gitea -c /tmp/app.ini test-cmd",
  117. exp: makePathOutput(defaultWorkPath, defaultCustomPath, "/tmp/app.ini"),
  118. },
  119. {
  120. cmd: "./gitea test-cmd -c /tmp/app.ini",
  121. exp: makePathOutput(defaultWorkPath, defaultCustomPath, "/tmp/app.ini"),
  122. },
  123. {
  124. env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
  125. cmd: "./gitea test-cmd",
  126. exp: makePathOutput("/tmp", "/tmp/custom", "/tmp/custom/conf/app.ini"),
  127. },
  128. {
  129. env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
  130. cmd: "./gitea test-cmd --work-path /tmp/other",
  131. exp: makePathOutput("/tmp/other", "/tmp/other/custom", "/tmp/other/custom/conf/app.ini"),
  132. },
  133. {
  134. env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
  135. cmd: "./gitea test-cmd --config /tmp/app-other.ini",
  136. exp: makePathOutput("/tmp", "/tmp/custom", "/tmp/app-other.ini"),
  137. },
  138. }
  139. for _, c := range cases {
  140. t.Run(c.cmd, func(t *testing.T) {
  141. app := newTestApp(func(ctx context.Context, cmd *cli.Command) error {
  142. _, _ = fmt.Fprint(cmd.Root().Writer, makePathOutput(setting.AppWorkPath, setting.CustomPath, setting.CustomConf))
  143. return nil
  144. })
  145. for k, v := range c.env {
  146. t.Setenv(k, v)
  147. }
  148. args := strings.Split(c.cmd, " ") // for test only, "split" is good enough
  149. r, err := runTestApp(app, args...)
  150. assert.NoError(t, err, c.cmd)
  151. assert.NotEmpty(t, c.exp, c.cmd)
  152. assert.Contains(t, r.Stdout, c.exp, c.cmd)
  153. })
  154. }
  155. }
  156. func TestCliCmdError(t *testing.T) {
  157. app := newTestApp(func(ctx context.Context, cmd *cli.Command) error { return errors.New("normal error") })
  158. r, err := runTestApp(app, "./gitea", "test-cmd")
  159. assert.Error(t, err)
  160. assert.Equal(t, 1, r.ExitCode)
  161. assert.Empty(t, r.Stdout)
  162. assert.Equal(t, "Command error: normal error\n", r.Stderr)
  163. app = newTestApp(func(ctx context.Context, cmd *cli.Command) error { return cli.Exit("exit error", 2) })
  164. r, err = runTestApp(app, "./gitea", "test-cmd")
  165. assert.Error(t, err)
  166. assert.Equal(t, 2, r.ExitCode)
  167. assert.Empty(t, r.Stdout)
  168. assert.Equal(t, "exit error\n", r.Stderr)
  169. app = newTestApp(func(ctx context.Context, cmd *cli.Command) error { return nil })
  170. r, err = runTestApp(app, "./gitea", "test-cmd", "--no-such")
  171. assert.Error(t, err)
  172. assert.Equal(t, 1, r.ExitCode)
  173. assert.Empty(t, r.Stdout)
  174. assert.Equal(t, "Incorrect Usage: flag provided but not defined: -no-such\n\n", r.Stderr)
  175. app = newTestApp(func(ctx context.Context, cmd *cli.Command) error { return nil })
  176. r, err = runTestApp(app, "./gitea", "test-cmd")
  177. assert.NoError(t, err)
  178. assert.Equal(t, -1, r.ExitCode) // the cli.OsExiter is not called
  179. assert.Empty(t, r.Stdout)
  180. assert.Empty(t, r.Stderr)
  181. }