github.com/keys-pub/mattermost-server@v4.10.10+incompatible/app/apptestlib.go (about) 1 // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package app 5 6 import ( 7 "encoding/json" 8 "io" 9 "io/ioutil" 10 "os" 11 "path/filepath" 12 "time" 13 14 "github.com/mattermost/mattermost-server/einterfaces" 15 "github.com/mattermost/mattermost-server/mlog" 16 "github.com/mattermost/mattermost-server/model" 17 "github.com/mattermost/mattermost-server/plugin" 18 "github.com/mattermost/mattermost-server/plugin/pluginenv" 19 "github.com/mattermost/mattermost-server/store" 20 "github.com/mattermost/mattermost-server/store/sqlstore" 21 "github.com/mattermost/mattermost-server/store/storetest" 22 "github.com/mattermost/mattermost-server/utils" 23 ) 24 25 type TestHelper struct { 26 App *App 27 BasicTeam *model.Team 28 BasicUser *model.User 29 BasicUser2 *model.User 30 BasicChannel *model.Channel 31 BasicPost *model.Post 32 33 SystemAdminUser *model.User 34 35 tempConfigPath string 36 tempWorkspace string 37 pluginHooks map[string]plugin.Hooks 38 } 39 40 type persistentTestStore struct { 41 store.Store 42 } 43 44 func (*persistentTestStore) Close() {} 45 46 var testStoreContainer *storetest.RunningContainer 47 var testStore *persistentTestStore 48 var testStoreSqlSupplier *sqlstore.SqlSupplier 49 var testClusterInterface *FakeClusterInterface 50 51 // UseTestStore sets the container and corresponding settings to use for tests. Once the tests are 52 // complete (e.g. at the end of your TestMain implementation), you should call StopTestStore. 53 func UseTestStore(container *storetest.RunningContainer, settings *model.SqlSettings) { 54 testClusterInterface = &FakeClusterInterface{} 55 testStoreContainer = container 56 testStoreSqlSupplier = sqlstore.NewSqlSupplier(*settings, nil) 57 testStore = &persistentTestStore{store.NewLayeredStore(testStoreSqlSupplier, nil, testClusterInterface)} 58 } 59 60 func StopTestStore() { 61 if testStoreContainer != nil { 62 testStoreContainer.Stop() 63 testStoreContainer = nil 64 } 65 } 66 67 func setupTestHelper(enterprise bool) *TestHelper { 68 permConfig, err := os.Open(utils.FindConfigFile("config.json")) 69 if err != nil { 70 panic(err) 71 } 72 defer permConfig.Close() 73 tempConfig, err := ioutil.TempFile("", "") 74 if err != nil { 75 panic(err) 76 } 77 _, err = io.Copy(tempConfig, permConfig) 78 tempConfig.Close() 79 if err != nil { 80 panic(err) 81 } 82 83 options := []Option{ConfigFile(tempConfig.Name()), DisableConfigWatch} 84 if testStore != nil { 85 options = append(options, StoreOverride(testStore)) 86 } 87 88 a, err := New(options...) 89 if err != nil { 90 panic(err) 91 } 92 93 th := &TestHelper{ 94 App: a, 95 pluginHooks: make(map[string]plugin.Hooks), 96 tempConfigPath: tempConfig.Name(), 97 } 98 99 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.MaxUsersPerTeam = 50 }) 100 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.RateLimitSettings.Enable = false }) 101 prevListenAddress := *th.App.Config().ServiceSettings.ListenAddress 102 if testStore != nil { 103 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = ":0" }) 104 } 105 serverErr := th.App.StartServer() 106 if serverErr != nil { 107 panic(serverErr) 108 } 109 110 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = prevListenAddress }) 111 112 th.App.DoAdvancedPermissionsMigration() 113 th.App.DoPermissionsMigrations() 114 115 th.App.Srv.Store.MarkSystemRanUnitTests() 116 117 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = true }) 118 119 if enterprise { 120 th.App.SetLicense(model.NewTestLicense()) 121 } else { 122 th.App.SetLicense(nil) 123 } 124 125 return th 126 } 127 128 func SetupEnterprise() *TestHelper { 129 return setupTestHelper(true) 130 } 131 132 func Setup() *TestHelper { 133 return setupTestHelper(false) 134 } 135 136 func (me *TestHelper) InitBasic() *TestHelper { 137 me.BasicTeam = me.CreateTeam() 138 me.BasicUser = me.CreateUser() 139 me.LinkUserToTeam(me.BasicUser, me.BasicTeam) 140 me.BasicUser2 = me.CreateUser() 141 me.LinkUserToTeam(me.BasicUser2, me.BasicTeam) 142 me.BasicChannel = me.CreateChannel(me.BasicTeam) 143 me.BasicPost = me.CreatePost(me.BasicChannel) 144 145 return me 146 } 147 148 func (me *TestHelper) InitSystemAdmin() *TestHelper { 149 me.SystemAdminUser = me.CreateUser() 150 me.App.UpdateUserRoles(me.SystemAdminUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_ADMIN_ROLE_ID, false) 151 me.SystemAdminUser, _ = me.App.GetUser(me.SystemAdminUser.Id) 152 153 return me 154 } 155 156 func (me *TestHelper) MakeEmail() string { 157 return "success_" + model.NewId() + "@simulator.amazonses.com" 158 } 159 160 func (me *TestHelper) CreateTeam() *model.Team { 161 id := model.NewId() 162 team := &model.Team{ 163 DisplayName: "dn_" + id, 164 Name: "name" + id, 165 Email: "success+" + id + "@simulator.amazonses.com", 166 Type: model.TEAM_OPEN, 167 } 168 169 utils.DisableDebugLogForTest() 170 var err *model.AppError 171 if team, err = me.App.CreateTeam(team); err != nil { 172 mlog.Error(err.Error()) 173 174 time.Sleep(time.Second) 175 panic(err) 176 } 177 utils.EnableDebugLogForTest() 178 return team 179 } 180 181 func (me *TestHelper) CreateUser() *model.User { 182 id := model.NewId() 183 184 user := &model.User{ 185 Email: "success+" + id + "@simulator.amazonses.com", 186 Username: "un_" + id, 187 Nickname: "nn_" + id, 188 Password: "Password1", 189 EmailVerified: true, 190 } 191 192 utils.DisableDebugLogForTest() 193 var err *model.AppError 194 if user, err = me.App.CreateUser(user); err != nil { 195 mlog.Error(err.Error()) 196 197 time.Sleep(time.Second) 198 panic(err) 199 } 200 utils.EnableDebugLogForTest() 201 return user 202 } 203 204 func (me *TestHelper) CreateChannel(team *model.Team) *model.Channel { 205 return me.createChannel(team, model.CHANNEL_OPEN) 206 } 207 208 func (me *TestHelper) createChannel(team *model.Team, channelType string) *model.Channel { 209 id := model.NewId() 210 211 channel := &model.Channel{ 212 DisplayName: "dn_" + id, 213 Name: "name_" + id, 214 Type: channelType, 215 TeamId: team.Id, 216 CreatorId: me.BasicUser.Id, 217 } 218 219 utils.DisableDebugLogForTest() 220 var err *model.AppError 221 if channel, err = me.App.CreateChannel(channel, true); err != nil { 222 mlog.Error(err.Error()) 223 224 time.Sleep(time.Second) 225 panic(err) 226 } 227 utils.EnableDebugLogForTest() 228 return channel 229 } 230 231 func (me *TestHelper) createChannelWithAnotherUser(team *model.Team, channelType, userId string) *model.Channel { 232 id := model.NewId() 233 234 channel := &model.Channel{ 235 DisplayName: "dn_" + id, 236 Name: "name_" + id, 237 Type: channelType, 238 TeamId: team.Id, 239 CreatorId: userId, 240 } 241 242 utils.DisableDebugLogForTest() 243 var err *model.AppError 244 if channel, err = me.App.CreateChannel(channel, true); err != nil { 245 mlog.Error(err.Error()) 246 247 time.Sleep(time.Second) 248 panic(err) 249 } 250 utils.EnableDebugLogForTest() 251 return channel 252 } 253 254 func (me *TestHelper) CreateDmChannel(user *model.User) *model.Channel { 255 utils.DisableDebugLogForTest() 256 var err *model.AppError 257 var channel *model.Channel 258 if channel, err = me.App.CreateDirectChannel(me.BasicUser.Id, user.Id); err != nil { 259 mlog.Error(err.Error()) 260 261 time.Sleep(time.Second) 262 panic(err) 263 } 264 utils.EnableDebugLogForTest() 265 return channel 266 } 267 268 func (me *TestHelper) CreatePost(channel *model.Channel) *model.Post { 269 id := model.NewId() 270 271 post := &model.Post{ 272 UserId: me.BasicUser.Id, 273 ChannelId: channel.Id, 274 Message: "message_" + id, 275 CreateAt: model.GetMillis() - 10000, 276 } 277 278 utils.DisableDebugLogForTest() 279 var err *model.AppError 280 if post, err = me.App.CreatePost(post, channel, false); err != nil { 281 mlog.Error(err.Error()) 282 283 time.Sleep(time.Second) 284 panic(err) 285 } 286 utils.EnableDebugLogForTest() 287 return post 288 } 289 290 func (me *TestHelper) LinkUserToTeam(user *model.User, team *model.Team) { 291 utils.DisableDebugLogForTest() 292 293 err := me.App.JoinUserToTeam(team, user, "") 294 if err != nil { 295 mlog.Error(err.Error()) 296 297 time.Sleep(time.Second) 298 panic(err) 299 } 300 301 utils.EnableDebugLogForTest() 302 } 303 304 func (me *TestHelper) AddUserToChannel(user *model.User, channel *model.Channel) *model.ChannelMember { 305 utils.DisableDebugLogForTest() 306 307 member, err := me.App.AddUserToChannel(user, channel) 308 if err != nil { 309 mlog.Error(err.Error()) 310 311 time.Sleep(time.Second) 312 panic(err) 313 } 314 315 utils.EnableDebugLogForTest() 316 317 return member 318 } 319 320 func (me *TestHelper) TearDown() { 321 me.App.Shutdown() 322 os.Remove(me.tempConfigPath) 323 if err := recover(); err != nil { 324 StopTestStore() 325 panic(err) 326 } 327 if me.tempWorkspace != "" { 328 os.RemoveAll(me.tempWorkspace) 329 } 330 } 331 332 type mockPluginSupervisor struct { 333 hooks plugin.Hooks 334 } 335 336 func (s *mockPluginSupervisor) Start(api plugin.API) error { 337 return s.hooks.OnActivate(api) 338 } 339 340 func (s *mockPluginSupervisor) Stop() error { 341 return nil 342 } 343 344 func (s *mockPluginSupervisor) Hooks() plugin.Hooks { 345 return s.hooks 346 } 347 348 func (me *TestHelper) InstallPlugin(manifest *model.Manifest, hooks plugin.Hooks) { 349 if me.tempWorkspace == "" { 350 dir, err := ioutil.TempDir("", "apptest") 351 if err != nil { 352 panic(err) 353 } 354 me.tempWorkspace = dir 355 } 356 357 pluginDir := filepath.Join(me.tempWorkspace, "plugins") 358 webappDir := filepath.Join(me.tempWorkspace, "webapp") 359 me.App.InitPlugins(pluginDir, webappDir, func(bundle *model.BundleInfo) (plugin.Supervisor, error) { 360 if hooks, ok := me.pluginHooks[bundle.Manifest.Id]; ok { 361 return &mockPluginSupervisor{hooks}, nil 362 } 363 return pluginenv.DefaultSupervisorProvider(bundle) 364 }) 365 366 me.pluginHooks[manifest.Id] = hooks 367 368 manifestCopy := *manifest 369 if manifestCopy.Backend == nil { 370 manifestCopy.Backend = &model.ManifestBackend{} 371 } 372 manifestBytes, err := json.Marshal(&manifestCopy) 373 if err != nil { 374 panic(err) 375 } 376 377 if err := os.MkdirAll(filepath.Join(pluginDir, manifest.Id), 0700); err != nil { 378 panic(err) 379 } 380 381 if err := ioutil.WriteFile(filepath.Join(pluginDir, manifest.Id, "plugin.json"), manifestBytes, 0600); err != nil { 382 panic(err) 383 } 384 } 385 386 func (me *TestHelper) ResetRoleMigration() { 387 if _, err := testStoreSqlSupplier.GetMaster().Exec("DELETE from Roles"); err != nil { 388 panic(err) 389 } 390 391 testClusterInterface.sendClearRoleCacheMessage() 392 393 if _, err := testStoreSqlSupplier.GetMaster().Exec("DELETE from Systems where Name = :Name", map[string]interface{}{"Name": ADVANCED_PERMISSIONS_MIGRATION_KEY}); err != nil { 394 panic(err) 395 } 396 } 397 398 type FakeClusterInterface struct { 399 clusterMessageHandler einterfaces.ClusterMessageHandler 400 } 401 402 func (me *FakeClusterInterface) StartInterNodeCommunication() {} 403 func (me *FakeClusterInterface) StopInterNodeCommunication() {} 404 func (me *FakeClusterInterface) RegisterClusterMessageHandler(event string, crm einterfaces.ClusterMessageHandler) { 405 me.clusterMessageHandler = crm 406 } 407 func (me *FakeClusterInterface) GetClusterId() string { return "" } 408 func (me *FakeClusterInterface) IsLeader() bool { return false } 409 func (me *FakeClusterInterface) GetMyClusterInfo() *model.ClusterInfo { return nil } 410 func (me *FakeClusterInterface) GetClusterInfos() []*model.ClusterInfo { return nil } 411 func (me *FakeClusterInterface) SendClusterMessage(cluster *model.ClusterMessage) {} 412 func (me *FakeClusterInterface) NotifyMsg(buf []byte) {} 413 func (me *FakeClusterInterface) GetClusterStats() ([]*model.ClusterStats, *model.AppError) { 414 return nil, nil 415 } 416 func (me *FakeClusterInterface) GetLogs(page, perPage int) ([]string, *model.AppError) { 417 return []string{}, nil 418 } 419 func (me *FakeClusterInterface) ConfigChanged(previousConfig *model.Config, newConfig *model.Config, sendToOtherServer bool) *model.AppError { 420 return nil 421 } 422 func (me *FakeClusterInterface) sendClearRoleCacheMessage() { 423 me.clusterMessageHandler(&model.ClusterMessage{ 424 Event: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES, 425 }) 426 }