From 4582823f87bd69ba7abc3f2f639b427c23e1e9f0 Mon Sep 17 00:00:00 2001 From: Jesse Hallam Date: Sat, 18 Apr 2020 04:08:57 -0300 Subject: [PATCH] fix /test command (#14169) Automatic Merge --- app/auto_channels.go | 18 +++--- app/auto_environment.go | 53 +++++++++------ app/auto_posts.go | 34 +++++----- app/auto_teams.go | 22 +++---- app/auto_users.go | 62 +++++++++--------- app/command_loadtest.go | 140 +++++++++++++++++++++++----------------- tests/testjpg.jpg | Bin 0 -> 40600 bytes 7 files changed, 181 insertions(+), 148 deletions(-) create mode 100644 tests/testjpg.jpg diff --git a/app/auto_channels.go b/app/auto_channels.go index 4f176cff55..f0e1fc66ed 100644 --- a/app/auto_channels.go +++ b/app/auto_channels.go @@ -32,7 +32,7 @@ func NewAutoChannelCreator(client *model.Client4, team *model.Team) *AutoChannel } } -func (cfg *AutoChannelCreator) createRandomChannel() (*model.Channel, bool) { +func (cfg *AutoChannelCreator) createRandomChannel() (*model.Channel, error) { var displayName string if cfg.Fuzzy { displayName = utils.FuzzName() @@ -50,24 +50,22 @@ func (cfg *AutoChannelCreator) createRandomChannel() (*model.Channel, bool) { println(cfg.client.GetTeamRoute(cfg.team.Id)) channel, resp := cfg.client.CreateChannel(channel) if resp.Error != nil { - println(resp.Error.Error()) - println(resp.Error.DetailedError) - return nil, false + return nil, resp.Error } - return channel, true + return channel, nil } -func (cfg *AutoChannelCreator) CreateTestChannels(num utils.Range) ([]*model.Channel, bool) { +func (cfg *AutoChannelCreator) CreateTestChannels(num utils.Range) ([]*model.Channel, error) { numChannels := utils.RandIntFromRange(num) channels := make([]*model.Channel, numChannels) for i := 0; i < numChannels; i++ { - var err bool + var err error channels[i], err = cfg.createRandomChannel() - if !err { - return channels, false + if err != nil { + return nil, err } } - return channels, true + return channels, nil } diff --git a/app/auto_environment.go b/app/auto_environment.go index f46c5e7846..a04c5a33f6 100644 --- a/app/auto_environment.go +++ b/app/auto_environment.go @@ -16,14 +16,14 @@ type TestEnvironment struct { Environments []TeamEnvironment } -func CreateTestEnvironmentWithTeams(a *App, client *model.Client4, rangeTeams utils.Range, rangeChannels utils.Range, rangeUsers utils.Range, rangePosts utils.Range, fuzzy bool) (TestEnvironment, bool) { +func CreateTestEnvironmentWithTeams(a *App, client *model.Client4, rangeTeams utils.Range, rangeChannels utils.Range, rangeUsers utils.Range, rangePosts utils.Range, fuzzy bool) (TestEnvironment, error) { rand.Seed(time.Now().UTC().UnixNano()) teamCreator := NewAutoTeamCreator(client) teamCreator.Fuzzy = fuzzy teams, err := teamCreator.CreateTestTeams(rangeTeams) - if !err { - return TestEnvironment{}, false + if err != nil { + return TestEnvironment{}, err } environment := TestEnvironment{teams, make([]TeamEnvironment, len(teams))} @@ -32,21 +32,21 @@ func CreateTestEnvironmentWithTeams(a *App, client *model.Client4, rangeTeams ut userCreator := NewAutoUserCreator(a, client, team) userCreator.Fuzzy = fuzzy randomUser, err := userCreator.createRandomUser() - if !err { - return TestEnvironment{}, false + if err != nil { + return TestEnvironment{}, err } client.LoginById(randomUser.Id, USER_PASSWORD) teamEnvironment, err := CreateTestEnvironmentInTeam(a, client, team, rangeChannels, rangeUsers, rangePosts, fuzzy) - if !err { - return TestEnvironment{}, false + if err != nil { + return TestEnvironment{}, err } environment.Environments[i] = teamEnvironment } - return environment, true + return environment, nil } -func CreateTestEnvironmentInTeam(a *App, client *model.Client4, team *model.Team, rangeChannels utils.Range, rangeUsers utils.Range, rangePosts utils.Range, fuzzy bool) (TeamEnvironment, bool) { +func CreateTestEnvironmentInTeam(a *App, client *model.Client4, team *model.Team, rangeChannels utils.Range, rangeUsers utils.Range, rangePosts utils.Range, fuzzy bool) (TeamEnvironment, error) { rand.Seed(time.Now().UTC().UnixNano()) // We need to create at least one user @@ -57,8 +57,8 @@ func CreateTestEnvironmentInTeam(a *App, client *model.Client4, team *model.Team userCreator := NewAutoUserCreator(a, client, team) userCreator.Fuzzy = fuzzy users, err := userCreator.CreateTestUsers(rangeUsers) - if !err { - return TeamEnvironment{}, false + if err != nil { + return TeamEnvironment{}, nil } usernames := make([]string, len(users)) for i, user := range users { @@ -68,32 +68,45 @@ func CreateTestEnvironmentInTeam(a *App, client *model.Client4, team *model.Team channelCreator := NewAutoChannelCreator(client, team) channelCreator.Fuzzy = fuzzy channels, err := channelCreator.CreateTestChannels(rangeChannels) + if err != nil { + return TeamEnvironment{}, nil + } // Have every user join every channel for _, user := range users { for _, channel := range channels { - client.LoginById(user.Id, USER_PASSWORD) - client.AddChannelMember(channel.Id, user.Id) - } - } + _, resp := client.LoginById(user.Id, USER_PASSWORD) + if resp.Error != nil { + return TeamEnvironment{}, resp.Error + } - if !err { - return TeamEnvironment{}, false + _, resp = client.AddChannelMember(channel.Id, user.Id) + if resp.Error != nil { + return TeamEnvironment{}, resp.Error + } + } } numPosts := utils.RandIntFromRange(rangePosts) numImages := utils.RandIntFromRange(rangePosts) / 4 for j := 0; j < numPosts; j++ { user := users[utils.RandIntFromRange(utils.Range{Begin: 0, End: len(users) - 1})] - client.LoginById(user.Id, USER_PASSWORD) + _, resp := client.LoginById(user.Id, USER_PASSWORD) + if resp.Error != nil { + return TeamEnvironment{}, resp.Error + } + for i, channel := range channels { postCreator := NewAutoPostCreator(client, channel.Id) postCreator.HasImage = i < numImages postCreator.Users = usernames postCreator.Fuzzy = fuzzy - postCreator.CreateRandomPost() + _, err := postCreator.CreateRandomPost() + if err != nil { + return TeamEnvironment{}, err + } } } - return TeamEnvironment{users, channels}, true + return TeamEnvironment{users, channels}, nil } diff --git a/app/auto_posts.go b/app/auto_posts.go index 15a6b76d3b..43eaa28845 100644 --- a/app/auto_posts.go +++ b/app/auto_posts.go @@ -41,41 +41,41 @@ func NewAutoPostCreator(client *model.Client4, channelid string) *AutoPostCreato } } -func (cfg *AutoPostCreator) UploadTestFile() ([]string, bool) { +func (cfg *AutoPostCreator) UploadTestFile() ([]string, error) { filename := cfg.ImageFilenames[utils.RandIntFromRange(utils.Range{Begin: 0, End: len(cfg.ImageFilenames) - 1})] - path, _ := fileutils.FindDir("web/static/images") + path, _ := fileutils.FindDir("tests") file, err := os.Open(filepath.Join(path, filename)) if err != nil { - return nil, false + return nil, err } defer file.Close() data := &bytes.Buffer{} _, err = io.Copy(data, file) if err != nil { - return nil, false + return nil, err } - resp, appErr := cfg.client.UploadFile(data.Bytes(), cfg.channelid, filename) - if appErr != nil { - return nil, false + fileResp, resp := cfg.client.UploadFile(data.Bytes(), cfg.channelid, filename) + if resp.Error != nil { + return nil, resp.Error } - return []string{resp.FileInfos[0].Id}, true + return []string{fileResp.FileInfos[0].Id}, nil } -func (cfg *AutoPostCreator) CreateRandomPost() (*model.Post, bool) { +func (cfg *AutoPostCreator) CreateRandomPost() (*model.Post, error) { return cfg.CreateRandomPostNested("", "") } -func (cfg *AutoPostCreator) CreateRandomPostNested(parentId, rootId string) (*model.Post, bool) { +func (cfg *AutoPostCreator) CreateRandomPostNested(parentId, rootId string) (*model.Post, error) { var fileIds []string if cfg.HasImage { - var err1 bool - fileIds, err1 = cfg.UploadTestFile() - if !err1 { - return nil, false + var err error + fileIds, err = cfg.UploadTestFile() + if err != nil { + return nil, err } } @@ -93,8 +93,8 @@ func (cfg *AutoPostCreator) CreateRandomPostNested(parentId, rootId string) (*mo Message: postText, FileIds: fileIds} rpost, resp := cfg.client.CreatePost(post) - if resp != nil && resp.Error != nil { - return nil, false + if resp.Error != nil { + return nil, resp.Error } - return rpost, true + return rpost, nil } diff --git a/app/auto_teams.go b/app/auto_teams.go index ce1a690a90..7f06e247b7 100644 --- a/app/auto_teams.go +++ b/app/auto_teams.go @@ -37,14 +37,14 @@ func NewAutoTeamCreator(client *model.Client4) *AutoTeamCreator { } } -func (cfg *AutoTeamCreator) createRandomTeam() (*model.Team, bool) { +func (cfg *AutoTeamCreator) createRandomTeam() (*model.Team, error) { var teamEmail string var teamDisplayName string var teamName string if cfg.Fuzzy { teamEmail = "success+" + model.NewId() + "simulator.amazonses.com" teamDisplayName = utils.FuzzName() - teamName = utils.FuzzName() + teamName = model.NewRandomTeamName() } else { teamEmail = "success+" + model.NewId() + "simulator.amazonses.com" teamDisplayName = utils.RandomName(cfg.NameLength, cfg.NameCharset) @@ -57,24 +57,24 @@ func (cfg *AutoTeamCreator) createRandomTeam() (*model.Team, bool) { Type: model.TEAM_OPEN, } - createdTeam, err := cfg.client.CreateTeam(team) - if err != nil { - return nil, false + createdTeam, resp := cfg.client.CreateTeam(team) + if resp.Error != nil { + return nil, resp.Error } - return createdTeam, true + return createdTeam, nil } -func (cfg *AutoTeamCreator) CreateTestTeams(num utils.Range) ([]*model.Team, bool) { +func (cfg *AutoTeamCreator) CreateTestTeams(num utils.Range) ([]*model.Team, error) { numTeams := utils.RandIntFromRange(num) teams := make([]*model.Team, numTeams) for i := 0; i < numTeams; i++ { - var err bool + var err error teams[i], err = cfg.createRandomTeam() - if !err { - return teams, false + if err != nil { + return nil, err } } - return teams, true + return teams, nil } diff --git a/app/auto_users.go b/app/auto_users.go index 76c33fcabd..e43a3c93ad 100644 --- a/app/auto_users.go +++ b/app/auto_users.go @@ -4,7 +4,6 @@ package app import ( - "github.com/mattermost/mattermost-server/v5/mlog" "github.com/mattermost/mattermost-server/v5/model" "github.com/mattermost/mattermost-server/v5/utils" ) @@ -36,29 +35,32 @@ func NewAutoUserCreator(a *App, client *model.Client4, team *model.Team) *AutoUs // Basic test team and user so you always know one func (a *App) CreateBasicUser(client *model.Client4) *model.AppError { found, _ := client.TeamExists(BTEST_TEAM_NAME, "") - if !found { - newteam := &model.Team{DisplayName: BTEST_TEAM_DISPLAY_NAME, Name: BTEST_TEAM_NAME, Email: BTEST_TEAM_EMAIL, Type: BTEST_TEAM_TYPE} - basicteam, resp := client.CreateTeam(newteam) - if resp.Error != nil { - return resp.Error - } - newuser := &model.User{Email: BTEST_USER_EMAIL, Nickname: BTEST_USER_NAME, Password: BTEST_USER_PASSWORD} - ruser, resp := client.CreateUser(newuser) - if resp.Error != nil { - return resp.Error - } - _, err := a.Srv().Store.User().VerifyEmail(ruser.Id, ruser.Email) - if err != nil { - return err - } - if _, err = a.Srv().Store.Team().SaveMember(&model.TeamMember{TeamId: basicteam.Id, UserId: ruser.Id}, *a.Config().TeamSettings.MaxUsersPerTeam); err != nil { - return err - } + if found { + return nil } + + newteam := &model.Team{DisplayName: BTEST_TEAM_DISPLAY_NAME, Name: BTEST_TEAM_NAME, Email: BTEST_TEAM_EMAIL, Type: BTEST_TEAM_TYPE} + basicteam, resp := client.CreateTeam(newteam) + if resp.Error != nil { + return resp.Error + } + newuser := &model.User{Email: BTEST_USER_EMAIL, Nickname: BTEST_USER_NAME, Password: BTEST_USER_PASSWORD} + ruser, resp := client.CreateUser(newuser) + if resp.Error != nil { + return resp.Error + } + _, err := a.Srv().Store.User().VerifyEmail(ruser.Id, ruser.Email) + if err != nil { + return err + } + if _, err = a.Srv().Store.Team().SaveMember(&model.TeamMember{TeamId: basicteam.Id, UserId: ruser.Id}, *a.Config().TeamSettings.MaxUsersPerTeam); err != nil { + return err + } + return nil } -func (cfg *AutoUserCreator) createRandomUser() (*model.User, bool) { +func (cfg *AutoUserCreator) createRandomUser() (*model.User, error) { var userEmail string var userName string if cfg.Fuzzy { @@ -76,36 +78,34 @@ func (cfg *AutoUserCreator) createRandomUser() (*model.User, bool) { ruser, resp := cfg.client.CreateUserWithInviteId(user, cfg.team.InviteId) if resp.Error != nil { - mlog.Error(resp.Error.Error()) - return nil, false + return nil, resp.Error } status := &model.Status{UserId: ruser.Id, Status: model.STATUS_ONLINE, Manual: false, LastActivityAt: model.GetMillis(), ActiveChannel: ""} if err := cfg.app.Srv().Store.Status().SaveOrUpdate(status); err != nil { - mlog.Error(err.Error()) - return nil, false + return nil, err } // We need to cheat to verify the user's email _, err := cfg.app.Srv().Store.User().VerifyEmail(ruser.Id, ruser.Email) if err != nil { - return nil, false + return nil, err } - return ruser, true + return ruser, nil } -func (cfg *AutoUserCreator) CreateTestUsers(num utils.Range) ([]*model.User, bool) { +func (cfg *AutoUserCreator) CreateTestUsers(num utils.Range) ([]*model.User, error) { numUsers := utils.RandIntFromRange(num) users := make([]*model.User, numUsers) for i := 0; i < numUsers; i++ { - var err bool + var err error users[i], err = cfg.createRandomUser() - if !err { - return users, false + if err != nil { + return nil, err } } - return users, true + return users, nil } diff --git a/app/command_loadtest.go b/app/command_loadtest.go index 10f10112bc..8bce16ee85 100644 --- a/app/command_loadtest.go +++ b/app/command_loadtest.go @@ -15,6 +15,7 @@ import ( "github.com/mattermost/mattermost-server/v5/mlog" "github.com/mattermost/mattermost-server/v5/model" "github.com/mattermost/mattermost-server/v5/utils" + "github.com/pkg/errors" ) var usage = `Mattermost testing commands to help configure the system @@ -105,9 +106,18 @@ func (me *LoadTestProvider) GetCommand(a *App, T goi18n.TranslateFunc) *model.Co } func (me *LoadTestProvider) DoCommand(a *App, args *model.CommandArgs, message string) *model.CommandResponse { + commandResponse, err := me.doCommand(a, args, message) + if err != nil { + mlog.Error("failed command /"+CMD_TEST, mlog.Err(err)) + } + + return commandResponse +} + +func (me *LoadTestProvider) doCommand(a *App, args *model.CommandArgs, message string) (*model.CommandResponse, error) { //This command is only available when EnableTesting is true if !*a.Config().ServiceSettings.EnableTesting { - return &model.CommandResponse{} + return &model.CommandResponse{}, nil } if strings.HasPrefix(message, "setup") { @@ -145,17 +155,19 @@ func (me *LoadTestProvider) DoCommand(a *App, args *model.CommandArgs, message s if strings.HasPrefix(message, "url") { return me.UrlCommand(a, args, message) } + if strings.HasPrefix(message, "json") { return me.JsonCommand(a, args, message) } - return me.HelpCommand(args, message) + + return me.HelpCommand(args, message), nil } func (me *LoadTestProvider) HelpCommand(args *model.CommandArgs, message string) *model.CommandResponse { return &model.CommandResponse{Text: usage, ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } -func (me *LoadTestProvider) SetupCommand(a *App, args *model.CommandArgs, message string) *model.CommandResponse { +func (me *LoadTestProvider) SetupCommand(a *App, args *model.CommandArgs, message string) (*model.CommandResponse, error) { tokens := strings.Fields(strings.TrimPrefix(message, "setup")) doTeams := contains(tokens, "teams") doFuzz := contains(tokens, "fuzz") @@ -194,12 +206,16 @@ func (me *LoadTestProvider) SetupCommand(a *App, args *model.CommandArgs, messag } } client := model.NewAPIv4Client(args.SiteURL) + client.SetToken(args.Session.Token) if doTeams { if err := a.CreateBasicUser(client); err != nil { - return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err + } + _, resp := client.Login(BTEST_USER_EMAIL, BTEST_USER_PASSWORD) + if resp.Error != nil { + return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, resp.Error } - client.Login(BTEST_USER_EMAIL, BTEST_USER_PASSWORD) environment, err := CreateTestEnvironmentWithTeams( a, client, @@ -208,22 +224,21 @@ func (me *LoadTestProvider) SetupCommand(a *App, args *model.CommandArgs, messag utils.Range{Begin: numUsers, End: numUsers}, utils.Range{Begin: numPosts, End: numPosts}, doFuzz) - if !err { - return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} - } else { - mlog.Info("Testing environment created") - for i := 0; i < len(environment.Teams); i++ { - mlog.Info("Team Created: " + environment.Teams[i].Name) - mlog.Info("\t User to login: " + environment.Environments[i].Users[0].Email + ", " + USER_PASSWORD) - } + if err != nil { + return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err + } + + mlog.Info("Testing environment created") + for i := 0; i < len(environment.Teams); i++ { + mlog.Info("Team Created: " + environment.Teams[i].Name) + mlog.Info("\t User to login: " + environment.Environments[i].Users[0].Email + ", " + USER_PASSWORD) } } else { team, err := a.Srv().Store.Team().Get(args.TeamId) if err != nil { - return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err } - client.SetToken(args.Session.Token) CreateTestEnvironmentInTeam( a, client, @@ -234,26 +249,28 @@ func (me *LoadTestProvider) SetupCommand(a *App, args *model.CommandArgs, messag doFuzz) } - return &model.CommandResponse{Text: "Created environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Created environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, nil } -func (me *LoadTestProvider) ActivateUserCommand(a *App, args *model.CommandArgs, message string) *model.CommandResponse { +func (me *LoadTestProvider) ActivateUserCommand(a *App, args *model.CommandArgs, message string) (*model.CommandResponse, error) { user_id := strings.TrimSpace(strings.TrimPrefix(message, "activate_user")) if err := a.UpdateUserActive(user_id, true); err != nil { - return &model.CommandResponse{Text: "Failed to activate user", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Failed to activate user", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err } - return &model.CommandResponse{Text: "Activated user", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + + return &model.CommandResponse{Text: "Activated user", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, nil } -func (me *LoadTestProvider) DeActivateUserCommand(a *App, args *model.CommandArgs, message string) *model.CommandResponse { +func (me *LoadTestProvider) DeActivateUserCommand(a *App, args *model.CommandArgs, message string) (*model.CommandResponse, error) { user_id := strings.TrimSpace(strings.TrimPrefix(message, "deactivate_user")) if err := a.UpdateUserActive(user_id, false); err != nil { - return &model.CommandResponse{Text: "Failed to deactivate user", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Failed to deactivate user", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err } - return &model.CommandResponse{Text: "DeActivated user", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + + return &model.CommandResponse{Text: "DeActivated user", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, nil } -func (me *LoadTestProvider) UsersCommand(a *App, args *model.CommandArgs, message string) *model.CommandResponse { +func (me *LoadTestProvider) UsersCommand(a *App, args *model.CommandArgs, message string) (*model.CommandResponse, error) { cmd := strings.TrimSpace(strings.TrimPrefix(message, "users")) doFuzz := false @@ -269,7 +286,7 @@ func (me *LoadTestProvider) UsersCommand(a *App, args *model.CommandArgs, messag team, err := a.Srv().Store.Team().Get(args.TeamId) if err != nil { - return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Failed to add users", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err } client := model.NewAPIv4Client(args.SiteURL) @@ -277,10 +294,10 @@ func (me *LoadTestProvider) UsersCommand(a *App, args *model.CommandArgs, messag userCreator.Fuzzy = doFuzz userCreator.CreateTestUsers(usersr) - return &model.CommandResponse{Text: "Added users", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Added users", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, nil } -func (me *LoadTestProvider) ChannelsCommand(a *App, args *model.CommandArgs, message string) *model.CommandResponse { +func (me *LoadTestProvider) ChannelsCommand(a *App, args *model.CommandArgs, message string) (*model.CommandResponse, error) { cmd := strings.TrimSpace(strings.TrimPrefix(message, "channels")) doFuzz := false @@ -296,7 +313,7 @@ func (me *LoadTestProvider) ChannelsCommand(a *App, args *model.CommandArgs, mes team, err := a.Srv().Store.Team().Get(args.TeamId) if err != nil { - return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Failed to add channels", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err } client := model.NewAPIv4Client(args.SiteURL) @@ -305,10 +322,10 @@ func (me *LoadTestProvider) ChannelsCommand(a *App, args *model.CommandArgs, mes channelCreator.Fuzzy = doFuzz channelCreator.CreateTestChannels(channelsr) - return &model.CommandResponse{Text: "Added channels", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Added channels", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, nil } -func (me *LoadTestProvider) ThreadedPostCommand(a *App, args *model.CommandArgs, message string) *model.CommandResponse { +func (me *LoadTestProvider) ThreadedPostCommand(a *App, args *model.CommandArgs, message string) (*model.CommandResponse, error) { var usernames []string options := &model.UserGetOptions{InTeamId: args.TeamId, Page: 0, PerPage: 1000} if profileUsers, err := a.Srv().Store.User().GetProfiles(options); err == nil { @@ -325,18 +342,18 @@ func (me *LoadTestProvider) ThreadedPostCommand(a *App, args *model.CommandArgs, testPoster := NewAutoPostCreator(client, args.ChannelId) testPoster.Fuzzy = true testPoster.Users = usernames - rpost, ok := testPoster.CreateRandomPost() - if !ok { - return &model.CommandResponse{Text: "Cannot create a post", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + rpost, err := testPoster.CreateRandomPost() + if err != nil { + return &model.CommandResponse{Text: "Failed to create a post", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err } for i := 0; i < 1000; i++ { testPoster.CreateRandomPostNested(rpost.Id, rpost.Id) } - return &model.CommandResponse{Text: "Added threaded post", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Added threaded post", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, nil } -func (me *LoadTestProvider) PostsCommand(a *App, args *model.CommandArgs, message string) *model.CommandResponse { +func (me *LoadTestProvider) PostsCommand(a *App, args *model.CommandArgs, message string) (*model.CommandResponse, error) { cmd := strings.TrimSpace(strings.TrimPrefix(message, "posts")) doFuzz := false @@ -379,10 +396,14 @@ func (me *LoadTestProvider) PostsCommand(a *App, args *model.CommandArgs, messag numPosts := utils.RandIntFromRange(postsr) for i := 0; i < numPosts; i++ { testPoster.HasImage = (i < numImages) - testPoster.CreateRandomPost() + _, err := testPoster.CreateRandomPost() + if err != nil { + return &model.CommandResponse{Text: "Failed to add posts", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err + } + } - return &model.CommandResponse{Text: "Added posts", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Added posts", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, nil } func getMatch(re *regexp.Regexp, text string) string { @@ -393,35 +414,35 @@ func getMatch(re *regexp.Regexp, text string) string { return "" } -func (me *LoadTestProvider) PostCommand(a *App, args *model.CommandArgs, message string) *model.CommandResponse { +func (me *LoadTestProvider) PostCommand(a *App, args *model.CommandArgs, message string) (*model.CommandResponse, error) { textMessage := getMatch(messageRE, message) if textMessage == "" { - return &model.CommandResponse{Text: "No message to post", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "No message to post", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, nil } teamName := getMatch(teamRE, message) team, err := a.GetTeamByName(teamName) if err != nil { - return &model.CommandResponse{Text: "Failed to get a team", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Failed to get a team", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err } channelName := getMatch(channelRE, message) channel, err := a.GetChannelByName(channelName, team.Id, true) if err != nil { - return &model.CommandResponse{Text: "Failed to get a channel", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Failed to get a channel", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err } passwd := getMatch(passwdRE, message) username := getMatch(userRE, message) user, err := a.GetUserByUsername(username) if err != nil { - return &model.CommandResponse{Text: "Failed to get a user", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Failed to get a user", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err } client := model.NewAPIv4Client(args.SiteURL) _, resp := client.LoginById(user.Id, passwd) - if resp != nil && resp.Error != nil { - return &model.CommandResponse{Text: "Failed to login a user", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + if resp.Error != nil { + return &model.CommandResponse{Text: "Failed to login a user", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, resp.Error } post := &model.Post{ @@ -429,17 +450,17 @@ func (me *LoadTestProvider) PostCommand(a *App, args *model.CommandArgs, message Message: textMessage, } _, resp = client.CreatePost(post) - if resp != nil && resp.Error != nil { - return &model.CommandResponse{Text: "Failed to create a post", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + if resp.Error != nil { + return &model.CommandResponse{Text: "Failed to create a post", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, resp.Error } - return &model.CommandResponse{Text: "Added a post to " + channel.DisplayName, ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Added a post to " + channel.DisplayName, ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, nil } -func (me *LoadTestProvider) UrlCommand(a *App, args *model.CommandArgs, message string) *model.CommandResponse { +func (me *LoadTestProvider) UrlCommand(a *App, args *model.CommandArgs, message string) (*model.CommandResponse, error) { url := strings.TrimSpace(strings.TrimPrefix(message, "url")) if len(url) == 0 { - return &model.CommandResponse{Text: "Command must contain a url", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Command must contain a url", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, nil } // provide a shortcut to easily access tests stored in doc/developer/tests @@ -453,9 +474,9 @@ func (me *LoadTestProvider) UrlCommand(a *App, args *model.CommandArgs, message var contents io.ReadCloser if r, err := http.Get(url); err != nil { - return &model.CommandResponse{Text: "Unable to get file", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Unable to get file", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err } else if r.StatusCode > 400 { - return &model.CommandResponse{Text: "Unable to get file", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Unable to get file", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, errors.Errorf("unexpected status code %d", r.StatusCode) } else { contents = r.Body } @@ -466,7 +487,7 @@ func (me *LoadTestProvider) UrlCommand(a *App, args *model.CommandArgs, message for { length, err := contents.Read(bytes) if err != nil && err != io.EOF { - return &model.CommandResponse{Text: "Encountered error reading file", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Encountered error reading file", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err } if length == 0 { @@ -479,17 +500,17 @@ func (me *LoadTestProvider) UrlCommand(a *App, args *model.CommandArgs, message post.UserId = args.UserId if _, err := a.CreatePostMissingChannel(post, false); err != nil { - return &model.CommandResponse{Text: "Unable to create post", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Unable to create post", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err } } - return &model.CommandResponse{Text: "Loaded data", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Loaded data", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, nil } -func (me *LoadTestProvider) JsonCommand(a *App, args *model.CommandArgs, message string) *model.CommandResponse { +func (me *LoadTestProvider) JsonCommand(a *App, args *model.CommandArgs, message string) (*model.CommandResponse, error) { url := strings.TrimSpace(strings.TrimPrefix(message, "json")) if len(url) == 0 { - return &model.CommandResponse{Text: "Command must contain a url", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Command must contain a url", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, nil } // provide a shortcut to easily access tests stored in doc/developer/tests @@ -503,9 +524,9 @@ func (me *LoadTestProvider) JsonCommand(a *App, args *model.CommandArgs, message var contents io.ReadCloser if r, err := http.Get(url); err != nil { - return &model.CommandResponse{Text: "Unable to get file", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Unable to get file", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err } else if r.StatusCode > 400 { - return &model.CommandResponse{Text: "Unable to get file", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Unable to get file", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, errors.Errorf("unexpected status code %d", r.StatusCode) } else { contents = r.Body } @@ -518,9 +539,10 @@ func (me *LoadTestProvider) JsonCommand(a *App, args *model.CommandArgs, message } if _, err := a.CreatePostMissingChannel(post, false); err != nil { - return &model.CommandResponse{Text: "Unable to create post", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + return &model.CommandResponse{Text: "Unable to create post", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, err } - return &model.CommandResponse{Text: "Loaded data", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + + return &model.CommandResponse{Text: "Loaded data", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}, nil } func parseRange(command string, cmd string) (utils.Range, bool) { diff --git a/tests/testjpg.jpg b/tests/testjpg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a51e9f4d08776224757fd9e5d4e58f03b9711bd2 GIT binary patch literal 40600 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 sGDADDYL{D;