* [MM-13828] Running tests from a new temp folder with all test resources Possible fix for #10132 All packages which have a TestMain and use testlib.MainHelper will have a new current working directory which will have all the test resources copied. Note: default.json is copied as config.json as well to make sure tests don't have any impact due to changes in config by devs * [MM-13828] Added TestMain to remaining packages to use testlib.MainHelper This makes sure tests from all packages run with same test resources, setup in a new temp folder for each package * Updated Jenkins file to not not config/default.json This makes sure CI has same config files as a dev's machine * [MM-13828] Changes requested from code review Added accessor methods to testlib.MainHelper for accessing members Fixed some broken tests due to change in cwd while tests run Some other code refactoring and improvements * [MM-13828] Added new factory method with options for creating test main helper and some code refactoring testlib.NewMainHelperWithOptions supports options to turn on/off test dependencies and environment setup Some other code refactoring * Exporting members of testlib.MainHelper to make enterprise tests work * Fixed gofmt error * [MM-13828] removed unwanted dependency on plugins directory while setting up test resources * [MM-13828] Fixed some tests failing due to them being running from temp folder * [MM-13828] Some code changes suggested in PR review * Fixed gofmt error
186 строки
4.9 KiB
Go
186 строки
4.9 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See License.txt for license information.
|
|
|
|
package commands
|
|
|
|
import (
|
|
"bytes"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/mattermost/mattermost-server/api4"
|
|
"github.com/mattermost/mattermost-server/model"
|
|
"github.com/mattermost/mattermost-server/testlib"
|
|
)
|
|
|
|
var coverprofileCounters map[string]int = make(map[string]int)
|
|
|
|
var mainHelper *testlib.MainHelper
|
|
|
|
type testHelper struct {
|
|
*api4.TestHelper
|
|
|
|
config *model.Config
|
|
tempDir string
|
|
configFilePath string
|
|
disableAutoConfig bool
|
|
}
|
|
|
|
// Setup creates an instance of testHelper.
|
|
func Setup() *testHelper {
|
|
dir, err := ioutil.TempDir("", "testHelper")
|
|
if err != nil {
|
|
panic("failed to create temporary directory: " + err.Error())
|
|
}
|
|
|
|
api4TestHelper := api4.Setup()
|
|
|
|
testHelper := &testHelper{
|
|
TestHelper: api4TestHelper,
|
|
tempDir: dir,
|
|
configFilePath: filepath.Join(dir, "config-helper.json"),
|
|
}
|
|
|
|
config := &model.Config{}
|
|
config.SetDefaults()
|
|
testHelper.SetConfig(config)
|
|
|
|
return testHelper
|
|
}
|
|
|
|
// InitBasic simply proxies to api4.InitBasic, while still returning a testHelper.
|
|
func (h *testHelper) InitBasic() *testHelper {
|
|
h.TestHelper.InitBasic()
|
|
return h
|
|
}
|
|
|
|
// TemporaryDirectory returns the temporary directory created for user by the test helper.
|
|
func (h *testHelper) TemporaryDirectory() string {
|
|
return h.tempDir
|
|
}
|
|
|
|
// Config returns the configuration passed to a running command.
|
|
func (h *testHelper) Config() *model.Config {
|
|
return h.config.Clone()
|
|
}
|
|
|
|
// ConfigPath returns the path to the temporary config file passed to a running command.
|
|
func (h *testHelper) ConfigPath() string {
|
|
return h.configFilePath
|
|
}
|
|
|
|
// SetConfig replaces the configuration passed to a running command.
|
|
func (h *testHelper) SetConfig(config *model.Config) {
|
|
config.SqlSettings = *mainHelper.GetSqlSettings()
|
|
h.config = config
|
|
|
|
if err := ioutil.WriteFile(h.configFilePath, []byte(config.ToJson()), 0600); err != nil {
|
|
panic("failed to write file " + h.configFilePath + ": " + err.Error())
|
|
}
|
|
}
|
|
|
|
// SetAutoConfig configures whether the --config flag is automatically passed to a running command.
|
|
func (h *testHelper) SetAutoConfig(autoConfig bool) {
|
|
h.disableAutoConfig = !autoConfig
|
|
}
|
|
|
|
// TearDown cleans up temporary files and assets created during the life of the test helper.
|
|
func (h *testHelper) TearDown() {
|
|
h.TestHelper.TearDown()
|
|
os.RemoveAll(h.tempDir)
|
|
}
|
|
|
|
func (h *testHelper) execArgs(t *testing.T, args []string) []string {
|
|
ret := []string{"-test.v", "-test.run", "ExecCommand"}
|
|
if coverprofile := flag.Lookup("test.coverprofile").Value.String(); coverprofile != "" {
|
|
dir := filepath.Dir(coverprofile)
|
|
base := filepath.Base(coverprofile)
|
|
baseParts := strings.SplitN(base, ".", 2)
|
|
name := strings.Replace(t.Name(), "/", "_", -1)
|
|
coverprofileCounters[name] = coverprofileCounters[name] + 1
|
|
baseParts[0] = fmt.Sprintf("%v-%v-%v", baseParts[0], name, coverprofileCounters[name])
|
|
ret = append(ret, "-test.coverprofile", filepath.Join(dir, strings.Join(baseParts, ".")))
|
|
}
|
|
|
|
ret = append(ret, "--", "--disableconfigwatch")
|
|
|
|
// Unless the test passes a `--config` of its own, create a temporary one from the default
|
|
// configuration with the current test database applied.
|
|
hasConfig := h.disableAutoConfig
|
|
for _, arg := range args {
|
|
if arg == "--config" {
|
|
hasConfig = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !hasConfig {
|
|
ret = append(ret, "--config", h.configFilePath)
|
|
}
|
|
|
|
ret = append(ret, args...)
|
|
|
|
return ret
|
|
}
|
|
|
|
func (h *testHelper) cmd(t *testing.T, args []string) *exec.Cmd {
|
|
path, err := os.Executable()
|
|
require.NoError(t, err)
|
|
cmd := exec.Command(path, h.execArgs(t, args)...)
|
|
|
|
cmd.Env = []string{}
|
|
for _, env := range os.Environ() {
|
|
// Ignore MM_SQLSETTINGS_DATASOURCE from the environment, since we override.
|
|
if strings.HasPrefix(env, "MM_SQLSETTINGS_DATASOURCE=") {
|
|
continue
|
|
}
|
|
|
|
cmd.Env = append(cmd.Env, env)
|
|
}
|
|
|
|
return cmd
|
|
}
|
|
|
|
// CheckCommand invokes the test binary, returning the output modified for assertion testing.
|
|
func (h *testHelper) CheckCommand(t *testing.T, args ...string) string {
|
|
output, err := h.cmd(t, args).CombinedOutput()
|
|
require.NoError(t, err, string(output))
|
|
return strings.TrimSpace(strings.TrimSuffix(strings.TrimSpace(string(output)), "PASS"))
|
|
}
|
|
|
|
// RunCommand invokes the test binary, returning only any error.
|
|
func (h *testHelper) RunCommand(t *testing.T, args ...string) error {
|
|
return h.cmd(t, args).Run()
|
|
}
|
|
|
|
// RunCommandWithOutput is a variant of RunCommand that returns the unmodified output and any error.
|
|
func (h *testHelper) RunCommandWithOutput(t *testing.T, args ...string) (string, error) {
|
|
cmd := h.cmd(t, args)
|
|
|
|
var buf bytes.Buffer
|
|
reader, writer := io.Pipe()
|
|
cmd.Stdout = writer
|
|
cmd.Stderr = writer
|
|
|
|
done := make(chan bool)
|
|
go func() {
|
|
io.Copy(&buf, reader)
|
|
close(done)
|
|
}()
|
|
|
|
err := cmd.Run()
|
|
writer.Close()
|
|
<-done
|
|
|
|
return buf.String(), err
|
|
}
|