Improve testing init, clean up webhook tests (#37412)
Avoid webhook test fixtures affect other tests (be triggered) Also fixed more testing problems including path init, global config pollution & conflict --------- Signed-off-by: silverwind <me@silverwind.io> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: wxiaoguang <2114189+wxiaoguang@users.noreply.github.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
@@ -1,38 +0,0 @@
|
|||||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/urfave/cli/v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDefaultCommand(t *testing.T) {
|
|
||||||
test := func(t *testing.T, args []string, expectedRetName string, expectedRetValid bool) {
|
|
||||||
called := false
|
|
||||||
cmd := &cli.Command{
|
|
||||||
DefaultCommand: "test",
|
|
||||||
Commands: []*cli.Command{
|
|
||||||
{
|
|
||||||
Name: "test",
|
|
||||||
Action: func(ctx context.Context, command *cli.Command) error {
|
|
||||||
retName, retValid := isValidDefaultSubCommand(command)
|
|
||||||
assert.Equal(t, expectedRetName, retName)
|
|
||||||
assert.Equal(t, expectedRetValid, retValid)
|
|
||||||
called = true
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
assert.NoError(t, cmd.Run(t.Context(), args))
|
|
||||||
assert.True(t, called)
|
|
||||||
}
|
|
||||||
test(t, []string{"./gitea"}, "", true)
|
|
||||||
test(t, []string{"./gitea", "test"}, "", true)
|
|
||||||
test(t, []string{"./gitea", "other"}, "other", false)
|
|
||||||
}
|
|
||||||
237
cmd/cmdtest/cmd_test.go
Normal file
237
cmd/cmdtest/cmd_test.go
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
// Tests here reload the config system multiple times with uncontrollable details.
|
||||||
|
// So they must be in a separate package, to avoid affecting other tests
|
||||||
|
|
||||||
|
package cmdtest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/cmd"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/test"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/urfave/cli/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
unittest.MainTest(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makePathOutput(workPath, customPath, customConf string) string {
|
||||||
|
return fmt.Sprintf("WorkPath=%s\nCustomPath=%s\nCustomConf=%s", workPath, customPath, customConf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTestApp(testCmd cli.Command) *cli.Command {
|
||||||
|
app := cmd.NewMainApp(cmd.AppVersion{})
|
||||||
|
testCmd.Name = util.IfZero(testCmd.Name, "test-cmd")
|
||||||
|
cmd.PrepareSubcommandWithGlobalFlags(&testCmd)
|
||||||
|
app.Commands = append(app.Commands, &testCmd)
|
||||||
|
app.DefaultCommand = testCmd.Name
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
type runResult struct {
|
||||||
|
Stdout string
|
||||||
|
Stderr string
|
||||||
|
ExitCode int
|
||||||
|
}
|
||||||
|
|
||||||
|
func runTestApp(app *cli.Command, args ...string) (runResult, error) {
|
||||||
|
outBuf := new(strings.Builder)
|
||||||
|
errBuf := new(strings.Builder)
|
||||||
|
app.Writer = outBuf
|
||||||
|
app.ErrWriter = errBuf
|
||||||
|
exitCode := -1
|
||||||
|
defer test.MockVariableValue(&cli.ErrWriter, app.ErrWriter)()
|
||||||
|
defer test.MockVariableValue(&cli.OsExiter, func(code int) {
|
||||||
|
if exitCode == -1 {
|
||||||
|
exitCode = code // save the exit code once and then reset the writer (to simulate the exit)
|
||||||
|
app.Writer, app.ErrWriter, cli.ErrWriter = io.Discard, io.Discard, io.Discard
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
err := cmd.RunMainApp(app, args...)
|
||||||
|
return runResult{outBuf.String(), errBuf.String(), exitCode}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCliCmd(t *testing.T) {
|
||||||
|
defaultWorkPath := filepath.FromSlash("/tmp/mocked-work-path")
|
||||||
|
defaultCustomPath := filepath.Join(defaultWorkPath, "custom")
|
||||||
|
defaultCustomConf := filepath.Join(defaultCustomPath, "conf/app.ini")
|
||||||
|
defer setting.MockBuiltinPaths(defaultWorkPath, "", "")()
|
||||||
|
|
||||||
|
cli.CommandHelpTemplate = "(command help template)"
|
||||||
|
cli.RootCommandHelpTemplate = "(app help template)"
|
||||||
|
cli.SubcommandHelpTemplate = "(subcommand help template)"
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
env map[string]string
|
||||||
|
cmd string
|
||||||
|
exp string
|
||||||
|
}{
|
||||||
|
// help commands
|
||||||
|
{
|
||||||
|
cmd: "./gitea -h",
|
||||||
|
exp: "DEFAULT CONFIGURATION:",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cmd: "./gitea help",
|
||||||
|
exp: "DEFAULT CONFIGURATION:",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
cmd: "./gitea -c /dev/null -h",
|
||||||
|
exp: "ConfigFile: /dev/null",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
cmd: "./gitea -c /dev/null help",
|
||||||
|
exp: "ConfigFile: /dev/null",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cmd: "./gitea help -c /dev/null",
|
||||||
|
exp: "ConfigFile: /dev/null",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
cmd: "./gitea -c /dev/null test-cmd -h",
|
||||||
|
exp: "ConfigFile: /dev/null",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cmd: "./gitea test-cmd -c /dev/null -h",
|
||||||
|
exp: "ConfigFile: /dev/null",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cmd: "./gitea test-cmd -h -c /dev/null",
|
||||||
|
exp: "ConfigFile: /dev/null",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
cmd: "./gitea -c /dev/null test-cmd help",
|
||||||
|
exp: "ConfigFile: /dev/null",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cmd: "./gitea test-cmd -c /dev/null help",
|
||||||
|
exp: "ConfigFile: /dev/null",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cmd: "./gitea test-cmd help -c /dev/null",
|
||||||
|
exp: "ConfigFile: /dev/null",
|
||||||
|
},
|
||||||
|
|
||||||
|
// parse paths
|
||||||
|
{
|
||||||
|
cmd: "./gitea test-cmd",
|
||||||
|
exp: makePathOutput(defaultWorkPath, defaultCustomPath, defaultCustomConf),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cmd: "./gitea -c /tmp/app.ini test-cmd",
|
||||||
|
exp: makePathOutput(defaultWorkPath, defaultCustomPath, "/tmp/app.ini"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cmd: "./gitea test-cmd -c /tmp/app.ini",
|
||||||
|
exp: makePathOutput(defaultWorkPath, defaultCustomPath, "/tmp/app.ini"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
|
||||||
|
cmd: "./gitea test-cmd",
|
||||||
|
exp: makePathOutput("/tmp", "/tmp/custom", "/tmp/custom/conf/app.ini"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
|
||||||
|
cmd: "./gitea test-cmd --work-path /tmp/other",
|
||||||
|
exp: makePathOutput("/tmp/other", "/tmp/other/custom", "/tmp/other/custom/conf/app.ini"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
|
||||||
|
cmd: "./gitea test-cmd --config /tmp/app-other.ini",
|
||||||
|
exp: makePathOutput("/tmp", "/tmp/custom", "/tmp/app-other.ini"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
t.Run(c.cmd, func(t *testing.T) {
|
||||||
|
app := newTestApp(cli.Command{
|
||||||
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
_, _ = fmt.Fprint(cmd.Root().Writer, makePathOutput(setting.AppWorkPath, setting.CustomPath, setting.CustomConf))
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
for k, v := range c.env {
|
||||||
|
t.Setenv(k, v)
|
||||||
|
}
|
||||||
|
args := strings.Split(c.cmd, " ") // for test only, "split" is good enough
|
||||||
|
r, err := runTestApp(app, args...)
|
||||||
|
assert.NoError(t, err, c.cmd)
|
||||||
|
assert.NotEmpty(t, c.exp, c.cmd)
|
||||||
|
if !assert.Contains(t, r.Stdout, c.exp, c.cmd) {
|
||||||
|
t.Log("Full output:\n" + r.Stdout)
|
||||||
|
t.Log("Expected:\n" + c.exp)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCliCmdError(t *testing.T) {
|
||||||
|
app := newTestApp(cli.Command{Action: func(ctx context.Context, cmd *cli.Command) error { return errors.New("normal error") }})
|
||||||
|
r, err := runTestApp(app, "./gitea", "test-cmd")
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, 1, r.ExitCode)
|
||||||
|
assert.Empty(t, r.Stdout)
|
||||||
|
assert.Equal(t, "Command error: normal error\n", r.Stderr)
|
||||||
|
|
||||||
|
app = newTestApp(cli.Command{Action: func(ctx context.Context, cmd *cli.Command) error { return cli.Exit("exit error", 2) }})
|
||||||
|
r, err = runTestApp(app, "./gitea", "test-cmd")
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, 2, r.ExitCode)
|
||||||
|
assert.Empty(t, r.Stdout)
|
||||||
|
assert.Equal(t, "exit error\n", r.Stderr)
|
||||||
|
|
||||||
|
app = newTestApp(cli.Command{Action: func(ctx context.Context, cmd *cli.Command) error { return nil }})
|
||||||
|
r, err = runTestApp(app, "./gitea", "test-cmd", "--no-such")
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, 1, r.ExitCode)
|
||||||
|
assert.Empty(t, r.Stdout)
|
||||||
|
assert.Equal(t, "Incorrect Usage: flag provided but not defined: -no-such\n\n", r.Stderr)
|
||||||
|
|
||||||
|
app = newTestApp(cli.Command{Action: func(ctx context.Context, cmd *cli.Command) error { return nil }})
|
||||||
|
r, err = runTestApp(app, "./gitea", "test-cmd")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, -1, r.ExitCode) // the cli.OsExiter is not called
|
||||||
|
assert.Empty(t, r.Stdout)
|
||||||
|
assert.Empty(t, r.Stderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCliCmdBefore(t *testing.T) {
|
||||||
|
ctxNew := context.WithValue(context.Background(), any("key"), "value")
|
||||||
|
configValues := map[string]string{}
|
||||||
|
setting.CustomConf = "/tmp/any.ini"
|
||||||
|
var actionCtx context.Context
|
||||||
|
app := newTestApp(cli.Command{
|
||||||
|
Before: func(context.Context, *cli.Command) (context.Context, error) {
|
||||||
|
configValues["before"] = setting.CustomConf
|
||||||
|
return ctxNew, nil
|
||||||
|
},
|
||||||
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
configValues["action"] = setting.CustomConf
|
||||||
|
actionCtx = ctx
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
_, err := runTestApp(app, "./gitea", "--config", "/dev/null", "test-cmd")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, ctxNew, actionCtx)
|
||||||
|
assert.Equal(t, "/tmp/any.ini", configValues["before"], "BeforeFunc must be called before preparing config")
|
||||||
|
assert.Equal(t, "/dev/null", configValues["action"])
|
||||||
|
}
|
||||||
@@ -48,7 +48,7 @@ DEFAULT CONFIGURATION:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareSubcommandWithGlobalFlags(originCmd *cli.Command) {
|
func PrepareSubcommandWithGlobalFlags(originCmd *cli.Command) {
|
||||||
originBefore := originCmd.Before
|
originBefore := originCmd.Before
|
||||||
originCmd.Before = func(ctxOrig context.Context, cmd *cli.Command) (ctx context.Context, err error) {
|
originCmd.Before = func(ctxOrig context.Context, cmd *cli.Command) (ctx context.Context, err error) {
|
||||||
ctx = ctxOrig
|
ctx = ctxOrig
|
||||||
@@ -145,7 +145,7 @@ func NewMainApp(appVer AppVersion) *cli.Command {
|
|||||||
|
|
||||||
app.Before = PrepareConsoleLoggerLevel(log.INFO)
|
app.Before = PrepareConsoleLoggerLevel(log.INFO)
|
||||||
for i := range subCmdWithConfig {
|
for i := range subCmdWithConfig {
|
||||||
prepareSubcommandWithGlobalFlags(subCmdWithConfig[i])
|
PrepareSubcommandWithGlobalFlags(subCmdWithConfig[i])
|
||||||
}
|
}
|
||||||
app.Commands = append(app.Commands, subCmdWithConfig...)
|
app.Commands = append(app.Commands, subCmdWithConfig...)
|
||||||
app.Commands = append(app.Commands, subCmdStandalone...)
|
app.Commands = append(app.Commands, subCmdStandalone...)
|
||||||
|
|||||||
233
cmd/main_test.go
233
cmd/main_test.go
@@ -5,17 +5,9 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
"code.gitea.io/gitea/modules/test"
|
|
||||||
"code.gitea.io/gitea/modules/util"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
@@ -25,209 +17,28 @@ func TestMain(m *testing.M) {
|
|||||||
unittest.MainTest(m)
|
unittest.MainTest(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func makePathOutput(workPath, customPath, customConf string) string {
|
func TestDefaultCommand(t *testing.T) {
|
||||||
return fmt.Sprintf("WorkPath=%s\nCustomPath=%s\nCustomConf=%s", workPath, customPath, customConf)
|
test := func(t *testing.T, args []string, expectedRetName string, expectedRetValid bool) {
|
||||||
}
|
called := false
|
||||||
|
cmd := &cli.Command{
|
||||||
func newTestApp(testCmd cli.Command) *cli.Command {
|
DefaultCommand: "test",
|
||||||
app := NewMainApp(AppVersion{})
|
Commands: []*cli.Command{
|
||||||
testCmd.Name = util.IfZero(testCmd.Name, "test-cmd")
|
{
|
||||||
prepareSubcommandWithGlobalFlags(&testCmd)
|
Name: "test",
|
||||||
app.Commands = append(app.Commands, &testCmd)
|
Action: func(ctx context.Context, command *cli.Command) error {
|
||||||
app.DefaultCommand = testCmd.Name
|
retName, retValid := isValidDefaultSubCommand(command)
|
||||||
return app
|
assert.Equal(t, expectedRetName, retName)
|
||||||
}
|
assert.Equal(t, expectedRetValid, retValid)
|
||||||
|
called = true
|
||||||
type runResult struct {
|
return nil
|
||||||
Stdout string
|
},
|
||||||
Stderr string
|
|
||||||
ExitCode int
|
|
||||||
}
|
|
||||||
|
|
||||||
func runTestApp(app *cli.Command, args ...string) (runResult, error) {
|
|
||||||
outBuf := new(strings.Builder)
|
|
||||||
errBuf := new(strings.Builder)
|
|
||||||
app.Writer = outBuf
|
|
||||||
app.ErrWriter = errBuf
|
|
||||||
exitCode := -1
|
|
||||||
defer test.MockVariableValue(&cli.ErrWriter, app.ErrWriter)()
|
|
||||||
defer test.MockVariableValue(&cli.OsExiter, func(code int) {
|
|
||||||
if exitCode == -1 {
|
|
||||||
exitCode = code // save the exit code once and then reset the writer (to simulate the exit)
|
|
||||||
app.Writer, app.ErrWriter, cli.ErrWriter = io.Discard, io.Discard, io.Discard
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
err := RunMainApp(app, args...)
|
|
||||||
return runResult{outBuf.String(), errBuf.String(), exitCode}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCliCmd(t *testing.T) {
|
|
||||||
defaultWorkPath := filepath.FromSlash("/tmp/mocked-work-path")
|
|
||||||
defaultCustomPath := filepath.Join(defaultWorkPath, "custom")
|
|
||||||
defaultCustomConf := filepath.Join(defaultCustomPath, "conf/app.ini")
|
|
||||||
defer setting.MockBuiltinPaths(defaultWorkPath, "", "")()
|
|
||||||
|
|
||||||
cli.CommandHelpTemplate = "(command help template)"
|
|
||||||
cli.RootCommandHelpTemplate = "(app help template)"
|
|
||||||
cli.SubcommandHelpTemplate = "(subcommand help template)"
|
|
||||||
|
|
||||||
cases := []struct {
|
|
||||||
env map[string]string
|
|
||||||
cmd string
|
|
||||||
exp string
|
|
||||||
}{
|
|
||||||
// help commands
|
|
||||||
{
|
|
||||||
cmd: "./gitea -h",
|
|
||||||
exp: "DEFAULT CONFIGURATION:",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cmd: "./gitea help",
|
|
||||||
exp: "DEFAULT CONFIGURATION:",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
cmd: "./gitea -c /dev/null -h",
|
|
||||||
exp: "ConfigFile: /dev/null",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
cmd: "./gitea -c /dev/null help",
|
|
||||||
exp: "ConfigFile: /dev/null",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cmd: "./gitea help -c /dev/null",
|
|
||||||
exp: "ConfigFile: /dev/null",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
cmd: "./gitea -c /dev/null test-cmd -h",
|
|
||||||
exp: "ConfigFile: /dev/null",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cmd: "./gitea test-cmd -c /dev/null -h",
|
|
||||||
exp: "ConfigFile: /dev/null",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cmd: "./gitea test-cmd -h -c /dev/null",
|
|
||||||
exp: "ConfigFile: /dev/null",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
cmd: "./gitea -c /dev/null test-cmd help",
|
|
||||||
exp: "ConfigFile: /dev/null",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cmd: "./gitea test-cmd -c /dev/null help",
|
|
||||||
exp: "ConfigFile: /dev/null",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cmd: "./gitea test-cmd help -c /dev/null",
|
|
||||||
exp: "ConfigFile: /dev/null",
|
|
||||||
},
|
|
||||||
|
|
||||||
// parse paths
|
|
||||||
{
|
|
||||||
cmd: "./gitea test-cmd",
|
|
||||||
exp: makePathOutput(defaultWorkPath, defaultCustomPath, defaultCustomConf),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cmd: "./gitea -c /tmp/app.ini test-cmd",
|
|
||||||
exp: makePathOutput(defaultWorkPath, defaultCustomPath, "/tmp/app.ini"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cmd: "./gitea test-cmd -c /tmp/app.ini",
|
|
||||||
exp: makePathOutput(defaultWorkPath, defaultCustomPath, "/tmp/app.ini"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
|
|
||||||
cmd: "./gitea test-cmd",
|
|
||||||
exp: makePathOutput("/tmp", "/tmp/custom", "/tmp/custom/conf/app.ini"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
|
|
||||||
cmd: "./gitea test-cmd --work-path /tmp/other",
|
|
||||||
exp: makePathOutput("/tmp/other", "/tmp/other/custom", "/tmp/other/custom/conf/app.ini"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
|
|
||||||
cmd: "./gitea test-cmd --config /tmp/app-other.ini",
|
|
||||||
exp: makePathOutput("/tmp", "/tmp/custom", "/tmp/app-other.ini"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range cases {
|
|
||||||
t.Run(c.cmd, func(t *testing.T) {
|
|
||||||
app := newTestApp(cli.Command{
|
|
||||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
|
||||||
_, _ = fmt.Fprint(cmd.Root().Writer, makePathOutput(setting.AppWorkPath, setting.CustomPath, setting.CustomConf))
|
|
||||||
return nil
|
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
for k, v := range c.env {
|
}
|
||||||
t.Setenv(k, v)
|
assert.NoError(t, cmd.Run(t.Context(), args))
|
||||||
}
|
assert.True(t, called)
|
||||||
args := strings.Split(c.cmd, " ") // for test only, "split" is good enough
|
|
||||||
r, err := runTestApp(app, args...)
|
|
||||||
assert.NoError(t, err, c.cmd)
|
|
||||||
assert.NotEmpty(t, c.exp, c.cmd)
|
|
||||||
if !assert.Contains(t, r.Stdout, c.exp, c.cmd) {
|
|
||||||
t.Log("Full output:\n" + r.Stdout)
|
|
||||||
t.Log("Expected:\n" + c.exp)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
test(t, []string{"./gitea"}, "", true)
|
||||||
|
test(t, []string{"./gitea", "test"}, "", true)
|
||||||
func TestCliCmdError(t *testing.T) {
|
test(t, []string{"./gitea", "other"}, "other", false)
|
||||||
app := newTestApp(cli.Command{Action: func(ctx context.Context, cmd *cli.Command) error { return errors.New("normal error") }})
|
|
||||||
r, err := runTestApp(app, "./gitea", "test-cmd")
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.Equal(t, 1, r.ExitCode)
|
|
||||||
assert.Empty(t, r.Stdout)
|
|
||||||
assert.Equal(t, "Command error: normal error\n", r.Stderr)
|
|
||||||
|
|
||||||
app = newTestApp(cli.Command{Action: func(ctx context.Context, cmd *cli.Command) error { return cli.Exit("exit error", 2) }})
|
|
||||||
r, err = runTestApp(app, "./gitea", "test-cmd")
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.Equal(t, 2, r.ExitCode)
|
|
||||||
assert.Empty(t, r.Stdout)
|
|
||||||
assert.Equal(t, "exit error\n", r.Stderr)
|
|
||||||
|
|
||||||
app = newTestApp(cli.Command{Action: func(ctx context.Context, cmd *cli.Command) error { return nil }})
|
|
||||||
r, err = runTestApp(app, "./gitea", "test-cmd", "--no-such")
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.Equal(t, 1, r.ExitCode)
|
|
||||||
assert.Empty(t, r.Stdout)
|
|
||||||
assert.Equal(t, "Incorrect Usage: flag provided but not defined: -no-such\n\n", r.Stderr)
|
|
||||||
|
|
||||||
app = newTestApp(cli.Command{Action: func(ctx context.Context, cmd *cli.Command) error { return nil }})
|
|
||||||
r, err = runTestApp(app, "./gitea", "test-cmd")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, -1, r.ExitCode) // the cli.OsExiter is not called
|
|
||||||
assert.Empty(t, r.Stdout)
|
|
||||||
assert.Empty(t, r.Stderr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCliCmdBefore(t *testing.T) {
|
|
||||||
ctxNew := context.WithValue(context.Background(), any("key"), "value")
|
|
||||||
configValues := map[string]string{}
|
|
||||||
setting.CustomConf = "/tmp/any.ini"
|
|
||||||
var actionCtx context.Context
|
|
||||||
app := newTestApp(cli.Command{
|
|
||||||
Before: func(context.Context, *cli.Command) (context.Context, error) {
|
|
||||||
configValues["before"] = setting.CustomConf
|
|
||||||
return ctxNew, nil
|
|
||||||
},
|
|
||||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
|
||||||
configValues["action"] = setting.CustomConf
|
|
||||||
actionCtx = ctx
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
})
|
|
||||||
_, err := runTestApp(app, "./gitea", "--config", "/dev/null", "test-cmd")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, ctxNew, actionCtx)
|
|
||||||
assert.Equal(t, "/tmp/any.ini", configValues["before"], "BeforeFunc must be called before preparing config")
|
|
||||||
assert.Equal(t, "/dev/null", configValues["action"])
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,2 @@
|
|||||||
-
|
[]
|
||||||
id: 1
|
|
||||||
hook_id: 1
|
|
||||||
uuid: uuid1
|
|
||||||
is_delivered: true
|
|
||||||
is_succeed: false
|
|
||||||
request_content: >
|
|
||||||
{
|
|
||||||
"url": "/matrix-delivered",
|
|
||||||
"http_method":"PUT",
|
|
||||||
"headers": {
|
|
||||||
"X-Head": "42"
|
|
||||||
},
|
|
||||||
"body": "{}"
|
|
||||||
}
|
|
||||||
|
|
||||||
-
|
|
||||||
id: 2
|
|
||||||
hook_id: 1
|
|
||||||
uuid: uuid2
|
|
||||||
is_delivered: true
|
|
||||||
|
|
||||||
-
|
|
||||||
id: 3
|
|
||||||
hook_id: 1
|
|
||||||
uuid: uuid3
|
|
||||||
is_delivered: true
|
|
||||||
is_succeed: true
|
|
||||||
payload_content: '{"key":"value"}' # legacy task, payload saved in payload_content (and not in request_content)
|
|
||||||
request_content: >
|
|
||||||
{
|
|
||||||
"url": "/matrix-success",
|
|
||||||
"http_method":"PUT",
|
|
||||||
"headers": {
|
|
||||||
"X-Head": "42"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
|
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
|
||||||
|
|||||||
@@ -1,54 +1,2 @@
|
|||||||
-
|
[]
|
||||||
id: 1
|
|
||||||
repo_id: 1
|
|
||||||
url: https://www.example.com/url1
|
|
||||||
content_type: 1 # json
|
|
||||||
events: '{"push_only":true,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":false}}'
|
|
||||||
is_active: true
|
|
||||||
|
|
||||||
-
|
|
||||||
id: 2
|
|
||||||
repo_id: 1
|
|
||||||
url: https://www.example.com/url2
|
|
||||||
content_type: 1 # json
|
|
||||||
events: '{"push_only":false,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":true}}'
|
|
||||||
is_active: false
|
|
||||||
|
|
||||||
-
|
|
||||||
id: 3
|
|
||||||
owner_id: 3
|
|
||||||
repo_id: 3
|
|
||||||
url: https://www.example.com/url3
|
|
||||||
content_type: 1 # json
|
|
||||||
events: '{"push_only":false,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":true}}'
|
|
||||||
is_active: true
|
|
||||||
|
|
||||||
-
|
|
||||||
id: 4
|
|
||||||
repo_id: 2
|
|
||||||
url: https://www.example.com/url4
|
|
||||||
content_type: 1 # json
|
|
||||||
events: '{"push_only":true,"branch_filter":"{master,feature*}"}'
|
|
||||||
is_active: true
|
|
||||||
|
|
||||||
-
|
|
||||||
id: 5
|
|
||||||
repo_id: 0
|
|
||||||
owner_id: 0
|
|
||||||
url: https://www.example.com/url5
|
|
||||||
content_type: 1 # json
|
|
||||||
events: '{"push_only":true,"branch_filter":"{master,feature*}"}'
|
|
||||||
is_active: true
|
|
||||||
is_system_webhook: true
|
|
||||||
|
|
||||||
-
|
|
||||||
id: 6
|
|
||||||
repo_id: 0
|
|
||||||
owner_id: 0
|
|
||||||
url: https://www.example.com/url6
|
|
||||||
content_type: 1 # json
|
|
||||||
events: '{"push_only":true,"branch_filter":"{master,feature*}"}'
|
|
||||||
is_active: true
|
|
||||||
is_system_webhook: false
|
|
||||||
|
|
||||||
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
|
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ func deleteDB() error {
|
|||||||
}
|
}
|
||||||
db.Close()
|
db.Close()
|
||||||
|
|
||||||
// Check if we need to setup a specific schema
|
// Check if we need to set up a specific schema
|
||||||
if len(setting.Database.Schema) != 0 {
|
if len(setting.Database.Schema) != 0 {
|
||||||
db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
|
db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
|
||||||
setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode))
|
setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode))
|
||||||
@@ -91,7 +91,7 @@ func deleteDB() error {
|
|||||||
defer schrows.Close()
|
defer schrows.Close()
|
||||||
|
|
||||||
if !schrows.Next() {
|
if !schrows.Next() {
|
||||||
// Create and setup a DB schema
|
// Create and set up a DB schema
|
||||||
_, err = db.Exec("CREATE SCHEMA " + setting.Database.Schema)
|
_, err = db.Exec("CREATE SCHEMA " + setting.Database.Schema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -134,7 +134,8 @@ func PrepareTestEnv(t *testing.T, skip int, syncModels ...any) (*xorm.Engine, fu
|
|||||||
ourSkip := 2
|
ourSkip := 2
|
||||||
ourSkip += skip
|
ourSkip += skip
|
||||||
deferFn := testlogger.PrintCurrentTest(t, ourSkip)
|
deferFn := testlogger.PrintCurrentTest(t, ourSkip)
|
||||||
require.NoError(t, unittest.SyncDirs(filepath.Join(filepath.Dir(setting.AppPath), "tests/gitea-repositories-meta"), setting.RepoRootPath))
|
giteaRoot := setting.GetGiteaTestSourceRoot()
|
||||||
|
require.NoError(t, unittest.SyncDirs(filepath.Join(giteaRoot, "tests/gitea-repositories-meta"), setting.RepoRootPath))
|
||||||
|
|
||||||
if err := deleteDB(); err != nil {
|
if err := deleteDB(); err != nil {
|
||||||
t.Fatalf("unable to reset database: %v", err)
|
t.Fatalf("unable to reset database: %v", err)
|
||||||
@@ -166,7 +167,7 @@ func PrepareTestEnv(t *testing.T, skip int, syncModels ...any) (*xorm.Engine, fu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fixturesDir := filepath.Join(filepath.Dir(setting.AppPath), "models", "migrations", "fixtures", t.Name())
|
fixturesDir := filepath.Join(giteaRoot, "models", "migrations", "fixtures", t.Name())
|
||||||
|
|
||||||
if _, err := os.Stat(fixturesDir); err == nil {
|
if _, err := os.Stat(fixturesDir); err == nil {
|
||||||
t.Logf("initializing fixtures from: %s", fixturesDir)
|
t.Logf("initializing fixtures from: %s", fixturesDir)
|
||||||
@@ -202,17 +203,18 @@ func LoadTableSchemasMap(t *testing.T, x *xorm.Engine) map[string]*schemas.Table
|
|||||||
|
|
||||||
func mainTest(m *testing.M) int {
|
func mainTest(m *testing.M) int {
|
||||||
testlogger.Init()
|
testlogger.Init()
|
||||||
setting.SetupGiteaTestEnv()
|
|
||||||
|
|
||||||
tmpDataPath, cleanup, err := tempdir.OsTempDir("gitea-test").MkdirTempRandom("data")
|
tempWorkPath, cleanup, err := tempdir.OsTempDir("gitea-test").MkdirTempRandom("migration-test-data-")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
testlogger.Panicf("Unable to create temporary data path %v\n", err)
|
return testlogger.MainErrorf("Unable to create temporary dir for migration test: %v", err)
|
||||||
}
|
}
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
setting.AppDataPath = tmpDataPath
|
|
||||||
|
setting.MockBuiltinPaths(tempWorkPath, "", "")
|
||||||
|
setting.SetupGiteaTestEnv()
|
||||||
|
|
||||||
if err = git.InitFull(); err != nil {
|
if err = git.InitFull(); err != nil {
|
||||||
testlogger.Panicf("Unable to InitFull: %v\n", err)
|
return testlogger.MainErrorf("Unable to InitFull: %v", err)
|
||||||
}
|
}
|
||||||
setting.LoadDBSetting()
|
setting.LoadDBSetting()
|
||||||
setting.InitLoggersForTest()
|
setting.InitLoggersForTest()
|
||||||
|
|||||||
@@ -42,12 +42,20 @@ func MainTest(m *testing.M, testOptsArg ...*TestOptions) {
|
|||||||
|
|
||||||
func mainTest(m *testing.M, testOptsArg ...*TestOptions) int {
|
func mainTest(m *testing.M, testOptsArg ...*TestOptions) int {
|
||||||
testOpts := util.OptionalArg(testOptsArg, &TestOptions{})
|
testOpts := util.OptionalArg(testOptsArg, &TestOptions{})
|
||||||
|
|
||||||
|
tempWorkPath, tempCleanup, err := tempdir.OsTempDir("gitea-test").MkdirTempRandom("unit-test-dir-")
|
||||||
|
if err != nil {
|
||||||
|
return testlogger.MainErrorf("Failed to create temp dir for unit test: %v", err)
|
||||||
|
}
|
||||||
|
defer tempCleanup()
|
||||||
|
|
||||||
|
defer setting.MockBuiltinPaths(tempWorkPath, "", "")()
|
||||||
setting.SetupGiteaTestEnv()
|
setting.SetupGiteaTestEnv()
|
||||||
|
|
||||||
giteaRoot := setting.GetGiteaTestSourceRoot()
|
giteaRoot := setting.GetGiteaTestSourceRoot()
|
||||||
fixturesOpts := FixturesOptions{Dir: filepath.Join(giteaRoot, "models", "fixtures"), Files: testOpts.FixtureFiles}
|
fixturesOpts := FixturesOptions{Dir: filepath.Join(giteaRoot, "models", "fixtures"), Files: testOpts.FixtureFiles}
|
||||||
if err := CreateTestEngine(fixturesOpts); err != nil {
|
if err := CreateTestEngine(fixturesOpts); err != nil {
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "Error creating test database engine: %v\n", err)
|
return testlogger.MainErrorf("Error creating test database engine: %v", err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setting.AppURL = "https://try.gitea.io/"
|
setting.AppURL = "https://try.gitea.io/"
|
||||||
@@ -59,59 +67,28 @@ func mainTest(m *testing.M, testOptsArg ...*TestOptions) int {
|
|||||||
setting.SSH.Domain = "try.gitea.io"
|
setting.SSH.Domain = "try.gitea.io"
|
||||||
setting.Database.Type = "sqlite3"
|
setting.Database.Type = "sqlite3"
|
||||||
setting.Repository.DefaultBranch = "master" // many test code still assume that default branch is called "master"
|
setting.Repository.DefaultBranch = "master" // many test code still assume that default branch is called "master"
|
||||||
repoRootPath, cleanup1, err := tempdir.OsTempDir("gitea-test").MkdirTempRandom("repos")
|
|
||||||
if err != nil {
|
|
||||||
testlogger.Panicf("TempDir: %v\n", err)
|
|
||||||
}
|
|
||||||
defer cleanup1()
|
|
||||||
|
|
||||||
setting.RepoRootPath = repoRootPath
|
|
||||||
appDataPath, cleanup2, err := tempdir.OsTempDir("gitea-test").MkdirTempRandom("appdata")
|
|
||||||
if err != nil {
|
|
||||||
testlogger.Panicf("TempDir: %v\n", err)
|
|
||||||
}
|
|
||||||
defer cleanup2()
|
|
||||||
|
|
||||||
setting.AppDataPath = appDataPath
|
|
||||||
setting.GravatarSource = "https://secure.gravatar.com/avatar/"
|
setting.GravatarSource = "https://secure.gravatar.com/avatar/"
|
||||||
|
|
||||||
setting.Attachment.Storage.Path = filepath.Join(setting.AppDataPath, "attachments")
|
|
||||||
|
|
||||||
setting.LFS.Storage.Path = filepath.Join(setting.AppDataPath, "lfs")
|
|
||||||
|
|
||||||
setting.Avatar.Storage.Path = filepath.Join(setting.AppDataPath, "avatars")
|
|
||||||
|
|
||||||
setting.RepoAvatar.Storage.Path = filepath.Join(setting.AppDataPath, "repo-avatars")
|
|
||||||
|
|
||||||
setting.RepoArchive.Storage.Path = filepath.Join(setting.AppDataPath, "repo-archive")
|
|
||||||
|
|
||||||
setting.Packages.Storage.Path = filepath.Join(setting.AppDataPath, "packages")
|
|
||||||
|
|
||||||
setting.Actions.LogStorage.Path = filepath.Join(setting.AppDataPath, "actions_log")
|
|
||||||
|
|
||||||
setting.Git.HomePath = filepath.Join(setting.AppDataPath, "home")
|
|
||||||
|
|
||||||
setting.IncomingEmail.ReplyToAddress = "incoming+%{token}@localhost"
|
setting.IncomingEmail.ReplyToAddress = "incoming+%{token}@localhost"
|
||||||
|
|
||||||
config.SetDynGetter(system.NewDatabaseDynKeyGetter())
|
config.SetDynGetter(system.NewDatabaseDynKeyGetter())
|
||||||
|
|
||||||
if err = cache.Init(); err != nil {
|
if err = cache.Init(); err != nil {
|
||||||
testlogger.Panicf("cache.Init: %v\n", err)
|
return testlogger.MainErrorf("cache.Init: %v", err)
|
||||||
}
|
}
|
||||||
if err = storage.Init(); err != nil {
|
if err = storage.Init(); err != nil {
|
||||||
testlogger.Panicf("storage.Init: %v\n", err)
|
return testlogger.MainErrorf("storage.Init: %v", err)
|
||||||
}
|
}
|
||||||
if err = SyncDirs(filepath.Join(giteaRoot, "tests", "gitea-repositories-meta"), setting.RepoRootPath); err != nil {
|
if err = SyncDirs(filepath.Join(giteaRoot, "tests", "gitea-repositories-meta"), setting.RepoRootPath); err != nil {
|
||||||
testlogger.Panicf("util.SyncDirs: %v\n", err)
|
return testlogger.MainErrorf("util.SyncDirs: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = git.InitFull(); err != nil {
|
if err = git.InitFull(); err != nil {
|
||||||
testlogger.Panicf("git.Init: %v\n", err)
|
return testlogger.MainErrorf("git.Init: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if testOpts.SetUp != nil {
|
if testOpts.SetUp != nil {
|
||||||
if err := testOpts.SetUp(); err != nil {
|
if err := testOpts.SetUp(); err != nil {
|
||||||
testlogger.Panicf("set up failed: %v\n", err)
|
return testlogger.MainErrorf("set up failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +96,7 @@ func mainTest(m *testing.M, testOptsArg ...*TestOptions) int {
|
|||||||
|
|
||||||
if testOpts.TearDown != nil {
|
if testOpts.TearDown != nil {
|
||||||
if err := testOpts.TearDown(); err != nil {
|
if err := testOpts.TearDown(); err != nil {
|
||||||
testlogger.Panicf("tear down failed: %v\n", err)
|
return testlogger.MainErrorf("tear down failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return exitStatus
|
return exitStatus
|
||||||
|
|||||||
@@ -15,5 +15,6 @@ func TestMain(m *testing.M) {
|
|||||||
"webhook.yml",
|
"webhook.yml",
|
||||||
"hook_task.yml",
|
"hook_task.yml",
|
||||||
},
|
},
|
||||||
|
SetUp: prepareWebhookTestData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,28 +10,28 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/optional"
|
"code.gitea.io/gitea/modules/optional"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestListSystemWebhookOptions(t *testing.T) {
|
func TestListSystemWebhookOptions(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hookSystem := unittest.AssertExistsAndLoadBean(t, &Webhook{URL: "https://www.example.com/system"})
|
||||||
|
hookDefault := unittest.AssertExistsAndLoadBean(t, &Webhook{URL: "https://www.example.com/default"})
|
||||||
opts := ListSystemWebhookOptions{IsSystem: optional.None[bool]()}
|
opts := ListSystemWebhookOptions{IsSystem: optional.None[bool]()}
|
||||||
hooks, _, err := GetGlobalWebhooks(t.Context(), &opts)
|
hooks, _, err := GetGlobalWebhooks(t.Context(), &opts)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if assert.Len(t, hooks, 2) {
|
require.Len(t, hooks, 2)
|
||||||
assert.Equal(t, int64(5), hooks[0].ID)
|
assert.Equal(t, hookSystem.ID, hooks[0].ID)
|
||||||
assert.Equal(t, int64(6), hooks[1].ID)
|
assert.Equal(t, hookDefault.ID, hooks[1].ID)
|
||||||
}
|
|
||||||
opts.IsSystem = optional.Some(true)
|
opts.IsSystem = optional.Some(true)
|
||||||
hooks, _, err = GetGlobalWebhooks(t.Context(), &opts)
|
hooks, _, err = GetGlobalWebhooks(t.Context(), &opts)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if assert.Len(t, hooks, 1) {
|
require.Len(t, hooks, 1)
|
||||||
assert.Equal(t, int64(5), hooks[0].ID)
|
assert.Equal(t, hookSystem.ID, hooks[0].ID)
|
||||||
}
|
|
||||||
|
|
||||||
opts.IsSystem = optional.Some(false)
|
opts.IsSystem = optional.Some(false)
|
||||||
hooks, _, err = GetGlobalWebhooks(t.Context(), &opts)
|
hooks, _, err = GetGlobalWebhooks(t.Context(), &opts)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if assert.Len(t, hooks, 1) {
|
require.Len(t, hooks, 1)
|
||||||
assert.Equal(t, int64(6), hooks[0].ID)
|
assert.Equal(t, hookDefault.ID, hooks[0].ID)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package webhook
|
package webhook
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -14,40 +15,105 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
webhook_module "code.gitea.io/gitea/modules/webhook"
|
webhook_module "code.gitea.io/gitea/modules/webhook"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHookContentType_Name(t *testing.T) {
|
func prepareWebhookTestData() error {
|
||||||
assert.Equal(t, "json", ContentTypeJSON.Name())
|
if err := unittest.PrepareTestDatabase(); err != nil {
|
||||||
assert.Equal(t, "form", ContentTypeForm.Name())
|
return err
|
||||||
|
}
|
||||||
|
var hooks []*Webhook
|
||||||
|
hooks = append(hooks, &Webhook{
|
||||||
|
RepoID: 1,
|
||||||
|
URL: "https://www.example.com/url1",
|
||||||
|
ContentType: ContentTypeJSON,
|
||||||
|
Events: `{"push_only":true,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":false}}`,
|
||||||
|
IsActive: true,
|
||||||
|
})
|
||||||
|
hooks = append(hooks, &Webhook{
|
||||||
|
RepoID: 1,
|
||||||
|
URL: "https://www.example.com/url2",
|
||||||
|
ContentType: ContentTypeJSON,
|
||||||
|
Events: `{}`,
|
||||||
|
IsActive: false,
|
||||||
|
})
|
||||||
|
hooks = append(hooks, &Webhook{
|
||||||
|
OwnerID: 3,
|
||||||
|
RepoID: 3,
|
||||||
|
URL: "https://www.example.com/url3",
|
||||||
|
ContentType: ContentTypeJSON,
|
||||||
|
Events: `{"push_only":false,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":true}}`,
|
||||||
|
IsActive: true,
|
||||||
|
})
|
||||||
|
hooks = append(hooks, &Webhook{
|
||||||
|
OwnerID: 3,
|
||||||
|
RepoID: 3,
|
||||||
|
URL: "https://www.example.com/url3",
|
||||||
|
ContentType: ContentTypeJSON,
|
||||||
|
Events: `{}`,
|
||||||
|
})
|
||||||
|
hooks = append(hooks, &Webhook{
|
||||||
|
RepoID: 2,
|
||||||
|
URL: "https://www.example.com/url4",
|
||||||
|
ContentType: ContentTypeJSON,
|
||||||
|
Events: `{"push_only":true,"branch_filter":"{master,feature*}"}`,
|
||||||
|
IsActive: true,
|
||||||
|
})
|
||||||
|
hooks = append(hooks, &Webhook{
|
||||||
|
URL: "https://www.example.com/system",
|
||||||
|
ContentType: ContentTypeJSON,
|
||||||
|
Events: `{"push_only":true,"branch_filter":"{master,feature*}"}`,
|
||||||
|
IsSystemWebhook: true,
|
||||||
|
})
|
||||||
|
hooks = append(hooks, &Webhook{
|
||||||
|
URL: "https://www.example.com/default",
|
||||||
|
ContentType: ContentTypeJSON,
|
||||||
|
Events: `{"push_only":true,"branch_filter":"{master,feature*}"}`,
|
||||||
|
})
|
||||||
|
ctx := context.Background()
|
||||||
|
if err := db.TruncateBeans(ctx, &Webhook{}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := db.Insert(ctx, hooks); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
hook, _, _ := db.Get[Webhook](ctx, builder.Eq{"repo_id": 1, "is_active": true})
|
||||||
|
var tasks []*HookTask
|
||||||
|
tasks = append(tasks, &HookTask{HookID: hook.ID, UUID: uuid.New().String()})
|
||||||
|
tasks = append(tasks, &HookTask{HookID: hook.ID, UUID: uuid.New().String()})
|
||||||
|
tasks = append(tasks, &HookTask{HookID: hook.ID, UUID: uuid.New().String()})
|
||||||
|
if err := db.TruncateBeans(ctx, &HookTask{}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return db.Insert(ctx, tasks)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsValidHookContentType(t *testing.T) {
|
func TestWebHookContentType(t *testing.T) {
|
||||||
|
assert.Equal(t, "json", ContentTypeJSON.Name())
|
||||||
|
assert.Equal(t, "form", ContentTypeForm.Name())
|
||||||
assert.True(t, IsValidHookContentType("json"))
|
assert.True(t, IsValidHookContentType("json"))
|
||||||
assert.True(t, IsValidHookContentType("form"))
|
assert.True(t, IsValidHookContentType("form"))
|
||||||
assert.False(t, IsValidHookContentType("invalid"))
|
assert.False(t, IsValidHookContentType("invalid"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWebhook_History(t *testing.T) {
|
func TestWebhook_History(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := unittest.AssertExistsAndLoadBean(t, &Webhook{RepoID: 1, IsActive: true})
|
||||||
webhook := unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 1})
|
tasks, err := hook.History(t.Context(), 0)
|
||||||
tasks, err := webhook.History(t.Context(), 0)
|
require.NoError(t, err)
|
||||||
assert.NoError(t, err)
|
require.Len(t, tasks, 3)
|
||||||
if assert.Len(t, tasks, 3) {
|
|
||||||
assert.Equal(t, int64(3), tasks[0].ID)
|
|
||||||
assert.Equal(t, int64(2), tasks[1].ID)
|
|
||||||
assert.Equal(t, int64(1), tasks[2].ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
webhook = unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 2})
|
hook = unittest.AssertExistsAndLoadBean(t, &Webhook{RepoID: 1, Events: "{}"})
|
||||||
tasks, err = webhook.History(t.Context(), 0)
|
tasks, err = hook.History(t.Context(), 0)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, tasks)
|
assert.Empty(t, tasks)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWebhook_UpdateEvent(t *testing.T) {
|
func TestWebhook_UpdateEvent(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
webhook := unittest.AssertExistsAndLoadBean(t, &Webhook{RepoID: 1, IsActive: true})
|
||||||
webhook := unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 1})
|
|
||||||
hookEvent := &webhook_module.HookEvent{
|
hookEvent := &webhook_module.HookEvent{
|
||||||
PushOnly: true,
|
PushOnly: true,
|
||||||
SendEverything: false,
|
SendEverything: false,
|
||||||
@@ -100,10 +166,10 @@ func TestCreateWebhook(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetWebhookByRepoID(t *testing.T) {
|
func TestGetWebhookByRepoID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := unittest.AssertExistsAndLoadBean(t, &Webhook{RepoID: 1, IsActive: true})
|
||||||
hook, err := GetWebhookByRepoID(t.Context(), 1, 1)
|
loaded, err := GetWebhookByRepoID(t.Context(), 1, hook.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, int64(1), hook.ID)
|
assert.Equal(t, hook.ID, loaded.ID)
|
||||||
|
|
||||||
_, err = GetWebhookByRepoID(t.Context(), unittest.NonexistentID, unittest.NonexistentID)
|
_, err = GetWebhookByRepoID(t.Context(), unittest.NonexistentID, unittest.NonexistentID)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
@@ -111,10 +177,10 @@ func TestGetWebhookByRepoID(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetWebhookByOwnerID(t *testing.T) {
|
func TestGetWebhookByOwnerID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := unittest.AssertExistsAndLoadBean(t, &Webhook{OwnerID: 3})
|
||||||
hook, err := GetWebhookByOwnerID(t.Context(), 3, 3)
|
loaded, err := GetWebhookByOwnerID(t.Context(), 3, hook.ID)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, int64(3), hook.ID)
|
require.Equal(t, hook.ID, loaded.ID)
|
||||||
|
|
||||||
_, err = GetWebhookByOwnerID(t.Context(), unittest.NonexistentID, unittest.NonexistentID)
|
_, err = GetWebhookByOwnerID(t.Context(), unittest.NonexistentID, unittest.NonexistentID)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
@@ -122,48 +188,45 @@ func TestGetWebhookByOwnerID(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetActiveWebhooksByRepoID(t *testing.T) {
|
func TestGetActiveWebhooksByRepoID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := unittest.AssertExistsAndLoadBean(t, &Webhook{RepoID: 1, IsActive: true})
|
||||||
hooks, err := db.Find[Webhook](t.Context(), ListWebhookOptions{RepoID: 1, IsActive: optional.Some(true)})
|
hooks, err := db.Find[Webhook](t.Context(), ListWebhookOptions{RepoID: 1, IsActive: optional.Some(true)})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if assert.Len(t, hooks, 1) {
|
require.Len(t, hooks, 1)
|
||||||
assert.Equal(t, int64(1), hooks[0].ID)
|
assert.Equal(t, hook.ID, hooks[0].ID)
|
||||||
assert.True(t, hooks[0].IsActive)
|
assert.True(t, hooks[0].IsActive)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetWebhooksByRepoID(t *testing.T) {
|
func TestGetWebhooksByRepoID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
hooks, err := db.Find[Webhook](t.Context(), ListWebhookOptions{RepoID: 1})
|
hooks, err := db.Find[Webhook](t.Context(), ListWebhookOptions{RepoID: 1})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if assert.Len(t, hooks, 2) {
|
require.Len(t, hooks, 2)
|
||||||
assert.Equal(t, int64(1), hooks[0].ID)
|
assert.Equal(t, int64(1), hooks[0].RepoID)
|
||||||
assert.Equal(t, int64(2), hooks[1].ID)
|
assert.True(t, hooks[0].IsActive)
|
||||||
}
|
assert.Equal(t, int64(1), hooks[1].RepoID)
|
||||||
|
assert.False(t, hooks[1].IsActive)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetActiveWebhooksByOwnerID(t *testing.T) {
|
func TestGetActiveWebhooksByOwnerID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
hooks, err := db.Find[Webhook](t.Context(), ListWebhookOptions{OwnerID: 3, IsActive: optional.Some(true)})
|
hooks, err := db.Find[Webhook](t.Context(), ListWebhookOptions{OwnerID: 3, IsActive: optional.Some(true)})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if assert.Len(t, hooks, 1) {
|
require.Len(t, hooks, 1)
|
||||||
assert.Equal(t, int64(3), hooks[0].ID)
|
assert.Equal(t, int64(3), hooks[0].OwnerID)
|
||||||
assert.True(t, hooks[0].IsActive)
|
assert.True(t, hooks[0].IsActive)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetWebhooksByOwnerID(t *testing.T) {
|
func TestGetWebhooksByOwnerID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
hooks, err := db.Find[Webhook](t.Context(), ListWebhookOptions{OwnerID: 3})
|
hooks, err := db.Find[Webhook](t.Context(), ListWebhookOptions{OwnerID: 3})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if assert.Len(t, hooks, 1) {
|
require.Len(t, hooks, 2)
|
||||||
assert.Equal(t, int64(3), hooks[0].ID)
|
assert.Equal(t, int64(3), hooks[0].OwnerID)
|
||||||
assert.True(t, hooks[0].IsActive)
|
assert.True(t, hooks[0].IsActive)
|
||||||
}
|
assert.Equal(t, int64(3), hooks[1].OwnerID)
|
||||||
|
assert.False(t, hooks[1].IsActive)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateWebhook(t *testing.T) {
|
func TestUpdateWebhook(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := unittest.AssertExistsAndLoadBean(t, &Webhook{RepoID: 1, Events: `{}`})
|
||||||
hook := unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 2})
|
require.False(t, hook.IsActive)
|
||||||
hook.IsActive = true
|
hook.IsActive = true
|
||||||
hook.ContentType = ContentTypeForm
|
hook.ContentType = ContentTypeForm
|
||||||
unittest.AssertNotExistsBean(t, hook)
|
unittest.AssertNotExistsBean(t, hook)
|
||||||
@@ -172,48 +235,36 @@ func TestUpdateWebhook(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteWebhookByRepoID(t *testing.T) {
|
func TestDeleteWebhookByRepoID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := unittest.AssertExistsAndLoadBean(t, &Webhook{RepoID: 1, Events: `{}`})
|
||||||
unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 2, RepoID: 1})
|
assert.NoError(t, DeleteWebhookByRepoID(t.Context(), 1, hook.ID))
|
||||||
assert.NoError(t, DeleteWebhookByRepoID(t.Context(), 1, 2))
|
unittest.AssertNotExistsBean(t, &Webhook{ID: hook.ID, RepoID: 1})
|
||||||
unittest.AssertNotExistsBean(t, &Webhook{ID: 2, RepoID: 1})
|
|
||||||
|
|
||||||
err := DeleteWebhookByRepoID(t.Context(), unittest.NonexistentID, unittest.NonexistentID)
|
err := DeleteWebhookByRepoID(t.Context(), unittest.NonexistentID, unittest.NonexistentID)
|
||||||
assert.Error(t, err)
|
|
||||||
assert.True(t, IsErrWebhookNotExist(err))
|
assert.True(t, IsErrWebhookNotExist(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteWebhookByOwnerID(t *testing.T) {
|
func TestDeleteWebhookByOwnerID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := unittest.AssertExistsAndLoadBean(t, &Webhook{OwnerID: 3, Events: `{}`})
|
||||||
unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 3, OwnerID: 3})
|
assert.NoError(t, DeleteWebhookByOwnerID(t.Context(), 3, hook.ID))
|
||||||
assert.NoError(t, DeleteWebhookByOwnerID(t.Context(), 3, 3))
|
unittest.AssertNotExistsBean(t, &Webhook{ID: hook.ID, OwnerID: 3})
|
||||||
unittest.AssertNotExistsBean(t, &Webhook{ID: 3, OwnerID: 3})
|
|
||||||
|
|
||||||
err := DeleteWebhookByOwnerID(t.Context(), unittest.NonexistentID, unittest.NonexistentID)
|
err := DeleteWebhookByOwnerID(t.Context(), unittest.NonexistentID, unittest.NonexistentID)
|
||||||
assert.Error(t, err)
|
|
||||||
assert.True(t, IsErrWebhookNotExist(err))
|
assert.True(t, IsErrWebhookNotExist(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHookTasks(t *testing.T) {
|
func TestHookTasks(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := unittest.AssertExistsAndLoadBean(t, &Webhook{RepoID: 1, IsActive: true})
|
||||||
hookTasks, err := HookTasks(t.Context(), 1, 1)
|
hookTasks, err := HookTasks(t.Context(), hook.ID, 1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
if assert.Len(t, hookTasks, 3) {
|
assert.Len(t, hookTasks, 3)
|
||||||
assert.Equal(t, int64(3), hookTasks[0].ID)
|
|
||||||
assert.Equal(t, int64(2), hookTasks[1].ID)
|
|
||||||
assert.Equal(t, int64(1), hookTasks[2].ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
hookTasks, err = HookTasks(t.Context(), unittest.NonexistentID, 1)
|
hookTasks, err = HookTasks(t.Context(), unittest.NonexistentID, 1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, hookTasks)
|
assert.Empty(t, hookTasks)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateHookTask(t *testing.T) {
|
func TestCreateHookTask(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := unittest.AssertExistsAndLoadBean(t, &Webhook{OwnerID: 3, IsActive: true})
|
||||||
hookTask := &HookTask{
|
hookTask := &HookTask{HookID: hook.ID, PayloadVersion: 2}
|
||||||
HookID: 3,
|
|
||||||
PayloadVersion: 2,
|
|
||||||
}
|
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
_, err := CreateHookTask(t.Context(), hookTask)
|
_, err := CreateHookTask(t.Context(), hookTask)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@@ -221,20 +272,23 @@ func TestCreateHookTask(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateHookTask(t *testing.T) {
|
func TestUpdateHookTask(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := unittest.AssertExistsAndLoadBean(t, &Webhook{OwnerID: 3, IsActive: true})
|
||||||
|
hookTask := &HookTask{HookID: hook.ID, PayloadVersion: 2}
|
||||||
|
_, err := CreateHookTask(t.Context(), hookTask)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
hook := unittest.AssertExistsAndLoadBean(t, &HookTask{ID: 1})
|
hookTask.PayloadContent = "new payload content"
|
||||||
hook.PayloadContent = "new payload content"
|
hookTask.IsDelivered = true
|
||||||
hook.IsDelivered = true
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
unittest.AssertNotExistsBean(t, hook)
|
assert.NoError(t, UpdateHookTask(t.Context(), hookTask))
|
||||||
assert.NoError(t, UpdateHookTask(t.Context(), hook))
|
unittest.AssertExistsAndLoadBean(t, hookTask)
|
||||||
unittest.AssertExistsAndLoadBean(t, hook)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCleanupHookTaskTable_PerWebhook_DeletesDelivered(t *testing.T) {
|
func TestCleanupHookTaskTable_PerWebhook_DeletesDelivered(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := &Webhook{RepoID: 3, URL: "https://www.example.com/cleanup1", ContentType: ContentTypeJSON, Events: `{"push_only":true}`}
|
||||||
|
require.NoError(t, db.Insert(t.Context(), hook))
|
||||||
hookTask := &HookTask{
|
hookTask := &HookTask{
|
||||||
HookID: 3,
|
HookID: hook.ID,
|
||||||
IsDelivered: true,
|
IsDelivered: true,
|
||||||
Delivered: timeutil.TimeStampNanoNow(),
|
Delivered: timeutil.TimeStampNanoNow(),
|
||||||
PayloadVersion: 2,
|
PayloadVersion: 2,
|
||||||
@@ -249,9 +303,10 @@ func TestCleanupHookTaskTable_PerWebhook_DeletesDelivered(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCleanupHookTaskTable_PerWebhook_LeavesUndelivered(t *testing.T) {
|
func TestCleanupHookTaskTable_PerWebhook_LeavesUndelivered(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := &Webhook{RepoID: 3, URL: "https://www.example.com/cleanup2", ContentType: ContentTypeJSON, Events: `{"push_only":true}`}
|
||||||
|
require.NoError(t, db.Insert(t.Context(), hook))
|
||||||
hookTask := &HookTask{
|
hookTask := &HookTask{
|
||||||
HookID: 4,
|
HookID: hook.ID,
|
||||||
IsDelivered: false,
|
IsDelivered: false,
|
||||||
PayloadVersion: 2,
|
PayloadVersion: 2,
|
||||||
}
|
}
|
||||||
@@ -265,9 +320,10 @@ func TestCleanupHookTaskTable_PerWebhook_LeavesUndelivered(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCleanupHookTaskTable_PerWebhook_LeavesMostRecentTask(t *testing.T) {
|
func TestCleanupHookTaskTable_PerWebhook_LeavesMostRecentTask(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := &Webhook{RepoID: 3, URL: "https://www.example.com/cleanup3", ContentType: ContentTypeJSON, Events: `{"push_only":true}`}
|
||||||
|
require.NoError(t, db.Insert(t.Context(), hook))
|
||||||
hookTask := &HookTask{
|
hookTask := &HookTask{
|
||||||
HookID: 4,
|
HookID: hook.ID,
|
||||||
IsDelivered: true,
|
IsDelivered: true,
|
||||||
Delivered: timeutil.TimeStampNanoNow(),
|
Delivered: timeutil.TimeStampNanoNow(),
|
||||||
PayloadVersion: 2,
|
PayloadVersion: 2,
|
||||||
@@ -282,9 +338,10 @@ func TestCleanupHookTaskTable_PerWebhook_LeavesMostRecentTask(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCleanupHookTaskTable_OlderThan_DeletesDelivered(t *testing.T) {
|
func TestCleanupHookTaskTable_OlderThan_DeletesDelivered(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := &Webhook{RepoID: 3, URL: "https://www.example.com/cleanup4", ContentType: ContentTypeJSON, Events: `{"push_only":true}`}
|
||||||
|
require.NoError(t, db.Insert(t.Context(), hook))
|
||||||
hookTask := &HookTask{
|
hookTask := &HookTask{
|
||||||
HookID: 3,
|
HookID: hook.ID,
|
||||||
IsDelivered: true,
|
IsDelivered: true,
|
||||||
Delivered: timeutil.TimeStampNano(time.Now().AddDate(0, 0, -8).UnixNano()),
|
Delivered: timeutil.TimeStampNano(time.Now().AddDate(0, 0, -8).UnixNano()),
|
||||||
PayloadVersion: 2,
|
PayloadVersion: 2,
|
||||||
@@ -299,9 +356,10 @@ func TestCleanupHookTaskTable_OlderThan_DeletesDelivered(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCleanupHookTaskTable_OlderThan_LeavesUndelivered(t *testing.T) {
|
func TestCleanupHookTaskTable_OlderThan_LeavesUndelivered(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := &Webhook{RepoID: 3, URL: "https://www.example.com/cleanup5", ContentType: ContentTypeJSON, Events: `{"push_only":true}`}
|
||||||
|
require.NoError(t, db.Insert(t.Context(), hook))
|
||||||
hookTask := &HookTask{
|
hookTask := &HookTask{
|
||||||
HookID: 4,
|
HookID: hook.ID,
|
||||||
IsDelivered: false,
|
IsDelivered: false,
|
||||||
PayloadVersion: 2,
|
PayloadVersion: 2,
|
||||||
}
|
}
|
||||||
@@ -315,9 +373,10 @@ func TestCleanupHookTaskTable_OlderThan_LeavesUndelivered(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCleanupHookTaskTable_OlderThan_LeavesTaskEarlierThanAgeToDelete(t *testing.T) {
|
func TestCleanupHookTaskTable_OlderThan_LeavesTaskEarlierThanAgeToDelete(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
hook := &Webhook{RepoID: 3, URL: "https://www.example.com/cleanup6", ContentType: ContentTypeJSON, Events: `{"push_only":true}`}
|
||||||
|
require.NoError(t, db.Insert(t.Context(), hook))
|
||||||
hookTask := &HookTask{
|
hookTask := &HookTask{
|
||||||
HookID: 4,
|
HookID: hook.ID,
|
||||||
IsDelivered: true,
|
IsDelivered: true,
|
||||||
Delivered: timeutil.TimeStampNano(time.Now().AddDate(0, 0, -6).UnixNano()),
|
Delivered: timeutil.TimeStampNano(time.Now().AddDate(0, 0, -6).UnixNano()),
|
||||||
PayloadVersion: 2,
|
PayloadVersion: 2,
|
||||||
|
|||||||
@@ -192,13 +192,13 @@ func RunGitTests(m interface{ Run() int }) {
|
|||||||
func runGitTests(m interface{ Run() int }) int {
|
func runGitTests(m interface{ Run() int }) int {
|
||||||
gitHomePath, cleanup, err := tempdir.OsTempDir("gitea-test").MkdirTempRandom("git-home")
|
gitHomePath, cleanup, err := tempdir.OsTempDir("gitea-test").MkdirTempRandom("git-home")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
testlogger.Panicf("unable to create temp dir: %s", err.Error())
|
return testlogger.MainErrorf("unable to create temp dir: %v", err)
|
||||||
}
|
}
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
setting.Git.HomePath = gitHomePath
|
setting.Git.HomePath = gitHomePath
|
||||||
if err = InitFull(); err != nil {
|
if err = InitFull(); err != nil {
|
||||||
testlogger.Panicf("failed to call Init: %s", err.Error())
|
return testlogger.MainErrorf("failed to call Init: %v", err)
|
||||||
}
|
}
|
||||||
return m.Run()
|
return m.Run()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func testMain(m *testing.M) int {
|
|||||||
// "setting.Git.HomePath" is initialized in "git" package but really used in "gitcmd" package
|
// "setting.Git.HomePath" is initialized in "git" package but really used in "gitcmd" package
|
||||||
gitHomePath, cleanup, err := tempdir.OsTempDir("gitea-test").MkdirTempRandom("git-home")
|
gitHomePath, cleanup, err := tempdir.OsTempDir("gitea-test").MkdirTempRandom("git-home")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
testlogger.Panicf("failed to create temp dir: %v", err)
|
return testlogger.MainErrorf("failed to create temp dir: %v", err)
|
||||||
}
|
}
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
|
|||||||
@@ -13,11 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestManager(t *testing.T) {
|
func TestManager(t *testing.T) {
|
||||||
oldAppDataPath := setting.AppDataPath
|
|
||||||
setting.AppDataPath = t.TempDir()
|
setting.AppDataPath = t.TempDir()
|
||||||
defer func() {
|
|
||||||
setting.AppDataPath = oldAppDataPath
|
|
||||||
}()
|
|
||||||
|
|
||||||
newQueueFromConfig := func(name, cfg string) (*WorkerPoolQueue[int], error) {
|
newQueueFromConfig := func(name, cfg string) (*WorkerPoolQueue[int], error) {
|
||||||
cfgProvider, err := setting.NewConfigProviderFromData(cfg)
|
cfgProvider, err := setting.NewConfigProviderFromData(cfg)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
var giteaTestSourceRoot *string
|
var giteaTestSourceRoot *string // intentionally use a pointer to make sure the uninitialized access panics
|
||||||
|
|
||||||
func GetGiteaTestSourceRoot() string {
|
func GetGiteaTestSourceRoot() string {
|
||||||
return *giteaTestSourceRoot
|
return *giteaTestSourceRoot
|
||||||
@@ -30,7 +30,9 @@ func SetupGiteaTestEnv() {
|
|||||||
|
|
||||||
log.OsExiter = func(code int) {
|
log.OsExiter = func(code int) {
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
// non-zero exit code (log.Fatal) shouldn't occur during testing, if it happens, show a full stacktrace for more details
|
// Non-zero exit code (log.Fatal) shouldn't occur during testing, if it happens:
|
||||||
|
// * Show a full stacktrace for more details.
|
||||||
|
// * If the "log.Fatal" is abused in tests, should fix.
|
||||||
panic(fmt.Errorf("non-zero exit code during testing: %d", code))
|
panic(fmt.Errorf("non-zero exit code during testing: %d", code))
|
||||||
}
|
}
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
@@ -49,12 +51,14 @@ func SetupGiteaTestEnv() {
|
|||||||
giteaTestSourceRoot = &giteaRoot
|
giteaTestSourceRoot = &giteaRoot
|
||||||
return giteaRoot
|
return giteaRoot
|
||||||
}
|
}
|
||||||
|
giteaRoot := initGiteaRoot()
|
||||||
|
|
||||||
initGiteaPaths := func() {
|
initGiteaPaths := func() {
|
||||||
appWorkPathBuiltin = *giteaTestSourceRoot
|
// need to load assets (options, public) from the source code directory for testing
|
||||||
AppWorkPath = appWorkPathBuiltin
|
StaticRootPath = giteaRoot
|
||||||
AppPath = filepath.Join(AppWorkPath, "gitea") + util.Iif(IsWindows, ".exe", "")
|
// during testing, the AppPath must point to the pre-built Gitea binary in the source root
|
||||||
StaticRootPath = AppWorkPath // need to load assets (options, public) from the source code directory for testing
|
// it needs to be called by git hooks
|
||||||
|
AppPath = filepath.Join(giteaRoot, "gitea") + util.Iif(IsWindows, ".exe", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
initGiteaConf := func() string {
|
initGiteaConf := func() string {
|
||||||
@@ -62,13 +66,15 @@ func SetupGiteaTestEnv() {
|
|||||||
giteaConf := os.Getenv("GITEA_TEST_CONF")
|
giteaConf := os.Getenv("GITEA_TEST_CONF")
|
||||||
if giteaConf == "" {
|
if giteaConf == "" {
|
||||||
// if no GITEA_TEST_CONF, then it is in unit test, use a temp (non-existing / empty) config file
|
// if no GITEA_TEST_CONF, then it is in unit test, use a temp (non-existing / empty) config file
|
||||||
|
// do not really use such config file, the test can run concurrently, using the same config file will cause data-race between tests
|
||||||
giteaConf = "custom/conf/app-test-tmp.ini"
|
giteaConf = "custom/conf/app-test-tmp.ini"
|
||||||
customConfBuiltin = filepath.Join(AppWorkPath, giteaConf)
|
customConfBuiltin = filepath.Join(AppWorkPath, giteaConf)
|
||||||
CustomConf = customConfBuiltin
|
CustomConf = customConfBuiltin
|
||||||
_ = os.Remove(CustomConf)
|
_ = os.Remove(CustomConf)
|
||||||
} else {
|
} else {
|
||||||
// CustomConf must be absolute path to make tests pass,
|
// CustomConf must be absolute path to make tests pass.
|
||||||
CustomConf = filepath.Join(AppWorkPath, giteaConf)
|
// At the moment, GITEA_TEST_CONF is always in Gitea's source root
|
||||||
|
CustomConf = filepath.Join(giteaRoot, giteaConf)
|
||||||
}
|
}
|
||||||
return giteaConf
|
return giteaConf
|
||||||
}
|
}
|
||||||
@@ -98,12 +104,15 @@ func SetupGiteaTestEnv() {
|
|||||||
PasswordHashAlgo, _ = hash.SetDefaultPasswordHashAlgorithm("dummy")
|
PasswordHashAlgo, _ = hash.SetDefaultPasswordHashAlgorithm("dummy")
|
||||||
}
|
}
|
||||||
|
|
||||||
giteaRoot := initGiteaRoot()
|
|
||||||
initGiteaPaths()
|
initGiteaPaths()
|
||||||
giteaConf := initGiteaConf()
|
giteaConf := initGiteaConf()
|
||||||
cleanUpEnv()
|
cleanUpEnv()
|
||||||
initWorkPathAndConfig()
|
initWorkPathAndConfig()
|
||||||
|
|
||||||
|
if RepoRootPath == "" || AppDataPath == "" {
|
||||||
|
panic("SetupGiteaTestEnv failed, paths are not initialized")
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: some git repo hooks (test fixtures) still use these env variables, need to be refactored in the future
|
// TODO: some git repo hooks (test fixtures) still use these env variables, need to be refactored in the future
|
||||||
_ = os.Setenv("GITEA_ROOT", giteaRoot)
|
_ = os.Setenv("GITEA_ROOT", giteaRoot)
|
||||||
_ = os.Setenv("GITEA_CONF", giteaConf) // test fixture git hooks use "$GITEA_ROOT/$GITEA_CONF" in their scripts
|
_ = os.Setenv("GITEA_CONF", giteaConf) // test fixture git hooks use "$GITEA_ROOT/$GITEA_CONF" in their scripts
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ func PrintCurrentTest(t testing.TB, skip ...int) func() {
|
|||||||
deferHasRun := false
|
deferHasRun := false
|
||||||
t.Cleanup(func() {
|
t.Cleanup(func() {
|
||||||
if !deferHasRun {
|
if !deferHasRun {
|
||||||
stdoutPrintf("!!! %s defer function hasn't been run but Cleanup is called, usually caused by panic\n", t.Name())
|
stdoutPrintf("!!! %s: defer function hasn't been run but Cleanup is called, usually caused by panic\n", t.Name())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
stdoutPrintf("=== %s (%s:%d)\n", log.NewColoredValue(t.Name()), strings.TrimPrefix(filename, prefix), line)
|
stdoutPrintf("=== %s (%s:%d)\n", log.NewColoredValue(t.Name()), strings.TrimPrefix(filename, prefix), line)
|
||||||
@@ -173,7 +173,8 @@ func Init() {
|
|||||||
log.RegisterEventWriter("test", newTestLoggerWriter)
|
log.RegisterEventWriter("test", newTestLoggerWriter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Panicf(format string, args ...any) {
|
// MainErrorf is used to report an error from TestMain and return a non-zero value to indicate the failure
|
||||||
// don't call os.Exit, otherwise the "defer" functions won't be executed
|
func MainErrorf(msg string, a ...any) int {
|
||||||
panic(fmt.Sprintf(format, args...))
|
_, _ = fmt.Fprintf(os.Stderr, msg+"\n", a...)
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ package repo
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
"code.gitea.io/gitea/models/webhook"
|
"code.gitea.io/gitea/models/webhook"
|
||||||
"code.gitea.io/gitea/services/contexttest"
|
"code.gitea.io/gitea/services/contexttest"
|
||||||
@@ -17,8 +19,17 @@ import (
|
|||||||
func TestTestHook(t *testing.T) {
|
func TestTestHook(t *testing.T) {
|
||||||
unittest.PrepareTestEnv(t)
|
unittest.PrepareTestEnv(t)
|
||||||
|
|
||||||
|
hook := &webhook.Webhook{
|
||||||
|
RepoID: 1,
|
||||||
|
URL: "https://www.example.com/test_hook",
|
||||||
|
ContentType: webhook.ContentTypeJSON,
|
||||||
|
Events: `{"push_only":true}`,
|
||||||
|
IsActive: true,
|
||||||
|
}
|
||||||
|
assert.NoError(t, db.Insert(t.Context(), hook))
|
||||||
|
|
||||||
ctx, _ := contexttest.MockAPIContext(t, "user2/repo1/wiki/_pages")
|
ctx, _ := contexttest.MockAPIContext(t, "user2/repo1/wiki/_pages")
|
||||||
ctx.SetPathParam("id", "1")
|
ctx.SetPathParam("id", strconv.FormatInt(hook.ID, 10))
|
||||||
contexttest.LoadRepo(t, ctx, 1)
|
contexttest.LoadRepo(t, ctx, 1)
|
||||||
contexttest.LoadRepoCommit(t, ctx)
|
contexttest.LoadRepoCommit(t, ctx)
|
||||||
contexttest.LoadUser(t, ctx, 2)
|
contexttest.LoadUser(t, ctx, 2)
|
||||||
@@ -26,6 +37,6 @@ func TestTestHook(t *testing.T) {
|
|||||||
assert.Equal(t, http.StatusNoContent, ctx.Resp.WrittenStatus())
|
assert.Equal(t, http.StatusNoContent, ctx.Resp.WrittenStatus())
|
||||||
|
|
||||||
unittest.AssertExistsAndLoadBean(t, &webhook.HookTask{
|
unittest.AssertExistsAndLoadBean(t, &webhook.HookTask{
|
||||||
HookID: 1,
|
HookID: hook.ID,
|
||||||
}, unittest.Cond("is_delivered=?", false))
|
}, unittest.Cond("is_delivered=?", false))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,10 +36,7 @@ import (
|
|||||||
|
|
||||||
func newDefaultRequest(ctx context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (req *http.Request, body []byte, err error) {
|
func newDefaultRequest(ctx context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (req *http.Request, body []byte, err error) {
|
||||||
switch w.HTTPMethod {
|
switch w.HTTPMethod {
|
||||||
case "":
|
case "", http.MethodPost:
|
||||||
log.Info("HTTP Method for %s webhook %s [ID: %d] is not set, defaulting to POST", w.Type, w.URL, w.ID)
|
|
||||||
fallthrough
|
|
||||||
case http.MethodPost:
|
|
||||||
switch w.ContentType {
|
switch w.ContentType {
|
||||||
case webhook_model.ContentTypeJSON:
|
case webhook_model.ContentTypeJSON:
|
||||||
req, err = http.NewRequest(http.MethodPost, w.URL, strings.NewReader(t.PayloadContent))
|
req, err = http.NewRequest(http.MethodPost, w.URL, strings.NewReader(t.PayloadContent))
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package webhook
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
@@ -21,7 +22,17 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWebhook_GetSlackHook(t *testing.T) {
|
func TestWebhookService(t *testing.T) {
|
||||||
|
unittest.PrepareTestEnv(t)
|
||||||
|
t.Run("GetSlackHook", testWebhookGetSlackHook)
|
||||||
|
t.Run("PrepareWebhooks", testWebhookPrepare)
|
||||||
|
t.Run("PrepareBranchFilterMatch", testWebhookPrepareBranchFilterMatch)
|
||||||
|
t.Run("PrepareBranchFilterNoMatch", testWebhookPrepareBranchFilterNoMatch)
|
||||||
|
t.Run("WebhookUserMail", testWebhookUserMail)
|
||||||
|
t.Run("CheckBranchFilter", testWebhookCheckBranchFilter)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testWebhookGetSlackHook(t *testing.T) {
|
||||||
w := &webhook_model.Webhook{
|
w := &webhook_model.Webhook{
|
||||||
Meta: `{"channel": "foo", "username": "username", "color": "blue"}`,
|
Meta: `{"channel": "foo", "username": "username", "color": "blue"}`,
|
||||||
}
|
}
|
||||||
@@ -33,66 +44,69 @@ func TestWebhook_GetSlackHook(t *testing.T) {
|
|||||||
}, *slackHook)
|
}, *slackHook)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrepareWebhooks(t *testing.T) {
|
func testWebhookPrepare(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
hookTasks := []*webhook_model.HookTask{
|
hook := &webhook_model.Webhook{
|
||||||
{HookID: 1, EventType: webhook_module.HookEventPush},
|
RepoID: repo.ID,
|
||||||
}
|
URL: "http://localhost/gitea-webhook-test-prepare_webhooks",
|
||||||
for _, hookTask := range hookTasks {
|
ContentType: webhook_model.ContentTypeJSON,
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
Events: `{"push_only":true}`,
|
||||||
}
|
IsActive: true,
|
||||||
assert.NoError(t, PrepareWebhooks(t.Context(), EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{Commits: []*api.PayloadCommit{{}}}))
|
|
||||||
for _, hookTask := range hookTasks {
|
|
||||||
unittest.AssertExistsAndLoadBean(t, hookTask)
|
|
||||||
}
|
}
|
||||||
|
require.NoError(t, db.Insert(t.Context(), hook))
|
||||||
|
|
||||||
|
hookTask := &webhook_model.HookTask{HookID: hook.ID, EventType: webhook_module.HookEventPush}
|
||||||
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
|
err := PrepareWebhooks(t.Context(), EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{Commits: []*api.PayloadCommit{{}}})
|
||||||
|
require.NoError(t, err)
|
||||||
|
unittest.AssertExistsAndLoadBean(t, hookTask)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrepareWebhooksBranchFilterMatch(t *testing.T) {
|
func testWebhookPrepareBranchFilterMatch(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||||
hookTasks := []*webhook_model.HookTask{
|
hook := &webhook_model.Webhook{
|
||||||
{HookID: 4, EventType: webhook_module.HookEventPush},
|
RepoID: repo.ID,
|
||||||
}
|
URL: "http://localhost/gitea-webhook-test-branch_filter_match",
|
||||||
for _, hookTask := range hookTasks {
|
ContentType: webhook_model.ContentTypeJSON,
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
Events: `{"push_only":true,"branch_filter":"{master,feature*}"}`,
|
||||||
|
IsActive: true,
|
||||||
}
|
}
|
||||||
|
require.NoError(t, db.Insert(t.Context(), hook))
|
||||||
|
|
||||||
|
hookTask := &webhook_model.HookTask{HookID: hook.ID, EventType: webhook_module.HookEventPush}
|
||||||
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
// this test also ensures that * doesn't handle / in any special way (like shell would)
|
// this test also ensures that * doesn't handle / in any special way (like shell would)
|
||||||
assert.NoError(t, PrepareWebhooks(t.Context(), EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{Ref: "refs/heads/feature/7791", Commits: []*api.PayloadCommit{{}}}))
|
err := PrepareWebhooks(t.Context(), EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{Ref: "refs/heads/feature/7791", Commits: []*api.PayloadCommit{{}}})
|
||||||
for _, hookTask := range hookTasks {
|
require.NoError(t, err)
|
||||||
unittest.AssertExistsAndLoadBean(t, hookTask)
|
unittest.AssertExistsAndLoadBean(t, hookTask)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrepareWebhooksBranchFilterNoMatch(t *testing.T) {
|
func testWebhookPrepareBranchFilterNoMatch(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||||
hookTasks := []*webhook_model.HookTask{
|
hook := &webhook_model.Webhook{
|
||||||
{HookID: 4, EventType: webhook_module.HookEventPush},
|
RepoID: repo.ID,
|
||||||
|
URL: "http://localhost/gitea-webhook-test-branch_filter_no_match",
|
||||||
|
ContentType: webhook_model.ContentTypeJSON,
|
||||||
|
Events: `{"push_only":true,"branch_filter":"{master,feature*}"}`,
|
||||||
|
IsActive: true,
|
||||||
}
|
}
|
||||||
for _, hookTask := range hookTasks {
|
require.NoError(t, db.Insert(t.Context(), hook))
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
|
||||||
}
|
|
||||||
assert.NoError(t, PrepareWebhooks(t.Context(), EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{Ref: "refs/heads/fix_weird_bug"}))
|
|
||||||
|
|
||||||
for _, hookTask := range hookTasks {
|
hookTask := &webhook_model.HookTask{HookID: hook.ID, EventType: webhook_module.HookEventPush}
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
}
|
err := PrepareWebhooks(t.Context(), EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{Ref: "refs/heads/fix_weird_bug"})
|
||||||
|
require.NoError(t, err)
|
||||||
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWebhookUserMail(t *testing.T) {
|
func testWebhookUserMail(t *testing.T) {
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
defer test.MockVariableValue(&setting.Service.NoReplyAddress, "no-reply.com")()
|
defer test.MockVariableValue(&setting.Service.NoReplyAddress, "no-reply.com")()
|
||||||
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
assert.Equal(t, user.GetPlaceholderEmail(), convert.ToUser(t.Context(), user, nil).Email)
|
assert.Equal(t, user.GetPlaceholderEmail(), convert.ToUser(t.Context(), user, nil).Email)
|
||||||
assert.Equal(t, user.Email, convert.ToUser(t.Context(), user, user).Email)
|
assert.Equal(t, user.Email, convert.ToUser(t.Context(), user, user).Email)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckBranchFilter(t *testing.T) {
|
func testWebhookCheckBranchFilter(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
filter string
|
filter string
|
||||||
ref git.RefName
|
ref git.RefName
|
||||||
|
|||||||
@@ -87,16 +87,19 @@ func testMain(m *testing.M) int {
|
|||||||
graceful.InitManager(managerCtx)
|
graceful.InitManager(managerCtx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
tests.InitTest()
|
err := tests.InitTest()
|
||||||
|
if err != nil {
|
||||||
|
return testlogger.MainErrorf("InitTest error: %v", err)
|
||||||
|
}
|
||||||
testWebRoutes = routers.NormalRoutes()
|
testWebRoutes = routers.NormalRoutes()
|
||||||
|
|
||||||
err := unittest.InitFixtures(
|
err = unittest.InitFixtures(
|
||||||
unittest.FixturesOptions{
|
unittest.FixturesOptions{
|
||||||
Dir: filepath.Join(filepath.Dir(setting.AppPath), "models/fixtures/"),
|
Dir: filepath.Join(setting.GetGiteaTestSourceRoot(), "models/fixtures/"),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
testlogger.Panicf("InitFixtures: %v", err)
|
return testlogger.MainErrorf("InitFixtures: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: the console logger is deleted by mistake, so if there is any `log.Fatal`, developers won't see any error message.
|
// FIXME: the console logger is deleted by mistake, so if there is any `log.Fatal`, developers won't see any error message.
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ func initMigrationTest(t *testing.T) func() {
|
|||||||
setting.SetupGiteaTestEnv()
|
setting.SetupGiteaTestEnv()
|
||||||
|
|
||||||
assert.NotEmpty(t, setting.RepoRootPath)
|
assert.NotEmpty(t, setting.RepoRootPath)
|
||||||
assert.NoError(t, unittest.SyncDirs(filepath.Join(filepath.Dir(setting.AppPath), "tests/gitea-repositories-meta"), setting.RepoRootPath))
|
assert.NoError(t, unittest.SyncDirs(filepath.Join(setting.GetGiteaTestSourceRoot(), "tests/gitea-repositories-meta"), setting.RepoRootPath))
|
||||||
assert.NoError(t, git.InitFull())
|
assert.NoError(t, git.InitFull())
|
||||||
setting.LoadDBSetting()
|
setting.LoadDBSetting()
|
||||||
setting.InitLoggersForTest()
|
setting.InitLoggersForTest()
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
auth_model "code.gitea.io/gitea/models/auth"
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
git_model "code.gitea.io/gitea/models/git"
|
git_model "code.gitea.io/gitea/models/git"
|
||||||
issues_model "code.gitea.io/gitea/models/issues"
|
issues_model "code.gitea.io/gitea/models/issues"
|
||||||
pull_model "code.gitea.io/gitea/models/pull"
|
pull_model "code.gitea.io/gitea/models/pull"
|
||||||
@@ -92,12 +93,25 @@ func testPullCleanUp(t *testing.T, session *TestSession, user, repo, pullnum str
|
|||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func preparePullMergeWebhook(t *testing.T, repoID int64) {
|
||||||
|
require.NoError(t, db.TruncateBeans(t.Context(), &webhook.Webhook{}, &webhook.HookTask{}))
|
||||||
|
require.NoError(t, db.Insert(t.Context(), &webhook.Webhook{
|
||||||
|
RepoID: repoID,
|
||||||
|
URL: "http://localhost/gitea-test-webhook-pull-merge",
|
||||||
|
ContentType: webhook.ContentTypeJSON,
|
||||||
|
Events: `{"push_only":true,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":false}}`,
|
||||||
|
IsActive: true,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertPullMergeWebhookTask(t *testing.T, repoID int64) {
|
||||||
|
hook := unittest.AssertExistsAndLoadBean(t, &webhook.Webhook{RepoID: repoID})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &webhook.HookTask{HookID: hook.ID})
|
||||||
|
}
|
||||||
|
|
||||||
func TestPullMerge(t *testing.T) {
|
func TestPullMerge(t *testing.T) {
|
||||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||||
hookTasks, err := webhook.HookTasks(t.Context(), 1, 1) // Retrieve previous hook number
|
preparePullMergeWebhook(t, 1)
|
||||||
assert.NoError(t, err)
|
|
||||||
hookTasksLenBefore := len(hookTasks)
|
|
||||||
|
|
||||||
session := loginUser(t, "user1") // FIXME: don't use admin user for testing
|
session := loginUser(t, "user1") // FIXME: don't use admin user for testing
|
||||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "")
|
testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "")
|
||||||
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
||||||
@@ -123,18 +137,13 @@ func TestPullMerge(t *testing.T) {
|
|||||||
assert.Equal(t, 4, repo.NumPulls)
|
assert.Equal(t, 4, repo.NumPulls)
|
||||||
assert.Equal(t, 3, repo.NumOpenPulls)
|
assert.Equal(t, 3, repo.NumOpenPulls)
|
||||||
|
|
||||||
hookTasks, err = webhook.HookTasks(t.Context(), 1, 1)
|
assertPullMergeWebhookTask(t, 1)
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPullRebase(t *testing.T) {
|
func TestPullRebase(t *testing.T) {
|
||||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||||
hookTasks, err := webhook.HookTasks(t.Context(), 1, 1) // Retrieve previous hook number
|
preparePullMergeWebhook(t, 1)
|
||||||
assert.NoError(t, err)
|
|
||||||
hookTasksLenBefore := len(hookTasks)
|
|
||||||
|
|
||||||
session := loginUser(t, "user1") // FIXME: don't use admin user for testing
|
session := loginUser(t, "user1") // FIXME: don't use admin user for testing
|
||||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "")
|
testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "")
|
||||||
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
||||||
@@ -160,18 +169,13 @@ func TestPullRebase(t *testing.T) {
|
|||||||
assert.Equal(t, 4, repo.NumPulls)
|
assert.Equal(t, 4, repo.NumPulls)
|
||||||
assert.Equal(t, 3, repo.NumOpenPulls)
|
assert.Equal(t, 3, repo.NumOpenPulls)
|
||||||
|
|
||||||
hookTasks, err = webhook.HookTasks(t.Context(), 1, 1)
|
assertPullMergeWebhookTask(t, 1)
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPullRebaseMerge(t *testing.T) {
|
func TestPullRebaseMerge(t *testing.T) {
|
||||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||||
hookTasks, err := webhook.HookTasks(t.Context(), 1, 1) // Retrieve previous hook number
|
preparePullMergeWebhook(t, 1)
|
||||||
assert.NoError(t, err)
|
|
||||||
hookTasksLenBefore := len(hookTasks)
|
|
||||||
|
|
||||||
session := loginUser(t, "user1") // FIXME: don't use admin user for testing
|
session := loginUser(t, "user1") // FIXME: don't use admin user for testing
|
||||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "")
|
testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "")
|
||||||
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
||||||
@@ -197,18 +201,13 @@ func TestPullRebaseMerge(t *testing.T) {
|
|||||||
assert.Equal(t, 4, repo.NumPulls)
|
assert.Equal(t, 4, repo.NumPulls)
|
||||||
assert.Equal(t, 3, repo.NumOpenPulls)
|
assert.Equal(t, 3, repo.NumOpenPulls)
|
||||||
|
|
||||||
hookTasks, err = webhook.HookTasks(t.Context(), 1, 1)
|
assertPullMergeWebhookTask(t, 1)
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPullSquash(t *testing.T) {
|
func TestPullSquash(t *testing.T) {
|
||||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||||
hookTasks, err := webhook.HookTasks(t.Context(), 1, 1) // Retrieve previous hook number
|
preparePullMergeWebhook(t, 1)
|
||||||
assert.NoError(t, err)
|
|
||||||
hookTasksLenBefore := len(hookTasks)
|
|
||||||
|
|
||||||
session := loginUser(t, "user1") // FIXME: don't use admin user for testing
|
session := loginUser(t, "user1") // FIXME: don't use admin user for testing
|
||||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "")
|
testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "")
|
||||||
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
||||||
@@ -223,18 +222,13 @@ func TestPullSquash(t *testing.T) {
|
|||||||
DeleteBranch: false,
|
DeleteBranch: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
hookTasks, err = webhook.HookTasks(t.Context(), 1, 1)
|
assertPullMergeWebhookTask(t, 1)
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPullSquashWithHeadCommitID(t *testing.T) {
|
func TestPullSquashWithHeadCommitID(t *testing.T) {
|
||||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||||
hookTasks, err := webhook.HookTasks(t.Context(), 1, 1) // Retrieve previous hook number
|
preparePullMergeWebhook(t, 1)
|
||||||
assert.NoError(t, err)
|
|
||||||
hookTasksLenBefore := len(hookTasks)
|
|
||||||
|
|
||||||
session := loginUser(t, "user1") // FIXME: don't use admin user for testing
|
session := loginUser(t, "user1") // FIXME: don't use admin user for testing
|
||||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "")
|
testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "")
|
||||||
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
||||||
@@ -267,9 +261,7 @@ func TestPullSquashWithHeadCommitID(t *testing.T) {
|
|||||||
assert.Equal(t, 4, repo.NumPulls)
|
assert.Equal(t, 4, repo.NumPulls)
|
||||||
assert.Equal(t, 3, repo.NumOpenPulls)
|
assert.Equal(t, 3, repo.NumOpenPulls)
|
||||||
|
|
||||||
hookTasks, err = webhook.HookTasks(t.Context(), 1, 1)
|
assertPullMergeWebhookTask(t, 1)
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,18 +295,14 @@ func TestPullCleanUpAfterMerge(t *testing.T) {
|
|||||||
|
|
||||||
// Check PR branch deletion
|
// Check PR branch deletion
|
||||||
resp = testPullCleanUp(t, session, elem[1], elem[2], elem[4])
|
resp = testPullCleanUp(t, session, elem[1], elem[2], elem[4])
|
||||||
respJSON := struct {
|
respJSON := test.ParseJSONRedirect(resp.Body.Bytes())
|
||||||
Redirect string
|
require.NotEmpty(t, respJSON.Redirect, "Redirected URL is not found")
|
||||||
}{}
|
|
||||||
DecodeJSON(t, resp, &respJSON)
|
|
||||||
|
|
||||||
assert.NotEmpty(t, respJSON.Redirect, "Redirected URL is not found")
|
elem = strings.Split(*respJSON.Redirect, "/")
|
||||||
|
|
||||||
elem = strings.Split(respJSON.Redirect, "/")
|
|
||||||
assert.Equal(t, "pulls", elem[3])
|
assert.Equal(t, "pulls", elem[3])
|
||||||
|
|
||||||
// Check branch deletion result
|
// Check branch deletion result
|
||||||
req := NewRequest(t, "GET", respJSON.Redirect)
|
req := NewRequest(t, "GET", *respJSON.Redirect)
|
||||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
@@ -767,8 +755,7 @@ func TestPullMergeIndexerNotifier(t *testing.T) {
|
|||||||
|
|
||||||
// search issues
|
// search issues
|
||||||
searchIssuesResp := session.MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
|
searchIssuesResp := session.MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
|
||||||
var apiIssuesBefore []*api.Issue
|
apiIssuesBefore := DecodeJSON(t, searchIssuesResp, []*api.Issue{})
|
||||||
DecodeJSON(t, searchIssuesResp, &apiIssuesBefore)
|
|
||||||
assert.Empty(t, apiIssuesBefore)
|
assert.Empty(t, apiIssuesBefore)
|
||||||
|
|
||||||
// merge the pull request
|
// merge the pull request
|
||||||
@@ -790,11 +777,9 @@ func TestPullMergeIndexerNotifier(t *testing.T) {
|
|||||||
|
|
||||||
// search issues again
|
// search issues again
|
||||||
searchIssuesResp = session.MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
|
searchIssuesResp = session.MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
|
||||||
var apiIssuesAfter []*api.Issue
|
apiIssuesAfter := DecodeJSON(t, searchIssuesResp, []*api.Issue{})
|
||||||
DecodeJSON(t, searchIssuesResp, &apiIssuesAfter)
|
require.Len(t, apiIssuesAfter, 1)
|
||||||
if assert.Len(t, apiIssuesAfter, 1) {
|
assert.Equal(t, issue.ID, apiIssuesAfter[0].ID)
|
||||||
assert.Equal(t, issue.ID, apiIssuesAfter[0].ID)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,14 @@ import (
|
|||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
actions_model "code.gitea.io/gitea/models/actions"
|
actions_model "code.gitea.io/gitea/models/actions"
|
||||||
auth_model "code.gitea.io/gitea/models/auth"
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
|
db_model "code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
"code.gitea.io/gitea/models/repo"
|
"code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
@@ -40,26 +42,28 @@ import (
|
|||||||
|
|
||||||
func TestNewWebHookLink(t *testing.T) {
|
func TestNewWebHookLink(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
require.NoError(t, db_model.Insert(t.Context(), &webhook.Webhook{
|
||||||
|
RepoID: 1,
|
||||||
|
URL: "http://localhost/gitea-test-webhook-link",
|
||||||
|
ContentType: webhook.ContentTypeJSON,
|
||||||
|
Events: `{}`,
|
||||||
|
IsActive: true,
|
||||||
|
}))
|
||||||
|
hook := unittest.AssertExistsAndLoadBean(t, &webhook.Webhook{RepoID: 1})
|
||||||
session := loginUser(t, "user2")
|
session := loginUser(t, "user2")
|
||||||
|
webhooksBaseHref := "/user2/repo1/settings/hooks"
|
||||||
baseurl := "/user2/repo1/settings/hooks"
|
cases := []string{
|
||||||
tests := []string{
|
webhooksBaseHref,
|
||||||
// webhook list page
|
webhooksBaseHref + "/gitea/new",
|
||||||
baseurl,
|
webhooksBaseHref + "/" + strconv.FormatInt(hook.ID, 10), // edit webhook
|
||||||
// new webhook page
|
|
||||||
baseurl + "/gitea/new",
|
|
||||||
// edit webhook page
|
|
||||||
baseurl + "/1",
|
|
||||||
}
|
}
|
||||||
|
for _, reqHref := range cases {
|
||||||
for _, url := range tests {
|
resp := session.MakeRequest(t, NewRequest(t, "GET", reqHref), http.StatusOK)
|
||||||
resp := session.MakeRequest(t, NewRequest(t, "GET", url), http.StatusOK)
|
|
||||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
menus := htmlDoc.doc.Find(".ui.top.attached.header .ui.dropdown .menu a")
|
menus := htmlDoc.doc.Find(".ui.top.attached.header .ui.dropdown .menu a")
|
||||||
menus.Each(func(i int, menu *goquery.Selection) {
|
menus.Each(func(i int, menu *goquery.Selection) {
|
||||||
url, exist := menu.Attr("href")
|
foundHref := menu.AttrOr("href", "")
|
||||||
assert.True(t, exist)
|
assert.True(t, strings.HasPrefix(foundHref, webhooksBaseHref))
|
||||||
assert.True(t, strings.HasPrefix(url, baseurl))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
@@ -15,7 +16,6 @@ import (
|
|||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/graceful"
|
"code.gitea.io/gitea/modules/graceful"
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
"code.gitea.io/gitea/modules/testlogger"
|
"code.gitea.io/gitea/modules/testlogger"
|
||||||
@@ -25,8 +25,9 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitTest() {
|
func InitTest() error {
|
||||||
testlogger.Init()
|
testlogger.Init()
|
||||||
|
|
||||||
if os.Getenv("GITEA_TEST_CONF") == "" {
|
if os.Getenv("GITEA_TEST_CONF") == "" {
|
||||||
// By default, use sqlite.ini for testing, then IDE like GoLand can start the test process with debugger.
|
// By default, use sqlite.ini for testing, then IDE like GoLand can start the test process with debugger.
|
||||||
// It's easier for developers to debug bugs step by step with a debugger.
|
// It's easier for developers to debug bugs step by step with a debugger.
|
||||||
@@ -39,101 +40,102 @@ func InitTest() {
|
|||||||
setting.Repository.DefaultBranch = "master" // many test code still assume that default branch is called "master"
|
setting.Repository.DefaultBranch = "master" // many test code still assume that default branch is called "master"
|
||||||
|
|
||||||
if err := git.InitFull(); err != nil {
|
if err := git.InitFull(); err != nil {
|
||||||
log.Fatal("git.InitOnceWithSync: %v", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
setting.LoadDBSetting()
|
setting.LoadDBSetting()
|
||||||
if err := storage.Init(); err != nil {
|
if err := storage.Init(); err != nil {
|
||||||
testlogger.Panicf("Init storage failed: %v\n", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case setting.Database.Type.IsMySQL():
|
case setting.Database.Type.IsMySQL():
|
||||||
connType := "tcp"
|
{
|
||||||
if len(setting.Database.Host) > 0 && setting.Database.Host[0] == '/' { // looks like a unix socket
|
connType := util.Iif(strings.HasPrefix(setting.Database.Host, "/"), "unix", "tcp")
|
||||||
connType = "unix"
|
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@%s(%s)/",
|
||||||
}
|
setting.Database.User, setting.Database.Passwd, connType, setting.Database.Host))
|
||||||
|
if err != nil {
|
||||||
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@%s(%s)/",
|
return err
|
||||||
setting.Database.User, setting.Database.Passwd, connType, setting.Database.Host))
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
if err != nil {
|
if _, err = db.Exec("CREATE DATABASE IF NOT EXISTS " + setting.Database.Name); err != nil {
|
||||||
log.Fatal("sql.Open: %v", err)
|
return err
|
||||||
}
|
|
||||||
if _, err = db.Exec("CREATE DATABASE IF NOT EXISTS " + setting.Database.Name); err != nil {
|
|
||||||
log.Fatal("db.Exec: %v", err)
|
|
||||||
}
|
|
||||||
case setting.Database.Type.IsPostgreSQL():
|
|
||||||
var db *sql.DB
|
|
||||||
var err error
|
|
||||||
if setting.Database.Host[0] == '/' {
|
|
||||||
db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@/%s?sslmode=%s&host=%s",
|
|
||||||
setting.Database.User, setting.Database.Passwd, setting.Database.Name, setting.Database.SSLMode, setting.Database.Host))
|
|
||||||
} else {
|
|
||||||
db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
|
|
||||||
setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode))
|
|
||||||
}
|
|
||||||
|
|
||||||
defer db.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("sql.Open: %v", err)
|
|
||||||
}
|
|
||||||
dbrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM pg_database WHERE datname = '%s'", setting.Database.Name))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("db.Query: %v", err)
|
|
||||||
}
|
|
||||||
defer dbrows.Close()
|
|
||||||
|
|
||||||
if !dbrows.Next() {
|
|
||||||
if _, err = db.Exec("CREATE DATABASE " + setting.Database.Name); err != nil {
|
|
||||||
log.Fatal("db.Exec: CREATE DATABASE: %v", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check if we need to setup a specific schema
|
case setting.Database.Type.IsPostgreSQL():
|
||||||
if len(setting.Database.Schema) == 0 {
|
openPostgreSQL := func() (*sql.DB, error) {
|
||||||
break
|
if strings.HasPrefix(setting.Database.Host, "/") {
|
||||||
}
|
return sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@/%s?sslmode=%s&host=%s",
|
||||||
db.Close()
|
setting.Database.User, setting.Database.Passwd, setting.Database.Name, setting.Database.SSLMode, setting.Database.Host))
|
||||||
|
}
|
||||||
if setting.Database.Host[0] == '/' {
|
return sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
|
||||||
db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@/%s?sslmode=%s&host=%s",
|
|
||||||
setting.Database.User, setting.Database.Passwd, setting.Database.Name, setting.Database.SSLMode, setting.Database.Host))
|
|
||||||
} else {
|
|
||||||
db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
|
|
||||||
setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode))
|
setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode))
|
||||||
}
|
}
|
||||||
// This is a different db object; requires a different Close()
|
|
||||||
defer db.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("sql.Open: %v", err)
|
|
||||||
}
|
|
||||||
schrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM information_schema.schemata WHERE schema_name = '%s'", setting.Database.Schema))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("db.Query: %v", err)
|
|
||||||
}
|
|
||||||
defer schrows.Close()
|
|
||||||
|
|
||||||
if !schrows.Next() {
|
// create database
|
||||||
// Create and setup a DB schema
|
{
|
||||||
if _, err = db.Exec("CREATE SCHEMA " + setting.Database.Schema); err != nil {
|
db, err := openPostgreSQL()
|
||||||
log.Fatal("db.Exec: CREATE SCHEMA: %v", err)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
dbRows, err := db.Query(fmt.Sprintf("SELECT 1 FROM pg_database WHERE datname = '%s'", setting.Database.Name))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer dbRows.Close()
|
||||||
|
|
||||||
|
if !dbRows.Next() {
|
||||||
|
if _, err = db.Exec("CREATE DATABASE " + setting.Database.Name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check if we need to set up a specific schema
|
||||||
|
if setting.Database.Schema == "" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
db.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// create schema
|
||||||
|
{
|
||||||
|
db, err := openPostgreSQL()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
schemaRows, err := db.Query(fmt.Sprintf("SELECT 1 FROM information_schema.schemata WHERE schema_name = '%s'", setting.Database.Schema))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer schemaRows.Close()
|
||||||
|
|
||||||
|
if !schemaRows.Next() {
|
||||||
|
// Create and set up a DB schema
|
||||||
|
if _, err = db.Exec("CREATE SCHEMA " + setting.Database.Schema); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case setting.Database.Type.IsMSSQL():
|
case setting.Database.Type.IsMSSQL():
|
||||||
host, port := setting.ParseMSSQLHostPort(setting.Database.Host)
|
{
|
||||||
db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
|
host, port := setting.ParseMSSQLHostPort(setting.Database.Host)
|
||||||
host, port, "master", setting.Database.User, setting.Database.Passwd))
|
db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
|
||||||
if err != nil {
|
host, port, "master", setting.Database.User, setting.Database.Passwd))
|
||||||
log.Fatal("sql.Open: %v", err)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
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 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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 {
|
|
||||||
log.Fatal("db.Exec: %v", err)
|
|
||||||
}
|
|
||||||
defer db.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
routers.InitWebInstalled(graceful.GetManager().HammerContext())
|
routers.InitWebInstalled(graceful.GetManager().HammerContext())
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func PrepareAttachmentsStorage(t testing.TB) {
|
func PrepareAttachmentsStorage(t testing.TB) {
|
||||||
@@ -154,7 +156,7 @@ func PrepareGitRepoDirectory(t testing.TB) {
|
|||||||
if !assert.NotEmpty(t, setting.RepoRootPath) {
|
if !assert.NotEmpty(t, setting.RepoRootPath) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert.NoError(t, unittest.SyncDirs(filepath.Join(filepath.Dir(setting.AppPath), "tests/gitea-repositories-meta"), setting.RepoRootPath))
|
assert.NoError(t, unittest.SyncDirs(filepath.Join(setting.GetGiteaTestSourceRoot(), "tests/gitea-repositories-meta"), setting.RepoRootPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
func PrepareArtifactsStorage(t testing.TB) {
|
func PrepareArtifactsStorage(t testing.TB) {
|
||||||
|
|||||||
Reference in New Issue
Block a user