github.com/psyb0t/mattermost-server@v4.6.1-0.20180125161845-5503a1351abf+incompatible/api/apitestlib.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package api
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  	"io/ioutil"
    10  	"net"
    11  	"os"
    12  	"strings"
    13  	"time"
    14  
    15  	"github.com/mattermost/mattermost-server/api4"
    16  	"github.com/mattermost/mattermost-server/app"
    17  	"github.com/mattermost/mattermost-server/model"
    18  	"github.com/mattermost/mattermost-server/store"
    19  	"github.com/mattermost/mattermost-server/store/sqlstore"
    20  	"github.com/mattermost/mattermost-server/store/storetest"
    21  	"github.com/mattermost/mattermost-server/utils"
    22  	"github.com/mattermost/mattermost-server/wsapi"
    23  
    24  	l4g "github.com/alecthomas/log4go"
    25  )
    26  
    27  type TestHelper struct {
    28  	App            *app.App
    29  	tempConfigPath string
    30  
    31  	BasicClient  *model.Client
    32  	BasicTeam    *model.Team
    33  	BasicUser    *model.User
    34  	BasicUser2   *model.User
    35  	BasicChannel *model.Channel
    36  	BasicPost    *model.Post
    37  	PinnedPost   *model.Post
    38  
    39  	SystemAdminClient  *model.Client
    40  	SystemAdminTeam    *model.Team
    41  	SystemAdminUser    *model.User
    42  	SystemAdminChannel *model.Channel
    43  }
    44  
    45  type persistentTestStore struct {
    46  	store.Store
    47  }
    48  
    49  func (*persistentTestStore) Close() {}
    50  
    51  var testStoreContainer *storetest.RunningContainer
    52  var testStore *persistentTestStore
    53  
    54  // UseTestStore sets the container and corresponding settings to use for tests. Once the tests are
    55  // complete (e.g. at the end of your TestMain implementation), you should call StopTestStore.
    56  func UseTestStore(container *storetest.RunningContainer, settings *model.SqlSettings) {
    57  	testStoreContainer = container
    58  	testStore = &persistentTestStore{store.NewLayeredStore(sqlstore.NewSqlSupplier(*settings, nil), nil, nil)}
    59  }
    60  
    61  func StopTestStore() {
    62  	if testStoreContainer != nil {
    63  		testStoreContainer.Stop()
    64  		testStoreContainer = nil
    65  	}
    66  }
    67  
    68  func setupTestHelper(enterprise bool) *TestHelper {
    69  	permConfig, err := os.Open(utils.FindConfigFile("config.json"))
    70  	if err != nil {
    71  		panic(err)
    72  	}
    73  	defer permConfig.Close()
    74  	tempConfig, err := ioutil.TempFile("", "")
    75  	if err != nil {
    76  		panic(err)
    77  	}
    78  	_, err = io.Copy(tempConfig, permConfig)
    79  	tempConfig.Close()
    80  	if err != nil {
    81  		panic(err)
    82  	}
    83  
    84  	options := []app.Option{app.ConfigFile(tempConfig.Name()), app.DisableConfigWatch}
    85  	if testStore != nil {
    86  		options = append(options, app.StoreOverride(testStore))
    87  	}
    88  
    89  	a, err := app.New(options...)
    90  	if err != nil {
    91  		panic(err)
    92  	}
    93  
    94  	th := &TestHelper{
    95  		App:            a,
    96  		tempConfigPath: tempConfig.Name(),
    97  	}
    98  
    99  	th.App.UpdateConfig(func(cfg *model.Config) {
   100  		*cfg.TeamSettings.MaxUsersPerTeam = 50
   101  		*cfg.RateLimitSettings.Enable = false
   102  		cfg.EmailSettings.SendEmailNotifications = true
   103  	})
   104  	prevListenAddress := *th.App.Config().ServiceSettings.ListenAddress
   105  	if testStore != nil {
   106  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = ":0" })
   107  	}
   108  	th.App.StartServer()
   109  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = prevListenAddress })
   110  	api4.Init(th.App, th.App.Srv.Router, false)
   111  	Init(th.App, th.App.Srv.Router)
   112  	wsapi.Init(th.App, th.App.Srv.WebSocketRouter)
   113  	th.App.Srv.Store.MarkSystemRanUnitTests()
   114  
   115  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = true })
   116  
   117  	utils.SetIsLicensed(enterprise)
   118  	if enterprise {
   119  		utils.License().Features.SetDefaults()
   120  	}
   121  
   122  	return th
   123  }
   124  
   125  func SetupEnterprise() *TestHelper {
   126  	return setupTestHelper(true)
   127  }
   128  
   129  func Setup() *TestHelper {
   130  	return setupTestHelper(false)
   131  }
   132  
   133  func (me *TestHelper) InitBasic() *TestHelper {
   134  	me.waitForConnectivity()
   135  
   136  	me.BasicClient = me.CreateClient()
   137  	me.BasicUser = me.CreateUser(me.BasicClient)
   138  	me.App.UpdateUserRoles(me.BasicUser.Id, model.SYSTEM_USER_ROLE_ID, false)
   139  	me.LoginBasic()
   140  	me.BasicTeam = me.CreateTeam(me.BasicClient)
   141  	me.LinkUserToTeam(me.BasicUser, me.BasicTeam)
   142  	me.UpdateUserToNonTeamAdmin(me.BasicUser, me.BasicTeam)
   143  	me.BasicUser2 = me.CreateUser(me.BasicClient)
   144  	me.LinkUserToTeam(me.BasicUser2, me.BasicTeam)
   145  	me.BasicClient.SetTeamId(me.BasicTeam.Id)
   146  	me.BasicChannel = me.CreateChannel(me.BasicClient, me.BasicTeam)
   147  	me.BasicPost = me.CreatePost(me.BasicClient, me.BasicChannel)
   148  
   149  	pinnedPostChannel := me.CreateChannel(me.BasicClient, me.BasicTeam)
   150  	me.PinnedPost = me.CreatePinnedPost(me.BasicClient, pinnedPostChannel)
   151  
   152  	return me
   153  }
   154  
   155  func (me *TestHelper) InitSystemAdmin() *TestHelper {
   156  	me.waitForConnectivity()
   157  
   158  	me.SystemAdminClient = me.CreateClient()
   159  	me.SystemAdminUser = me.CreateUser(me.SystemAdminClient)
   160  	me.SystemAdminUser.Password = "Password1"
   161  	me.LoginSystemAdmin()
   162  	me.SystemAdminTeam = me.CreateTeam(me.SystemAdminClient)
   163  	me.LinkUserToTeam(me.SystemAdminUser, me.SystemAdminTeam)
   164  	me.SystemAdminClient.SetTeamId(me.SystemAdminTeam.Id)
   165  	me.App.UpdateUserRoles(me.SystemAdminUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_ADMIN_ROLE_ID, false)
   166  	me.SystemAdminChannel = me.CreateChannel(me.SystemAdminClient, me.SystemAdminTeam)
   167  
   168  	return me
   169  }
   170  
   171  func (me *TestHelper) waitForConnectivity() {
   172  	for i := 0; i < 1000; i++ {
   173  		conn, err := net.Dial("tcp", fmt.Sprintf("localhost:%v", me.App.Srv.ListenAddr.Port))
   174  		if err == nil {
   175  			conn.Close()
   176  			return
   177  		}
   178  		time.Sleep(time.Millisecond * 20)
   179  	}
   180  	panic("unable to connect")
   181  }
   182  
   183  func (me *TestHelper) CreateClient() *model.Client {
   184  	return model.NewClient(fmt.Sprintf("http://localhost:%v", me.App.Srv.ListenAddr.Port))
   185  }
   186  
   187  func (me *TestHelper) CreateWebSocketClient() (*model.WebSocketClient, *model.AppError) {
   188  	return model.NewWebSocketClient(fmt.Sprintf("ws://localhost:%v", me.App.Srv.ListenAddr.Port), me.BasicClient.AuthToken)
   189  }
   190  
   191  func (me *TestHelper) CreateTeam(client *model.Client) *model.Team {
   192  	id := model.NewId()
   193  	team := &model.Team{
   194  		DisplayName: "dn_" + id,
   195  		Name:        GenerateTestTeamName(),
   196  		Email:       me.GenerateTestEmail(),
   197  		Type:        model.TEAM_OPEN,
   198  	}
   199  
   200  	utils.DisableDebugLogForTest()
   201  	r := client.Must(client.CreateTeam(team)).Data.(*model.Team)
   202  	utils.EnableDebugLogForTest()
   203  	return r
   204  }
   205  
   206  func (me *TestHelper) CreateUser(client *model.Client) *model.User {
   207  	id := model.NewId()
   208  
   209  	user := &model.User{
   210  		Email:    me.GenerateTestEmail(),
   211  		Username: "un_" + id,
   212  		Nickname: "nn_" + id,
   213  		Password: "Password1",
   214  	}
   215  
   216  	utils.DisableDebugLogForTest()
   217  	ruser := client.Must(client.CreateUser(user, "")).Data.(*model.User)
   218  	ruser.Password = "Password1"
   219  	store.Must(me.App.Srv.Store.User().VerifyEmail(ruser.Id))
   220  	utils.EnableDebugLogForTest()
   221  	return ruser
   222  }
   223  
   224  func (me *TestHelper) LinkUserToTeam(user *model.User, team *model.Team) {
   225  	utils.DisableDebugLogForTest()
   226  
   227  	err := me.App.JoinUserToTeam(team, user, "")
   228  	if err != nil {
   229  		l4g.Error(err.Error())
   230  		l4g.Close()
   231  		time.Sleep(time.Second)
   232  		panic(err)
   233  	}
   234  
   235  	utils.EnableDebugLogForTest()
   236  }
   237  
   238  func (me *TestHelper) UpdateUserToTeamAdmin(user *model.User, team *model.Team) {
   239  	utils.DisableDebugLogForTest()
   240  
   241  	tm := &model.TeamMember{TeamId: team.Id, UserId: user.Id, Roles: model.TEAM_USER_ROLE_ID + " " + model.TEAM_ADMIN_ROLE_ID}
   242  	if tmr := <-me.App.Srv.Store.Team().UpdateMember(tm); tmr.Err != nil {
   243  		utils.EnableDebugLogForTest()
   244  		l4g.Error(tmr.Err.Error())
   245  		l4g.Close()
   246  		time.Sleep(time.Second)
   247  		panic(tmr.Err)
   248  	}
   249  	utils.EnableDebugLogForTest()
   250  }
   251  
   252  func (me *TestHelper) UpdateUserToNonTeamAdmin(user *model.User, team *model.Team) {
   253  	utils.DisableDebugLogForTest()
   254  
   255  	tm := &model.TeamMember{TeamId: team.Id, UserId: user.Id, Roles: model.TEAM_USER_ROLE_ID}
   256  	if tmr := <-me.App.Srv.Store.Team().UpdateMember(tm); tmr.Err != nil {
   257  		utils.EnableDebugLogForTest()
   258  		l4g.Error(tmr.Err.Error())
   259  		l4g.Close()
   260  		time.Sleep(time.Second)
   261  		panic(tmr.Err)
   262  	}
   263  	utils.EnableDebugLogForTest()
   264  }
   265  
   266  func (me *TestHelper) MakeUserChannelAdmin(user *model.User, channel *model.Channel) {
   267  	utils.DisableDebugLogForTest()
   268  
   269  	if cmr := <-me.App.Srv.Store.Channel().GetMember(channel.Id, user.Id); cmr.Err == nil {
   270  		cm := cmr.Data.(*model.ChannelMember)
   271  		cm.Roles = "channel_admin channel_user"
   272  		if sr := <-me.App.Srv.Store.Channel().UpdateMember(cm); sr.Err != nil {
   273  			utils.EnableDebugLogForTest()
   274  			panic(sr.Err)
   275  		}
   276  	} else {
   277  		utils.EnableDebugLogForTest()
   278  		panic(cmr.Err)
   279  	}
   280  
   281  	utils.EnableDebugLogForTest()
   282  }
   283  
   284  func (me *TestHelper) MakeUserChannelUser(user *model.User, channel *model.Channel) {
   285  	utils.DisableDebugLogForTest()
   286  
   287  	if cmr := <-me.App.Srv.Store.Channel().GetMember(channel.Id, user.Id); cmr.Err == nil {
   288  		cm := cmr.Data.(*model.ChannelMember)
   289  		cm.Roles = "channel_user"
   290  		if sr := <-me.App.Srv.Store.Channel().UpdateMember(cm); sr.Err != nil {
   291  			utils.EnableDebugLogForTest()
   292  			panic(sr.Err)
   293  		}
   294  	} else {
   295  		utils.EnableDebugLogForTest()
   296  		panic(cmr.Err)
   297  	}
   298  
   299  	utils.EnableDebugLogForTest()
   300  }
   301  
   302  func (me *TestHelper) CreateChannel(client *model.Client, team *model.Team) *model.Channel {
   303  	return me.createChannel(client, team, model.CHANNEL_OPEN)
   304  }
   305  
   306  func (me *TestHelper) CreatePrivateChannel(client *model.Client, team *model.Team) *model.Channel {
   307  	return me.createChannel(client, team, model.CHANNEL_PRIVATE)
   308  }
   309  
   310  func (me *TestHelper) createChannel(client *model.Client, team *model.Team, channelType string) *model.Channel {
   311  	id := model.NewId()
   312  
   313  	channel := &model.Channel{
   314  		DisplayName: "dn_" + id,
   315  		Name:        "name_" + id,
   316  		Type:        channelType,
   317  		TeamId:      team.Id,
   318  	}
   319  
   320  	utils.DisableDebugLogForTest()
   321  	r := client.Must(client.CreateChannel(channel)).Data.(*model.Channel)
   322  	utils.EnableDebugLogForTest()
   323  	return r
   324  }
   325  
   326  func (me *TestHelper) CreatePost(client *model.Client, channel *model.Channel) *model.Post {
   327  	id := model.NewId()
   328  
   329  	post := &model.Post{
   330  		ChannelId: channel.Id,
   331  		Message:   "message_" + id,
   332  	}
   333  
   334  	utils.DisableDebugLogForTest()
   335  	r := client.Must(client.CreatePost(post)).Data.(*model.Post)
   336  	utils.EnableDebugLogForTest()
   337  	return r
   338  }
   339  
   340  func (me *TestHelper) CreatePinnedPost(client *model.Client, channel *model.Channel) *model.Post {
   341  	id := model.NewId()
   342  
   343  	post := &model.Post{
   344  		ChannelId: channel.Id,
   345  		Message:   "message_" + id,
   346  		IsPinned:  true,
   347  	}
   348  
   349  	utils.DisableDebugLogForTest()
   350  	r := client.Must(client.CreatePost(post)).Data.(*model.Post)
   351  	utils.EnableDebugLogForTest()
   352  	return r
   353  }
   354  
   355  func (me *TestHelper) LoginBasic() {
   356  	utils.DisableDebugLogForTest()
   357  	me.BasicClient.Must(me.BasicClient.Login(me.BasicUser.Email, me.BasicUser.Password))
   358  	utils.EnableDebugLogForTest()
   359  }
   360  
   361  func (me *TestHelper) LoginBasic2() {
   362  	utils.DisableDebugLogForTest()
   363  	me.BasicClient.Must(me.BasicClient.Login(me.BasicUser2.Email, me.BasicUser2.Password))
   364  	utils.EnableDebugLogForTest()
   365  }
   366  
   367  func (me *TestHelper) LoginSystemAdmin() {
   368  	utils.DisableDebugLogForTest()
   369  	me.SystemAdminClient.Must(me.SystemAdminClient.Login(me.SystemAdminUser.Email, me.SystemAdminUser.Password))
   370  	utils.EnableDebugLogForTest()
   371  }
   372  
   373  func (me *TestHelper) GenerateTestEmail() string {
   374  	if me.App.Config().EmailSettings.SMTPServer != "dockerhost" && os.Getenv("CI_INBUCKET_PORT") == "" {
   375  		return strings.ToLower("success+" + model.NewId() + "@simulator.amazonses.com")
   376  	}
   377  	return strings.ToLower(model.NewId() + "@dockerhost")
   378  }
   379  
   380  func GenerateTestTeamName() string {
   381  	return "faketeam" + model.NewRandomString(6)
   382  }
   383  
   384  func (me *TestHelper) TearDown() {
   385  	me.App.Shutdown()
   386  	os.Remove(me.tempConfigPath)
   387  	if err := recover(); err != nil {
   388  		StopTestStore()
   389  		panic(err)
   390  	}
   391  }