mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
Enable products for tests (#22757)
* Enable products for channels tests * increase unit test timeout; check IsConfigReadOnly * make app-layers * Avoid loading boards tempaltes between tests to improve speed * Fix delete query to be compatible with both databases * Avoid preserving the templates for boards store tests * Run all tests in one command * Revert "Run all tests in one command" This reverts commit0330f7cd8f
. * concurrent pkg group tests in CI * Revert "Revert "Run all tests in one command"" This reverts commit73892fec77
. * Revert "concurrent pkg group tests in CI" This reverts commit550fb6cdd4
. * try testing 3 subsets of packages concurrently to improve time taken * Revert "try testing 3 subsets of packages concurrently to improve time taken" This reverts commit97475f3c4e
. --------- Co-authored-by: Mattermost Build <build@mattermost.com> Co-authored-by: wiggin77 <wiggin77@warpmail.net>
This commit is contained in:
parent
a8d79ec3da
commit
067e36c23c
@ -132,9 +132,7 @@ DIST_PATH_WIN=$(DIST_ROOT)/windows/mattermost
|
||||
TESTS=.
|
||||
|
||||
# Packages lists
|
||||
TE_PACKAGES=$(shell $(GO) list ./... | grep -vE 'server/v8/playbooks|server/v8/boards')
|
||||
BOARDS_PACKAGES=$(shell $(GO) list ./... | grep -E 'server/v8/boards')
|
||||
PLAYBOOKS_PACKAGES=$(shell $(GO) list ./... | grep -E 'server/v8/playbooks')
|
||||
SUITE_PACKAGES=$(shell $(GO) list ./...)
|
||||
|
||||
TEMPLATES_DIR=templates
|
||||
|
||||
@ -170,9 +168,9 @@ endif
|
||||
EE_PACKAGES=$(shell $(GO) list $(BUILD_ENTERPRISE_DIR)/...)
|
||||
|
||||
ifeq ($(BUILD_ENTERPRISE_READY),true)
|
||||
ALL_PACKAGES=$(TE_PACKAGES) $(BOARDS_PACKAGES) $(PLAYBOOKS_PACKAGES) $(EE_PACKAGES)
|
||||
ALL_PACKAGES=$(SUITE_PACKAGES) $(EE_PACKAGES)
|
||||
else
|
||||
ALL_PACKAGES=$(TE_PACKAGES) $(BOARDS_PACKAGES) $(PLAYBOOKS_PACKAGES)
|
||||
ALL_PACKAGES=$(SUITE_PACKAGES)
|
||||
endif
|
||||
|
||||
all: run ## Alias for 'run'.
|
||||
@ -412,7 +410,7 @@ go-junit-report:
|
||||
test-compile: ## Compile tests.
|
||||
@echo COMPILE TESTS
|
||||
|
||||
for package in $(TE_PACKAGES) $(BOARDS_PACKAGES) $(PLAYBOOKS_PACKAGES) $(EE_PACKAGES); do \
|
||||
for package in $(SUITE_PACKAGES) $(EE_PACKAGES); do \
|
||||
$(GO) test $(GOFLAGS) -c $$package; \
|
||||
done
|
||||
|
||||
@ -450,9 +448,7 @@ else
|
||||
endif
|
||||
|
||||
test-server-race: test-server-pre
|
||||
MM_DISABLE_PLAYBOOKS=true MM_DISABLE_BOARDS=true ./scripts/test.sh "$(GO)" "-race $(GOFLAGS)" "$(TE_PACKAGES) $(EE_PACKAGES)" "$(TESTS)" "$(TESTFLAGS)" "$(GOBIN)" "90m" "atomic"
|
||||
MM_DISABLE_PLAYBOOKS=true MM_DISABLE_BOARDS=false ./scripts/test.sh "$(GO)" "-race $(GOFLAGS)" "$(BOARDS_PACKAGES)" "$(TESTS)" "$(TESTFLAGS)" "$(GOBIN)" "90m" "atomic"
|
||||
MM_DISABLE_PLAYBOOKS=false MM_DISABLE_BOARDS=true ./scripts/test.sh "$(GO)" "-race $(GOFLAGS)" "$(PLAYBOOKS_PACKAGES)" "$(TESTS)" "$(TESTFLAGS)" "$(GOBIN)" "90m" "atomic"
|
||||
./scripts/test.sh "$(GO)" "-race $(GOFLAGS)" "$(SUITE_PACKAGES) $(EE_PACKAGES)" "$(TESTS)" "$(TESTFLAGS)" "$(GOBIN)" "90m" "atomic"
|
||||
ifneq ($(IS_CI),true)
|
||||
ifneq ($(MM_NO_DOCKER),true)
|
||||
ifneq ($(TEMP_DOCKER_SERVICES),)
|
||||
@ -463,9 +459,7 @@ ifneq ($(IS_CI),true)
|
||||
endif
|
||||
|
||||
test-server: test-server-pre
|
||||
MM_DISABLE_PLAYBOOKS=true MM_DISABLE_BOARDS=true ./scripts/test.sh "$(GO)" "$(GOFLAGS)" "$(TE_PACKAGES) $(EE_PACKAGES)" "$(TESTS)" "$(TESTFLAGS)" "$(GOBIN)" "45m" "count"
|
||||
MM_DISABLE_PLAYBOOKS=true MM_DISABLE_BOARDS=false ./scripts/test.sh "$(GO)" "$(GOFLAGS)" "$(BOARDS_PACKAGES)" "$(TESTS)" "$(TESTFLAGS)" "$(GOBIN)" "45m" "count"
|
||||
MM_DISABLE_PLAYBOOKS=false MM_DISABLE_BOARDS=true ./scripts/test.sh "$(GO)" "$(GOFLAGS)" "$(PLAYBOOKS_PACKAGES)" "$(TESTS)" "$(TESTFLAGS)" "$(GOBIN)" "45m" "count"
|
||||
./scripts/test.sh "$(GO)" "$(GOFLAGS)" "$(SUITE_PACKAGES) $(EE_PACKAGES)" "$(TESTS)" "$(TESTFLAGS)" "$(GOBIN)" "90m" "count"
|
||||
ifneq ($(IS_CI),true)
|
||||
ifneq ($(MM_NO_DOCKER),true)
|
||||
ifneq ($(TEMP_DOCKER_SERVICES),)
|
||||
@ -477,19 +471,15 @@ endif
|
||||
|
||||
test-server-ee: check-prereqs-enterprise start-docker go-junit-report do-cover-file ## Runs EE tests.
|
||||
@echo Running only EE tests
|
||||
MM_DISABLE_PLAYBOOKS=true MM_DISABLE_BOARDS=true ./scripts/test.sh "$(GO)" "$(GOFLAGS)" "$(EE_PACKAGES)" "$(TESTS)" "$(TESTFLAGS)" "$(GOBIN)" "20m" "count"
|
||||
./scripts/test.sh "$(GO)" "$(GOFLAGS)" "$(EE_PACKAGES)" "$(TESTS)" "$(TESTFLAGS)" "$(GOBIN)" "20m" "count"
|
||||
|
||||
test-server-quick: check-prereqs-enterprise ## Runs only quick tests.
|
||||
ifeq ($(BUILD_ENTERPRISE_READY),true)
|
||||
@echo Running all tests
|
||||
MM_DISABLE_PLAYBOOKS=true MM_DISABLE_BOARDS=true $(GO) test $(GOFLAGS) -short $(TE_PACKAGES) $(EE_PACKAGES)
|
||||
MM_DISABLE_PLAYBOOKS=true MM_DISABLE_BOARDS=false $(GO) test $(GOFLAGS) -short $(BOARDS_PACKAGES)
|
||||
MM_DISABLE_PLAYBOOKS=false MM_DISABLE_BOARDS=true $(GO) test $(GOFLAGS) -short $(PLAYBOOKS_PACKAGES)
|
||||
$(GO) test $(GOFLAGS) -short $(SUITE_PACKAGES) $(EE_PACKAGES)
|
||||
else
|
||||
@echo Running only TE tests
|
||||
MM_DISABLE_PLAYBOOKS=true MM_DISABLE_BOARDS=true $(GO) test $(GOFLAGS) -short $(TE_PACKAGES)
|
||||
MM_DISABLE_PLAYBOOKS=true MM_DISABLE_BOARDS=false $(GO) test $(GOFLAGS) -short $(BOARDS_PACKAGES)
|
||||
MM_DISABLE_PLAYBOOKS=false MM_DISABLE_BOARDS=true $(GO) test $(GOFLAGS) -short $(PLAYBOOKS_PACKAGES)
|
||||
$(GO) test $(GOFLAGS) -short $(SUITE_PACKAGES)
|
||||
endif
|
||||
|
||||
internal-test-web-client: ## Runs web client tests.
|
||||
|
@ -20,11 +20,13 @@ const (
|
||||
botDescription = "Created by Boards plugin."
|
||||
)
|
||||
|
||||
var FocalboardBot = &mm_model.Bot{
|
||||
Username: botUsername,
|
||||
DisplayName: botDisplayname,
|
||||
Description: botDescription,
|
||||
OwnerId: SystemUserID,
|
||||
func GetDefaultFocalboardBot() *mm_model.Bot {
|
||||
return &mm_model.Bot{
|
||||
Username: botUsername,
|
||||
DisplayName: botDisplayname,
|
||||
Description: botDescription,
|
||||
OwnerId: SystemUserID,
|
||||
}
|
||||
}
|
||||
|
||||
type ServicesAPI interface {
|
||||
|
@ -66,7 +66,7 @@ func createSubscriptionsNotifyBackend(params notifyBackendParams) (*notifysubscr
|
||||
}
|
||||
|
||||
func createDelivery(servicesAPI model.ServicesAPI, serverRoot string) (*plugindelivery.PluginDelivery, error) {
|
||||
bot := model.FocalboardBot
|
||||
bot := model.GetDefaultFocalboardBot()
|
||||
|
||||
botID, err := servicesAPI.EnsureBot(bot)
|
||||
if err != nil {
|
||||
|
@ -70,9 +70,10 @@ func New(dbType string, db *sql.DB, store store.Store, logger mlog.LoggerIFace,
|
||||
return layer, nil
|
||||
}
|
||||
|
||||
// Shutdown close the connection with the store.
|
||||
// For MattermostAuthLayer we don't close the database connection
|
||||
// because it's directly managed by the platform
|
||||
func (s *MattermostAuthLayer) Shutdown() error {
|
||||
return s.Store.Shutdown()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) GetRegisteredUserCount() (int, error) {
|
||||
@ -1218,7 +1219,7 @@ func (s *MattermostAuthLayer) GetChannel(teamID, channelID string) (*mm_model.Ch
|
||||
func (s *MattermostAuthLayer) getBoardsBotID() (string, error) {
|
||||
if boardsBotID == "" {
|
||||
var err error
|
||||
boardsBotID, err = s.servicesAPI.EnsureBot(model.FocalboardBot)
|
||||
boardsBotID, err = s.servicesAPI.EnsureBot(model.GetDefaultFocalboardBot())
|
||||
if err != nil {
|
||||
s.logger.Error("failed to ensure boards bot", mlog.Err(err))
|
||||
return "", err
|
||||
|
@ -24,11 +24,11 @@ func TestGetBoardsBotID(t *testing.T) {
|
||||
|
||||
mmAuthLayer, _ := New("test", nil, nil, mlog.CreateConsoleTestLogger(true, mlog.LvlError), servicesAPI, "")
|
||||
|
||||
servicesAPI.EXPECT().EnsureBot(model.FocalboardBot).Return("", errTest)
|
||||
servicesAPI.EXPECT().EnsureBot(model.GetDefaultFocalboardBot()).Return("", errTest)
|
||||
_, err := mmAuthLayer.getBoardsBotID()
|
||||
require.NotEmpty(t, err)
|
||||
|
||||
servicesAPI.EXPECT().EnsureBot(model.FocalboardBot).Return("TestBotID", nil).Times(1)
|
||||
servicesAPI.EXPECT().EnsureBot(model.GetDefaultFocalboardBot()).Return("TestBotID", nil).Times(1)
|
||||
botID, err := mmAuthLayer.getBoardsBotID()
|
||||
require.Empty(t, err)
|
||||
require.NotEmpty(t, botID)
|
||||
|
@ -199,6 +199,10 @@ func (s *SQLStore) DBVersion() string {
|
||||
return version
|
||||
}
|
||||
|
||||
// dropAllTables deletes the contents of all the database tables
|
||||
// except the schema_migrations table with the intention of cleaning
|
||||
// the state for the next text to execute without having to run the
|
||||
// migrations.
|
||||
func (s *SQLStore) dropAllTables(db sq.BaseRunner) error {
|
||||
if s.DBType() == model.PostgresDBType {
|
||||
_, err := db.Exec(`DO
|
||||
|
@ -93,7 +93,9 @@ func setupTestHelper(dbStore store.Store, searchEngine *searchengine.Broker, ent
|
||||
panic("failed to initialize memory store: " + err.Error())
|
||||
}
|
||||
|
||||
memoryConfig := &model.Config{}
|
||||
memoryConfig := &model.Config{
|
||||
SqlSettings: *mainHelper.GetSQLSettings(),
|
||||
}
|
||||
memoryConfig.SetDefaults()
|
||||
*memoryConfig.PluginSettings.Directory = filepath.Join(tempWorkspace, "plugins")
|
||||
*memoryConfig.PluginSettings.ClientDirectory = filepath.Join(tempWorkspace, "webapp")
|
||||
@ -287,6 +289,7 @@ func SetupConfig(tb testing.TB, updateConfig func(cfg *model.Config)) *TestHelpe
|
||||
dbStore := mainHelper.GetStore()
|
||||
dbStore.DropAllTables()
|
||||
dbStore.MarkSystemRanUnitTests()
|
||||
mainHelper.PreloadBoardsMigrationsIfNeeded()
|
||||
searchEngine := mainHelper.GetSearchEngine()
|
||||
th := setupTestHelper(dbStore, searchEngine, false, true, updateConfig, nil)
|
||||
th.InitLogin()
|
||||
@ -294,7 +297,8 @@ func SetupConfig(tb testing.TB, updateConfig func(cfg *model.Config)) *TestHelpe
|
||||
}
|
||||
|
||||
func SetupConfigWithStoreMock(tb testing.TB, updateConfig func(cfg *model.Config)) *TestHelper {
|
||||
th := setupTestHelper(testlib.GetMockStoreForSetupFunctions(), nil, false, false, updateConfig, nil)
|
||||
setupOptions := []app.Option{app.SkipProductsInitialization()}
|
||||
th := setupTestHelper(testlib.GetMockStoreForSetupFunctions(), nil, false, false, updateConfig, setupOptions)
|
||||
statusMock := mocks.StatusStore{}
|
||||
statusMock.On("UpdateExpiredDNDStatuses").Return([]*model.Status{}, nil)
|
||||
statusMock.On("Get", "user1").Return(&model.Status{UserId: "user1", Status: model.StatusOnline}, nil)
|
||||
@ -308,7 +312,8 @@ func SetupConfigWithStoreMock(tb testing.TB, updateConfig func(cfg *model.Config
|
||||
}
|
||||
|
||||
func SetupWithStoreMock(tb testing.TB) *TestHelper {
|
||||
th := setupTestHelper(testlib.GetMockStoreForSetupFunctions(), nil, false, false, nil, nil)
|
||||
setupOptions := []app.Option{app.SkipProductsInitialization()}
|
||||
th := setupTestHelper(testlib.GetMockStoreForSetupFunctions(), nil, false, false, nil, setupOptions)
|
||||
statusMock := mocks.StatusStore{}
|
||||
statusMock.On("UpdateExpiredDNDStatuses").Return([]*model.Status{}, nil)
|
||||
statusMock.On("Get", "user1").Return(&model.Status{UserId: "user1", Status: model.StatusOnline}, nil)
|
||||
@ -322,7 +327,8 @@ func SetupWithStoreMock(tb testing.TB) *TestHelper {
|
||||
}
|
||||
|
||||
func SetupEnterpriseWithStoreMock(tb testing.TB, options ...app.Option) *TestHelper {
|
||||
th := setupTestHelper(testlib.GetMockStoreForSetupFunctions(), nil, true, false, nil, options)
|
||||
setupOptions := append(options, app.SkipProductsInitialization())
|
||||
th := setupTestHelper(testlib.GetMockStoreForSetupFunctions(), nil, true, false, nil, setupOptions)
|
||||
statusMock := mocks.StatusStore{}
|
||||
statusMock.On("UpdateExpiredDNDStatuses").Return([]*model.Status{}, nil)
|
||||
statusMock.On("Get", "user1").Return(&model.Status{UserId: "user1", Status: model.StatusOnline}, nil)
|
||||
@ -479,6 +485,14 @@ func (th *TestHelper) InitBasic() *TestHelper {
|
||||
return th
|
||||
}
|
||||
|
||||
func (th *TestHelper) DeleteBots() *TestHelper {
|
||||
preexistingBots, _ := th.App.GetBots(&model.BotGetOptions{Page: 0, PerPage: 100})
|
||||
for _, bot := range preexistingBots {
|
||||
th.App.PermanentDeleteBot(bot.UserId)
|
||||
}
|
||||
return th
|
||||
}
|
||||
|
||||
func (th *TestHelper) waitForConnectivity() {
|
||||
for i := 0; i < 1000; i++ {
|
||||
conn, err := net.Dial("tcp", fmt.Sprintf("localhost:%v", th.App.Srv().ListenAddr.Port))
|
||||
|
@ -297,11 +297,10 @@ func TestPatchBot(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
|
||||
bots, resp, err := th.Client.GetBots(0, 2, "")
|
||||
bot, resp, err := th.Client.GetBot(createdBot.UserId, "")
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
require.Len(t, bots, 1)
|
||||
require.Equal(t, []*model.Bot{patchedBot}, bots)
|
||||
require.Equal(t, patchedBot, bot)
|
||||
})
|
||||
|
||||
t.Run("patch my bot without permission", func(t *testing.T) {
|
||||
@ -630,7 +629,7 @@ func TestGetBot(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetBots(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
th := Setup(t).InitBasic().DeleteBots()
|
||||
defer th.TearDown()
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
|
@ -4140,6 +4140,12 @@ func TestGetChannelModerations(t *testing.T) {
|
||||
scheme.DefaultChannelGuestRole = ""
|
||||
|
||||
mockStore := mocks.Store{}
|
||||
|
||||
// Playbooks DB job requires a plugin mock
|
||||
pluginStore := mocks.PluginStore{}
|
||||
pluginStore.On("List", mock.Anything, mock.Anything, mock.Anything).Return([]string{}, nil)
|
||||
mockStore.On("Plugin").Return(&pluginStore)
|
||||
|
||||
mockSchemeStore := mocks.SchemeStore{}
|
||||
mockSchemeStore.On("Get", mock.Anything).Return(scheme, nil)
|
||||
mockStore.On("Scheme").Return(&mockSchemeStore)
|
||||
@ -4282,6 +4288,12 @@ func TestPatchChannelModerations(t *testing.T) {
|
||||
scheme.DefaultChannelGuestRole = ""
|
||||
|
||||
mockStore := mocks.Store{}
|
||||
|
||||
// Playbooks DB job requires a plugin mock
|
||||
pluginStore := mocks.PluginStore{}
|
||||
pluginStore.On("List", mock.Anything, mock.Anything, mock.Anything).Return([]string{}, nil)
|
||||
mockStore.On("Plugin").Return(&pluginStore)
|
||||
|
||||
mockSchemeStore := mocks.SchemeStore{}
|
||||
mockSchemeStore.On("Get", mock.Anything).Return(scheme, nil)
|
||||
mockSchemeStore.On("Save", mock.Anything).Return(scheme, nil)
|
||||
@ -4340,7 +4352,6 @@ func TestPatchChannelModerations(t *testing.T) {
|
||||
require.Equal(t, moderation.Roles.Members.Enabled, true)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestGetChannelMemberCountsByGroup(t *testing.T) {
|
||||
|
@ -1541,6 +1541,12 @@ func TestGetFlaggedPostsForUser(t *testing.T) {
|
||||
mockStore.On("License").Return(th.App.Srv().Store().License())
|
||||
mockStore.On("Role").Return(th.App.Srv().Store().Role())
|
||||
mockStore.On("Close").Return(nil)
|
||||
|
||||
// Playbooks DB job requires a plugin mock
|
||||
pluginStore := mocks.PluginStore{}
|
||||
pluginStore.On("List", mock.Anything, mock.Anything, mock.Anything).Return([]string{}, nil)
|
||||
mockStore.On("Plugin").Return(&pluginStore)
|
||||
|
||||
th.App.Srv().SetStore(&mockStore)
|
||||
|
||||
_, resp, err = th.SystemAdminClient.GetFlaggedPostsForUser(user.Id, 0, 10)
|
||||
|
@ -2714,7 +2714,7 @@ func TestGetUsersInTeam(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetUsersNotInTeam(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
th := Setup(t).InitBasic().DeleteBots()
|
||||
defer th.TearDown()
|
||||
teamId := th.BasicTeam.Id
|
||||
|
||||
|
@ -892,6 +892,7 @@ type AppIface interface {
|
||||
InviteNewUsersToTeam(emailList []string, teamID, senderId string) *model.AppError
|
||||
InviteNewUsersToTeamGracefully(memberInvite *model.MemberInvite, teamID, senderId string, reminderInterval string) ([]*model.EmailInviteWithError, *model.AppError)
|
||||
IsCRTEnabledForUser(c request.CTX, userID string) bool
|
||||
IsConfigReadOnly() bool
|
||||
IsFirstAdmin(user *model.User) bool
|
||||
IsFirstUserAccount() bool
|
||||
IsLeader() bool
|
||||
|
@ -12,12 +12,13 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/mattermost/mattermost-server/server/v8/channels/store/storetest/mocks"
|
||||
"github.com/mattermost/mattermost-server/server/v8/model"
|
||||
)
|
||||
|
||||
/* Temporarily comment out until MM-11108
|
||||
/* TODO: Temporarily comment out until MM-11108
|
||||
func TestAppRace(t *testing.T) {
|
||||
for i := 0; i < 10; i++ {
|
||||
a, err := New()
|
||||
@ -61,6 +62,8 @@ func TestUnitUpdateConfig(t *testing.T) {
|
||||
|
||||
prev := *th.App.Config().ServiceSettings.SiteURL
|
||||
|
||||
require.False(t, th.App.IsConfigReadOnly())
|
||||
|
||||
var called int32
|
||||
th.App.AddConfigListener(func(old, current *model.Config) {
|
||||
atomic.AddInt32(&called, 1)
|
||||
|
@ -85,6 +85,12 @@ func TestSessionHasPermissionToChannel(t *testing.T) {
|
||||
// Regression test for MM-29812
|
||||
// Mock the channel store so getting the channel returns with an error, as per the bug report.
|
||||
mockStore := mocks.Store{}
|
||||
|
||||
// Playbooks DB job requires a plugin mock
|
||||
pluginStore := mocks.PluginStore{}
|
||||
pluginStore.On("List", mock.Anything, mock.Anything, mock.Anything).Return([]string{}, nil)
|
||||
mockStore.On("Plugin").Return(&pluginStore)
|
||||
|
||||
mockChannelStore := mocks.ChannelStore{}
|
||||
mockChannelStore.On("Get", mock.Anything, mock.Anything).Return(nil, fmt.Errorf("arbitrary error"))
|
||||
mockChannelStore.On("GetAllChannelMembersForUser", mock.Anything, mock.Anything, mock.Anything).Return(th.App.Srv().Store().Channel().GetAllChannelMembersForUser(th.BasicUser.Id, false, false))
|
||||
|
@ -278,7 +278,7 @@ func TestGetBot(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetBots(t *testing.T) {
|
||||
th := Setup(t)
|
||||
th := Setup(t).DeleteBots()
|
||||
defer th.TearDown()
|
||||
|
||||
OwnerId1 := model.NewId()
|
||||
|
@ -554,7 +554,7 @@ func TestGetDirectChannelCreatesChannelMemberHistoryRecord(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAddUserToChannelCreatesChannelMemberHistoryRecord(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
th := Setup(t).InitBasic().DeleteBots()
|
||||
defer th.TearDown()
|
||||
|
||||
// create a user and add it to a channel
|
||||
|
@ -40,6 +40,10 @@ func (a *App) UpdateConfig(f func(*model.Config)) {
|
||||
a.Srv().platform.UpdateConfig(f)
|
||||
}
|
||||
|
||||
func (a *App) IsConfigReadOnly() bool {
|
||||
return a.Srv().platform.IsConfigReadOnly()
|
||||
}
|
||||
|
||||
func (a *App) ReloadConfig() error {
|
||||
return a.Srv().platform.ReloadConfig()
|
||||
}
|
||||
|
@ -52,8 +52,8 @@ func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer boo
|
||||
}
|
||||
|
||||
configStore := config.NewTestMemoryStore()
|
||||
|
||||
memoryConfig := configStore.Get()
|
||||
memoryConfig.SqlSettings = *mainHelper.GetSQLSettings()
|
||||
*memoryConfig.PluginSettings.Directory = filepath.Join(tempWorkspace, "plugins")
|
||||
*memoryConfig.PluginSettings.ClientDirectory = filepath.Join(tempWorkspace, "webapp")
|
||||
*memoryConfig.PluginSettings.AutomaticPrepackagedPlugins = false
|
||||
@ -138,7 +138,7 @@ func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer boo
|
||||
return th
|
||||
}
|
||||
|
||||
func Setup(tb testing.TB) *TestHelper {
|
||||
func Setup(tb testing.TB, options ...Option) *TestHelper {
|
||||
if testing.Short() {
|
||||
tb.SkipNow()
|
||||
}
|
||||
@ -147,7 +147,7 @@ func Setup(tb testing.TB) *TestHelper {
|
||||
dbStore.MarkSystemRanUnitTests()
|
||||
mainHelper.PreloadMigrations()
|
||||
|
||||
return setupTestHelper(dbStore, false, true, nil, tb)
|
||||
return setupTestHelper(dbStore, false, true, options, tb)
|
||||
}
|
||||
|
||||
func SetupWithoutPreloadMigrations(tb testing.TB) *TestHelper {
|
||||
@ -157,13 +157,16 @@ func SetupWithoutPreloadMigrations(tb testing.TB) *TestHelper {
|
||||
dbStore := mainHelper.GetStore()
|
||||
dbStore.DropAllTables()
|
||||
dbStore.MarkSystemRanUnitTests()
|
||||
// Only boards migrations are applied
|
||||
mainHelper.PreloadBoardsMigrationsIfNeeded()
|
||||
|
||||
return setupTestHelper(dbStore, false, true, nil, tb)
|
||||
}
|
||||
|
||||
func SetupWithStoreMock(tb testing.TB) *TestHelper {
|
||||
mockStore := testlib.GetMockStoreForSetupFunctions()
|
||||
th := setupTestHelper(mockStore, false, false, nil, tb)
|
||||
setupOptions := []Option{SkipProductsInitialization()}
|
||||
th := setupTestHelper(mockStore, false, false, setupOptions, tb)
|
||||
statusMock := mocks.StatusStore{}
|
||||
statusMock.On("UpdateExpiredDNDStatuses").Return([]*model.Status{}, nil)
|
||||
statusMock.On("Get", "user1").Return(&model.Status{UserId: "user1", Status: model.StatusOnline}, nil)
|
||||
@ -184,7 +187,8 @@ func SetupWithStoreMock(tb testing.TB) *TestHelper {
|
||||
|
||||
func SetupEnterpriseWithStoreMock(tb testing.TB) *TestHelper {
|
||||
mockStore := testlib.GetMockStoreForSetupFunctions()
|
||||
th := setupTestHelper(mockStore, true, false, nil, tb)
|
||||
setupOptions := []Option{SkipProductsInitialization()}
|
||||
th := setupTestHelper(mockStore, true, false, setupOptions, tb)
|
||||
statusMock := mocks.StatusStore{}
|
||||
statusMock.On("UpdateExpiredDNDStatuses").Return([]*model.Status{}, nil)
|
||||
statusMock.On("Get", "user1").Return(&model.Status{UserId: "user1", Status: model.StatusOnline}, nil)
|
||||
@ -249,6 +253,14 @@ func (th *TestHelper) InitBasic() *TestHelper {
|
||||
return th
|
||||
}
|
||||
|
||||
func (th *TestHelper) DeleteBots() *TestHelper {
|
||||
preexistingBots, _ := th.App.GetBots(&model.BotGetOptions{Page: 0, PerPage: 100})
|
||||
for _, bot := range preexistingBots {
|
||||
th.App.PermanentDeleteBot(bot.UserId)
|
||||
}
|
||||
return th
|
||||
}
|
||||
|
||||
func (*TestHelper) MakeEmail() string {
|
||||
return "success_" + model.NewId() + "@simulator.amazonses.com"
|
||||
}
|
||||
|
@ -1433,6 +1433,10 @@ func TestPushNotificationRace(t *testing.T) {
|
||||
|
||||
memoryStore := config.NewTestMemoryStore()
|
||||
mockStore := testlib.GetMockStoreForSetupFunctions()
|
||||
// Playbooks DB job requires a plugin mock
|
||||
pluginStore := mocks.PluginStore{}
|
||||
pluginStore.On("List", mock.Anything, mock.Anything, mock.Anything).Return([]string{}, nil)
|
||||
mockStore.On("Plugin").Return(&pluginStore)
|
||||
mockPreferenceStore := mocks.PreferenceStore{}
|
||||
mockPreferenceStore.On("Get",
|
||||
mock.AnythingOfType("string"),
|
||||
@ -1445,10 +1449,12 @@ func TestPushNotificationRace(t *testing.T) {
|
||||
Router: mux.NewRouter(),
|
||||
}
|
||||
var err error
|
||||
s.platform, err = platform.New(platform.ServiceConfig{
|
||||
ConfigStore: memoryStore,
|
||||
}, platform.SetFileStore(&fmocks.FileBackend{}))
|
||||
s.SetStore(mockStore)
|
||||
s.platform, err = platform.New(
|
||||
platform.ServiceConfig{
|
||||
ConfigStore: memoryStore,
|
||||
},
|
||||
platform.SetFileStore(&fmocks.FileBackend{}),
|
||||
platform.StoreOverride(mockStore))
|
||||
require.NoError(t, err)
|
||||
serviceMap := map[product.ServiceKey]any{
|
||||
ServerKey: s,
|
||||
|
@ -12009,6 +12009,23 @@ func (a *OpenTracingAppLayer) IsCRTEnabledForUser(c request.CTX, userID string)
|
||||
return resultVar0
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) IsConfigReadOnly() bool {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.IsConfigReadOnly")
|
||||
|
||||
a.ctx = newCtx
|
||||
a.app.Srv().Store().SetContext(newCtx)
|
||||
defer func() {
|
||||
a.app.Srv().Store().SetContext(origCtx)
|
||||
a.ctx = origCtx
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0 := a.app.IsConfigReadOnly()
|
||||
|
||||
return resultVar0
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) IsFirstAdmin(user *model.User) bool {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.IsFirstAdmin")
|
||||
|
@ -103,6 +103,17 @@ func SkipPostInitialization() Option {
|
||||
}
|
||||
}
|
||||
|
||||
// SkipProductsInitialization is intended for testing only, in cases
|
||||
// where we're mocking components like the store and products cannot
|
||||
// be initialized correctly
|
||||
func SkipProductsInitialization() Option {
|
||||
return func(s *Server) error {
|
||||
s.skipProductsInit = true
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type AppOption func(a *App)
|
||||
type AppOptionCreator func() []AppOption
|
||||
|
||||
|
@ -65,6 +65,11 @@ func (ps *PlatformService) UpdateConfig(f func(*model.Config)) {
|
||||
}
|
||||
}
|
||||
|
||||
// IsConfigReadOnly returns true if the underlying configstore is readonly.
|
||||
func (ps *PlatformService) IsConfigReadOnly() bool {
|
||||
return ps.configStore.IsReadOnly()
|
||||
}
|
||||
|
||||
// SaveConfig replaces the active configuration, optionally notifying cluster peers.
|
||||
// It returns both the previous and current configs.
|
||||
func (ps *PlatformService) SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) (*model.Config, *model.Config, *model.AppError) {
|
||||
|
@ -99,6 +99,7 @@ func (th *TestHelper) InitBasic() *TestHelper {
|
||||
|
||||
func SetupWithStoreMock(tb testing.TB, options ...Option) *TestHelper {
|
||||
mockStore := testlib.GetMockStoreForSetupFunctions()
|
||||
options = append(options, StoreOverride(mockStore))
|
||||
th := setupTestHelper(mockStore, false, false, tb, options...)
|
||||
statusMock := mocks.StatusStore{}
|
||||
statusMock.On("UpdateExpiredDNDStatuses").Return([]*model.Status{}, nil)
|
||||
@ -136,6 +137,7 @@ func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer boo
|
||||
configStore := config.NewTestMemoryStore()
|
||||
|
||||
memoryConfig := configStore.Get()
|
||||
memoryConfig.SqlSettings = *mainHelper.GetSQLSettings()
|
||||
*memoryConfig.PluginSettings.Directory = filepath.Join(tempWorkspace, "plugins")
|
||||
*memoryConfig.PluginSettings.ClientDirectory = filepath.Join(tempWorkspace, "webapp")
|
||||
*memoryConfig.PluginSettings.AutomaticPrepackagedPlugins = false
|
||||
|
@ -28,16 +28,7 @@ func TestReadReplicaDisabledBasedOnLicense(t *testing.T) {
|
||||
if driverName == "" {
|
||||
driverName = model.DatabaseDriverPostgres
|
||||
}
|
||||
dsn := ""
|
||||
if driverName == model.DatabaseDriverPostgres {
|
||||
dsn = os.Getenv("TEST_DATABASE_POSTGRESQL_DSN")
|
||||
} else {
|
||||
dsn = os.Getenv("TEST_DATABASE_MYSQL_DSN")
|
||||
}
|
||||
cfg.SqlSettings = *storetest.MakeSqlSettings(driverName, false)
|
||||
if dsn != "" {
|
||||
cfg.SqlSettings.DataSource = &dsn
|
||||
}
|
||||
cfg.SqlSettings.DataSourceReplicas = []string{*cfg.SqlSettings.DataSource}
|
||||
cfg.SqlSettings.DataSourceSearchReplicas = []string{*cfg.SqlSettings.DataSource}
|
||||
|
||||
|
@ -82,6 +82,7 @@ func TestHubStopWithMultipleConnections(t *testing.T) {
|
||||
// block the caller indefinitely.
|
||||
func TestHubStopRaceCondition(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.Service.Store.Close()
|
||||
// We do not call TearDown because th.TearDown shuts down the hub again. And hub close is not idempotent.
|
||||
// Making it idempotent is not really important to the server because close only happens once.
|
||||
// So we just use this quick hack for the test.
|
||||
|
@ -304,7 +304,7 @@ func TestPluginAPIUpdateUserPreferences(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPluginAPIGetUsers(t *testing.T) {
|
||||
th := Setup(t)
|
||||
th := Setup(t).DeleteBots()
|
||||
defer th.TearDown()
|
||||
api := th.SetupPluginAPI()
|
||||
|
||||
@ -1171,7 +1171,7 @@ func TestBasicAPIPlugins(t *testing.T) {
|
||||
mainPath := path.Join(testFolder, d, "main.go")
|
||||
_, err := os.Stat(mainPath)
|
||||
require.NoError(t, err, "Cannot find plugin main file at %v", mainPath)
|
||||
th := Setup(t).InitBasic()
|
||||
th := Setup(t).InitBasic().DeleteBots()
|
||||
defer th.TearDown()
|
||||
setDefaultPluginConfig(th, dir.Name())
|
||||
err = pluginAPIHookTest(t, th, mainPath, dir.Name(), defaultSchema)
|
||||
|
@ -465,7 +465,6 @@ func (p *TProduct) ExecuteCommand(c *plugin.Context, args *model.CommandArgs) (*
|
||||
}
|
||||
|
||||
func TestProductCommands(t *testing.T) {
|
||||
|
||||
products := map[string]product.Manifest{
|
||||
"productT": {
|
||||
Initializer: newTProduct,
|
||||
@ -474,10 +473,11 @@ func TestProductCommands(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("Execute product command", func(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
th := Setup(t, SkipProductsInitialization()).InitBasic()
|
||||
defer th.TearDown()
|
||||
// Server hijack.
|
||||
// This must be done in a cleaner way.
|
||||
th.Server.skipProductsInit = false
|
||||
th.Server.initializeProducts(products, th.Server.services)
|
||||
th.Server.products["productT"].Start()
|
||||
require.Len(t, th.Server.products, 2) // 1 product + channels
|
||||
@ -504,11 +504,11 @@ func TestProductCommands(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Product commands can override builtin commands", func(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
th := Setup(t, SkipProductsInitialization()).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
// Server hijack.
|
||||
// This must be done in a cleaner way.
|
||||
th.Server.skipProductsInit = false
|
||||
th.Server.initializeProducts(products, th.Server.services)
|
||||
th.Server.products["productT"].Start()
|
||||
require.Len(t, th.Server.products, 2) // 1 product + channels
|
||||
@ -535,8 +535,7 @@ func TestProductCommands(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Plugin commands can override product commands", func(t *testing.T) {
|
||||
|
||||
th := Setup(t).InitBasic()
|
||||
th := Setup(t, SkipProductsInitialization()).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
@ -602,6 +601,7 @@ func TestProductCommands(t *testing.T) {
|
||||
|
||||
// Server hijack.
|
||||
// This must be done in a cleaner way.
|
||||
th.Server.skipProductsInit = false
|
||||
th.Server.initializeProducts(products, th.Server.services)
|
||||
th.Server.products["productT"].Start()
|
||||
require.Len(t, th.Server.products, 2) // 1 product + channels
|
||||
|
@ -1202,7 +1202,7 @@ func TestHookReactionHasBeenRemoved(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHookRunDataRetention(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
th := Setup(t, SkipProductsInitialization()).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
tearDown, pluginIDs, _ := SetAppEnvironmentWithPlugins(t,
|
||||
|
@ -3150,6 +3150,7 @@ func TestGetTopThreadsForUserSince(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetEditHistoryForPost(t *testing.T) {
|
||||
t.Skip("This needs fixing, OriginalId seems to be empty for all posts")
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/mattermost/mattermost-server/server/v8/channels/product"
|
||||
"github.com/mattermost/mattermost-server/server/v8/platform/shared/mlog"
|
||||
)
|
||||
|
||||
func (s *Server) initializeProducts(
|
||||
@ -71,6 +72,11 @@ func (s *Server) initializeProducts(
|
||||
}
|
||||
|
||||
func (s *Server) shouldStart(product string) bool {
|
||||
if s.skipProductsInit && product != "channels" {
|
||||
s.Log().Warn("Skipping product start: disabled via server options", mlog.String("product", product))
|
||||
return false
|
||||
}
|
||||
|
||||
if product == "boards" {
|
||||
if os.Getenv("MM_DISABLE_BOARDS") == "true" {
|
||||
s.Log().Warn("Skipping Boards start: disabled via env var")
|
||||
|
@ -39,8 +39,14 @@ func (p *productB) Start() error { return nil }
|
||||
func (p *productB) Stop() error { return nil }
|
||||
|
||||
func TestInitializeProducts(t *testing.T) {
|
||||
ps, err := platform.New(platform.ServiceConfig{ConfigStore: config.NewTestMemoryStore()})
|
||||
configStore := config.NewTestMemoryStore()
|
||||
memoryConfig := configStore.Get()
|
||||
memoryConfig.SqlSettings = *mainHelper.GetSQLSettings()
|
||||
configStore.Set(memoryConfig)
|
||||
|
||||
ps, err := platform.New(platform.ServiceConfig{ConfigStore: configStore})
|
||||
require.NoError(t, err)
|
||||
defer ps.Shutdown()
|
||||
|
||||
t.Run("2 products and no circular dependency", func(t *testing.T) {
|
||||
serviceMap := map[product.ServiceKey]any{
|
||||
@ -148,24 +154,4 @@ func TestInitializeProducts(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Len(t, server.products, 2)
|
||||
})
|
||||
|
||||
t.Run("boards product to be blocked", func(t *testing.T) {
|
||||
products := map[string]product.Manifest{
|
||||
"productA": {
|
||||
Initializer: newProductA,
|
||||
},
|
||||
"boards": {
|
||||
Initializer: newProductB,
|
||||
},
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
products: make(map[string]product.Product),
|
||||
platform: ps,
|
||||
}
|
||||
|
||||
err := server.initializeProducts(products, map[product.ServiceKey]any{})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, server.products, 1)
|
||||
})
|
||||
}
|
||||
|
@ -137,6 +137,8 @@ type Server struct {
|
||||
|
||||
tracer *tracing.Tracer
|
||||
|
||||
skipProductsInit bool
|
||||
|
||||
products map[string]product.Product
|
||||
services map[product.ServiceKey]any
|
||||
|
||||
|
@ -32,12 +32,17 @@ import (
|
||||
"github.com/mattermost/mattermost-server/server/v8/platform/shared/mlog"
|
||||
)
|
||||
|
||||
func newServer(t *testing.T) (*Server, error) {
|
||||
return newServerWithConfig(t, func(_ *model.Config) {})
|
||||
}
|
||||
|
||||
func newServerWithConfig(t *testing.T, f func(cfg *model.Config)) (*Server, error) {
|
||||
configStore, err := config.NewMemoryStore()
|
||||
require.NoError(t, err)
|
||||
store, err := config.NewStoreFromBacking(configStore, nil, false)
|
||||
require.NoError(t, err)
|
||||
cfg := store.Get()
|
||||
cfg.SqlSettings = *mainHelper.GetSQLSettings()
|
||||
f(cfg)
|
||||
|
||||
store.Set(cfg)
|
||||
@ -61,13 +66,13 @@ func TestStartServerSuccess(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStartServerPortUnavailable(t *testing.T) {
|
||||
s, err := NewServer()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Listen on the next available port
|
||||
listener, err := net.Listen("tcp", "localhost:0")
|
||||
require.NoError(t, err)
|
||||
|
||||
s, err := newServer(t)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Attempt to listen on the port used above.
|
||||
s.platform.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.ListenAddress = listener.Addr().String()
|
||||
@ -105,6 +110,7 @@ func TestStartServerNoS3Bucket(t *testing.T) {
|
||||
AmazonS3SSL: model.NewBool(false),
|
||||
}
|
||||
*cfg.ServiceSettings.ListenAddress = "localhost:0"
|
||||
cfg.SqlSettings = *mainHelper.GetSQLSettings()
|
||||
_, _, err := store.Set(cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -162,7 +168,7 @@ func TestDatabaseTypeAndMattermostVersion(t *testing.T) {
|
||||
|
||||
os.Setenv("MM_SQLSETTINGS_DRIVERNAME", "postgres")
|
||||
|
||||
th := Setup(t)
|
||||
th := Setup(t, SkipProductsInitialization())
|
||||
defer th.TearDown()
|
||||
|
||||
databaseType, mattermostVersion := th.Server.DatabaseTypeAndSchemaVersion()
|
||||
@ -171,7 +177,7 @@ func TestDatabaseTypeAndMattermostVersion(t *testing.T) {
|
||||
|
||||
os.Setenv("MM_SQLSETTINGS_DRIVERNAME", "mysql")
|
||||
|
||||
th2 := Setup(t)
|
||||
th2 := Setup(t, SkipProductsInitialization())
|
||||
defer th2.TearDown()
|
||||
|
||||
databaseType, mattermostVersion = th2.Server.DatabaseTypeAndSchemaVersion()
|
||||
@ -190,6 +196,7 @@ func TestStartServerTLSVersion(t *testing.T) {
|
||||
*cfg.ServiceSettings.TLSMinVer = "1.2"
|
||||
*cfg.ServiceSettings.TLSKeyFile = path.Join(testDir, "tls_test_key.pem")
|
||||
*cfg.ServiceSettings.TLSCertFile = path.Join(testDir, "tls_test_cert.pem")
|
||||
cfg.SqlSettings = *mainHelper.GetSQLSettings()
|
||||
|
||||
store.Set(cfg)
|
||||
|
||||
@ -316,7 +323,7 @@ func TestPanicLog(t *testing.T) {
|
||||
logger.LockConfiguration()
|
||||
|
||||
// Creating a server with logger
|
||||
s, err := NewServer()
|
||||
s, err := newServer(t)
|
||||
require.NoError(t, err)
|
||||
s.Platform().SetLogger(logger)
|
||||
|
||||
|
@ -51,6 +51,7 @@ func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer boo
|
||||
if configSet != nil {
|
||||
configSet(memoryConfig)
|
||||
}
|
||||
memoryConfig.SqlSettings = *mainHelper.GetSQLSettings()
|
||||
*memoryConfig.PluginSettings.Directory = filepath.Join(tempWorkspace, "plugins")
|
||||
*memoryConfig.PluginSettings.ClientDirectory = filepath.Join(tempWorkspace, "webapp")
|
||||
*memoryConfig.PluginSettings.AutomaticPrepackagedPlugins = false
|
||||
@ -142,6 +143,7 @@ func setup(tb testing.TB) *TestHelper {
|
||||
dbStore := mainHelper.GetStore()
|
||||
dbStore.DropAllTables()
|
||||
dbStore.MarkSystemRanUnitTests()
|
||||
mainHelper.PreloadBoardsMigrationsIfNeeded()
|
||||
|
||||
return setupTestHelper(dbStore, false, true, tb, nil)
|
||||
}
|
||||
|
@ -1026,7 +1026,7 @@ func TestCreateUserWithToken(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPermanentDeleteUser(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
th := Setup(t).InitBasic().DeleteBots()
|
||||
defer th.TearDown()
|
||||
|
||||
b := []byte("testimage")
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
func TestRestrictedViewMembers(t *testing.T) {
|
||||
th := Setup(t)
|
||||
th := Setup(t).DeleteBots()
|
||||
defer th.TearDown()
|
||||
|
||||
user1 := th.CreateUser()
|
||||
|
@ -993,6 +993,7 @@ func (ss *SqlStore) TrueUpReview() store.TrueUpReviewStore {
|
||||
}
|
||||
|
||||
func (ss *SqlStore) DropAllTables() {
|
||||
var tableSchemaFn string
|
||||
if ss.DriverName() == model.DatabaseDriverPostgres {
|
||||
ss.masterX.Exec(`DO
|
||||
$func$
|
||||
@ -1002,18 +1003,57 @@ func (ss *SqlStore) DropAllTables() {
|
||||
FROM pg_class
|
||||
WHERE relkind = 'r' -- only tables
|
||||
AND relnamespace = 'public'::regnamespace
|
||||
AND NOT relname = 'db_migrations'
|
||||
AND NOT (
|
||||
relname = 'db_migrations' OR
|
||||
relname = 'focalboard_schema_migrations' OR
|
||||
relname = 'focalboard_boards' OR
|
||||
relname = 'focalboard_blocks'
|
||||
)
|
||||
);
|
||||
END
|
||||
$func$;`)
|
||||
tableSchemaFn = "current_schema()"
|
||||
} else {
|
||||
tables := []string{}
|
||||
ss.masterX.Select(&tables, `show tables`)
|
||||
for _, t := range tables {
|
||||
if t != "db_migrations" {
|
||||
if t != "db_migrations" &&
|
||||
t != "focalboard_schema_migrations" &&
|
||||
t != "focalboard_boards" &&
|
||||
t != "focalboard_blocks" {
|
||||
ss.masterX.Exec(`TRUNCATE TABLE ` + t)
|
||||
|
||||
}
|
||||
}
|
||||
tableSchemaFn = "DATABASE()"
|
||||
}
|
||||
|
||||
var boardsTableCount int
|
||||
err := ss.masterX.Get(&boardsTableCount, `
|
||||
SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_SCHEMA = `+tableSchemaFn+`
|
||||
AND TABLE_NAME = 'focalboard_schema_migrations'`)
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "Error dropping all tables. Cannot query INFORMATION_SCHEMA table to check for focalboard_schema_migrations table"))
|
||||
}
|
||||
|
||||
if boardsTableCount != 0 {
|
||||
_, blErr := ss.masterX.Exec(`
|
||||
DELETE FROM focalboard_blocks
|
||||
WHERE board_id IN (
|
||||
SELECT id
|
||||
FROM focalboard_boards
|
||||
WHERE NOT is_template
|
||||
)`)
|
||||
if blErr != nil {
|
||||
panic(errors.Wrap(blErr, "Error deleting all non-template blocks"))
|
||||
}
|
||||
|
||||
_, boErr := ss.masterX.Exec(`DELETE FROM focalboard_boards WHERE NOT is_template`)
|
||||
if boErr != nil {
|
||||
panic(errors.Wrap(boErr, "Error delegint all non-template boards"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,11 @@ type HelperOptions struct {
|
||||
}
|
||||
|
||||
func NewMainHelper() *MainHelper {
|
||||
// Ignore any globally defined datasource if a test dsn defined
|
||||
if os.Getenv("TEST_DATABASE_MYSQL_DSN") != "" || os.Getenv("TEST_DATABASE_POSTGRESQL_DSN") != "" {
|
||||
os.Unsetenv("MM_SQLSETTINGS_DATASOURCE")
|
||||
}
|
||||
|
||||
return NewMainHelperWithOptions(&HelperOptions{
|
||||
EnableStore: true,
|
||||
EnableResources: true,
|
||||
@ -48,6 +53,11 @@ func NewMainHelper() *MainHelper {
|
||||
}
|
||||
|
||||
func NewMainHelperWithOptions(options *HelperOptions) *MainHelper {
|
||||
// Ignore any globally defined datasource if a test dsn defined
|
||||
if os.Getenv("TEST_DATABASE_MYSQL_DSN") != "" || os.Getenv("TEST_DATABASE_POSTGRESQL_DSN") != "" {
|
||||
os.Unsetenv("MM_SQLSETTINGS_DATASOURCE")
|
||||
}
|
||||
|
||||
var mainHelper MainHelper
|
||||
flag.Parse()
|
||||
|
||||
@ -153,6 +163,7 @@ func (h *MainHelper) setupResources() {
|
||||
func (h *MainHelper) PreloadMigrations() {
|
||||
var buf []byte
|
||||
var err error
|
||||
|
||||
basePath := os.Getenv("MM_SERVER_PATH")
|
||||
if basePath == "" {
|
||||
basePath = "mattermost-server/server"
|
||||
@ -177,6 +188,62 @@ func (h *MainHelper) PreloadMigrations() {
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "Error preloading migrations. Check if you have &multiStatements=true in your DSN if you are using MySQL. Or perhaps the schema changed? If yes, then update the warmup files accordingly"))
|
||||
}
|
||||
|
||||
h.PreloadBoardsMigrationsIfNeeded()
|
||||
}
|
||||
|
||||
// PreloadBoardsMigrationsIfNeeded loads boards migrations if the
|
||||
// focalboard_schema_migrations table exists already.
|
||||
// Besides this, the same compatibility and breaking conditions that
|
||||
// PreloadMigrations has apply here.
|
||||
//
|
||||
// Re-generate the files with:
|
||||
// pg_dump -a -h localhost -U mmuser -d <> --no-comments --inserts -t focalboard_system_settings
|
||||
// mysqldump -u root -p <> --no-create-info --extended-insert=FALSE focalboard_system_settings
|
||||
func (h *MainHelper) PreloadBoardsMigrationsIfNeeded() {
|
||||
tableSchemaFn := "current_schema()"
|
||||
if *h.Settings.DriverName == model.DatabaseDriverMysql {
|
||||
tableSchemaFn = "DATABASE()"
|
||||
}
|
||||
|
||||
basePath := os.Getenv("MM_SERVER_PATH")
|
||||
if basePath == "" {
|
||||
basePath = "mattermost-server/server"
|
||||
}
|
||||
relPath := "channels/testlib/testdata"
|
||||
|
||||
handle := h.SQLStore.GetMasterX()
|
||||
var boardsTableCount int
|
||||
gErr := handle.Get(&boardsTableCount, `
|
||||
SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_SCHEMA = `+tableSchemaFn+`
|
||||
AND TABLE_NAME = 'focalboard_schema_migrations'`)
|
||||
if gErr != nil {
|
||||
panic(errors.Wrap(gErr, "Error preloading migrations. Cannot query INFORMATION_SCHEMA table to check for focalboard_schema_migrations table"))
|
||||
}
|
||||
|
||||
var buf []byte
|
||||
var err error
|
||||
if boardsTableCount != 0 {
|
||||
switch *h.Settings.DriverName {
|
||||
case model.DatabaseDriverPostgres:
|
||||
boardsFinalPath := filepath.Join(basePath, relPath, "boards_postgres_migration_warmup.sql")
|
||||
buf, err = os.ReadFile(boardsFinalPath)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot read file: %v", err))
|
||||
}
|
||||
case model.DatabaseDriverMysql:
|
||||
boardsFinalPath := filepath.Join(basePath, relPath, "boards_mysql_migration_warmup.sql")
|
||||
buf, err = os.ReadFile(boardsFinalPath)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot read file: %v", err))
|
||||
}
|
||||
}
|
||||
if _, err := handle.Exec(string(buf)); err != nil {
|
||||
panic(errors.Wrap(err, "Error preloading boards migrations. Check if you have &multiStatements=true in your DSN if you are using MySQL. Or perhaps the schema changed? If yes, then update the warmup files accordingly"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *MainHelper) Close() error {
|
||||
|
@ -101,6 +101,9 @@ func GetMockStoreForSetupFunctions() *mocks.Store {
|
||||
oAuthStore := mocks.OAuthStore{}
|
||||
groupStore := mocks.GroupStore{}
|
||||
|
||||
pluginStore := mocks.PluginStore{}
|
||||
pluginStore.On("List", mock.Anything, mock.Anything, mock.Anything).Return([]string{}, nil)
|
||||
|
||||
mockStore.On("System").Return(&systemStore)
|
||||
mockStore.On("User").Return(&userStore)
|
||||
mockStore.On("Post").Return(&postStore)
|
||||
@ -116,6 +119,7 @@ func GetMockStoreForSetupFunctions() *mocks.Store {
|
||||
mockStore.On("OAuth").Return(&oAuthStore)
|
||||
mockStore.On("Group").Return(&groupStore)
|
||||
mockStore.On("GetDBSchemaVersion").Return(1, nil)
|
||||
mockStore.On("Plugin").Return(&pluginStore)
|
||||
|
||||
return &mockStore
|
||||
}
|
||||
|
41
server/channels/testlib/testdata/boards_mysql_migration_warmup.sql
vendored
Normal file
41
server/channels/testlib/testdata/boards_mysql_migration_warmup.sql
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
-- MySQL dump 10.13 Distrib 5.7.12, for Linux (x86_64)
|
||||
--
|
||||
-- Host: localhost Database: mattermost_test
|
||||
-- ------------------------------------------------------
|
||||
-- Server version 5.7.12
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `focalboard_system_settings`
|
||||
--
|
||||
|
||||
LOCK TABLES `focalboard_system_settings` WRITE;
|
||||
/*!40000 ALTER TABLE `focalboard_system_settings` DISABLE KEYS */;
|
||||
INSERT INTO `focalboard_system_settings` VALUES ('CategoryUuidIdMigrationComplete','true');
|
||||
INSERT INTO `focalboard_system_settings` VALUES ('DeDuplicateCategoryBoardTableComplete','true');
|
||||
INSERT INTO `focalboard_system_settings` VALUES ('DeletedMembershipBoardsMigrationComplete','true');
|
||||
INSERT INTO `focalboard_system_settings` VALUES ('TeamLessBoardsMigrationComplete','true');
|
||||
INSERT INTO `focalboard_system_settings` VALUES ('UniqueIDsMigrationComplete','true');
|
||||
/*!40000 ALTER TABLE `focalboard_system_settings` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
-- Dump completed on 2023-03-31 11:37:35
|
26
server/channels/testlib/testdata/boards_postgres_migration_warmup.sql
vendored
Normal file
26
server/channels/testlib/testdata/boards_postgres_migration_warmup.sql
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
--
|
||||
-- PostgreSQL database dump
|
||||
--
|
||||
|
||||
-- Dumped from database version 10.20 (Debian 10.20-1.pgdg90+1)
|
||||
-- Dumped by pg_dump version 14.7
|
||||
|
||||
SET statement_timeout = 0;
|
||||
SET lock_timeout = 0;
|
||||
SET idle_in_transaction_session_timeout = 0;
|
||||
SET client_encoding = 'UTF8';
|
||||
|
||||
--
|
||||
-- Data for Name: focalboard_system_settings; Type: TABLE DATA; Schema: public; Owner: mmuser
|
||||
--
|
||||
|
||||
INSERT INTO public.focalboard_system_settings VALUES ('UniqueIDsMigrationComplete', 'true');
|
||||
INSERT INTO public.focalboard_system_settings VALUES ('TeamLessBoardsMigrationComplete', 'true');
|
||||
INSERT INTO public.focalboard_system_settings VALUES ('DeletedMembershipBoardsMigrationComplete', 'true');
|
||||
INSERT INTO public.focalboard_system_settings VALUES ('CategoryUuidIdMigrationComplete', 'true');
|
||||
INSERT INTO public.focalboard_system_settings VALUES ('DeDuplicateCategoryBoardTableComplete', 'true');
|
||||
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump complete
|
||||
--
|
@ -55,7 +55,7 @@ func SetupWithStoreMock(tb testing.TB) *TestHelper {
|
||||
tb.SkipNow()
|
||||
}
|
||||
|
||||
th := setupTestHelper(tb, false)
|
||||
th := setupTestHelper(tb, false, []app.Option{app.SkipProductsInitialization()})
|
||||
emptyMockStore := mocks.Store{}
|
||||
emptyMockStore.On("Close").Return(nil)
|
||||
th.App.Srv().SetStore(&emptyMockStore)
|
||||
@ -68,17 +68,18 @@ func Setup(tb testing.TB) *TestHelper {
|
||||
}
|
||||
store := mainHelper.GetStore()
|
||||
store.DropAllTables()
|
||||
return setupTestHelper(tb, true)
|
||||
mainHelper.PreloadBoardsMigrationsIfNeeded()
|
||||
return setupTestHelper(tb, true, nil)
|
||||
}
|
||||
|
||||
func setupTestHelper(tb testing.TB, includeCacheLayer bool) *TestHelper {
|
||||
func setupTestHelper(tb testing.TB, includeCacheLayer bool, options []app.Option) *TestHelper {
|
||||
memoryStore := config.NewTestMemoryStore()
|
||||
newConfig := memoryStore.Get().Clone()
|
||||
newConfig.SqlSettings = *mainHelper.GetSQLSettings()
|
||||
*newConfig.AnnouncementSettings.AdminNoticesEnabled = false
|
||||
*newConfig.AnnouncementSettings.UserNoticesEnabled = false
|
||||
*newConfig.PluginSettings.AutomaticPrepackagedPlugins = false
|
||||
memoryStore.Set(newConfig)
|
||||
var options []app.Option
|
||||
options = append(options, app.ConfigStore(memoryStore))
|
||||
options = append(options, app.StoreOverride(mainHelper.Store))
|
||||
|
||||
|
@ -65,6 +65,7 @@ func TestRunServerSuccess(t *testing.T) {
|
||||
// Use non-default listening port in case another server instance is already running.
|
||||
cfg := configStore.Get()
|
||||
*cfg.ServiceSettings.ListenAddress = unitTestListeningPort
|
||||
cfg.SqlSettings = *mainHelper.GetSQLSettings()
|
||||
configStore.Set(cfg)
|
||||
|
||||
err := runServer(configStore, th.interruptChan)
|
||||
@ -117,6 +118,7 @@ func TestRunServerSystemdNotification(t *testing.T) {
|
||||
// Use non-default listening port in case another server instance is already running.
|
||||
cfg := configStore.Get()
|
||||
*cfg.ServiceSettings.ListenAddress = unitTestListeningPort
|
||||
cfg.SqlSettings = *mainHelper.GetSQLSettings()
|
||||
configStore.Set(cfg)
|
||||
|
||||
// Start and stop the server
|
||||
@ -142,6 +144,7 @@ func TestRunServerNoSystemd(t *testing.T) {
|
||||
// Use non-default listening port in case another server instance is already running.
|
||||
cfg := configStore.Get()
|
||||
*cfg.ServiceSettings.ListenAddress = unitTestListeningPort
|
||||
cfg.SqlSettings = *mainHelper.GetSQLSettings()
|
||||
configStore.Set(cfg)
|
||||
|
||||
err := runServer(configStore, th.interruptChan)
|
||||
|
Loading…
Reference in New Issue
Block a user