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