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.

main_test.go 5.2KB

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