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

     1  // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"runtime/debug"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/mattermost/mattermost-server/model"
    12  	"github.com/mattermost/mattermost-server/store"
    13  	"github.com/mattermost/mattermost-server/utils"
    14  )
    15  
    16  func ptrStr(s string) *string {
    17  	return &s
    18  }
    19  
    20  func ptrInt64(i int64) *int64 {
    21  	return &i
    22  }
    23  
    24  func ptrInt(i int) *int {
    25  	return &i
    26  }
    27  
    28  func ptrBool(b bool) *bool {
    29  	return &b
    30  }
    31  
    32  func checkPreference(t *testing.T, a *App, userId string, category string, name string, value string) {
    33  	if res := <-a.Srv.Store.Preference().GetCategory(userId, category); res.Err != nil {
    34  		debug.PrintStack()
    35  		t.Fatalf("Failed to get preferences for user %v with category %v", userId, category)
    36  	} else {
    37  		preferences := res.Data.(model.Preferences)
    38  		found := false
    39  		for _, preference := range preferences {
    40  			if preference.Name == name {
    41  				found = true
    42  				if preference.Value != value {
    43  					debug.PrintStack()
    44  					t.Fatalf("Preference for user %v in category %v with name %v has value %v, expected %v", userId, category, name, preference.Value, value)
    45  				}
    46  				break
    47  			}
    48  		}
    49  		if !found {
    50  			debug.PrintStack()
    51  			t.Fatalf("Did not find preference for user %v in category %v with name %v", userId, category, name)
    52  		}
    53  	}
    54  }
    55  
    56  func checkNotifyProp(t *testing.T, user *model.User, key string, value string) {
    57  	if actual, ok := user.NotifyProps[key]; !ok {
    58  		debug.PrintStack()
    59  		t.Fatalf("Notify prop %v not found. User: %v", key, user.Id)
    60  	} else if actual != value {
    61  		debug.PrintStack()
    62  		t.Fatalf("Notify Prop %v was %v but expected %v. User: %v", key, actual, value, user.Id)
    63  	}
    64  }
    65  
    66  func checkError(t *testing.T, err *model.AppError) {
    67  	if err == nil {
    68  		debug.PrintStack()
    69  		t.Fatal("Should have returned an error.")
    70  	}
    71  }
    72  
    73  func checkNoError(t *testing.T, err *model.AppError) {
    74  	if err != nil {
    75  		debug.PrintStack()
    76  		t.Fatalf("Unexpected Error: %v", err.Error())
    77  	}
    78  }
    79  
    80  func TestImportValidateTeamImportData(t *testing.T) {
    81  
    82  	// Test with minimum required valid properties.
    83  	data := TeamImportData{
    84  		Name:        ptrStr("teamname"),
    85  		DisplayName: ptrStr("Display Name"),
    86  		Type:        ptrStr("O"),
    87  	}
    88  	if err := validateTeamImportData(&data); err != nil {
    89  		t.Fatal("Validation failed but should have been valid.")
    90  	}
    91  
    92  	// Test with various invalid names.
    93  	data = TeamImportData{
    94  		DisplayName: ptrStr("Display Name"),
    95  		Type:        ptrStr("O"),
    96  	}
    97  	if err := validateTeamImportData(&data); err == nil {
    98  		t.Fatal("Should have failed due to missing name.")
    99  	}
   100  
   101  	data.Name = ptrStr(strings.Repeat("abcdefghij", 7))
   102  	if err := validateTeamImportData(&data); err == nil {
   103  		t.Fatal("Should have failed due to too long name.")
   104  	}
   105  
   106  	data.Name = ptrStr("login")
   107  	if err := validateTeamImportData(&data); err == nil {
   108  		t.Fatal("Should have failed due to reserved word in name.")
   109  	}
   110  
   111  	data.Name = ptrStr("Test::''ASD")
   112  	if err := validateTeamImportData(&data); err == nil {
   113  		t.Fatal("Should have failed due to non alphanum characters in name.")
   114  	}
   115  
   116  	data.Name = ptrStr("A")
   117  	if err := validateTeamImportData(&data); err == nil {
   118  		t.Fatal("Should have failed due to short name.")
   119  	}
   120  
   121  	// Test team various invalid display names.
   122  	data = TeamImportData{
   123  		Name: ptrStr("teamname"),
   124  		Type: ptrStr("O"),
   125  	}
   126  	if err := validateTeamImportData(&data); err == nil {
   127  		t.Fatal("Should have failed due to missing display_name.")
   128  	}
   129  
   130  	data.DisplayName = ptrStr("")
   131  	if err := validateTeamImportData(&data); err == nil {
   132  		t.Fatal("Should have failed due to empty display_name.")
   133  	}
   134  
   135  	data.DisplayName = ptrStr(strings.Repeat("abcdefghij", 7))
   136  	if err := validateTeamImportData(&data); err == nil {
   137  		t.Fatal("Should have failed due to too long display_name.")
   138  	}
   139  
   140  	// Test with various valid and invalid types.
   141  	data = TeamImportData{
   142  		Name:        ptrStr("teamname"),
   143  		DisplayName: ptrStr("Display Name"),
   144  	}
   145  	if err := validateTeamImportData(&data); err == nil {
   146  		t.Fatal("Should have failed due to missing type.")
   147  	}
   148  
   149  	data.Type = ptrStr("A")
   150  	if err := validateTeamImportData(&data); err == nil {
   151  		t.Fatal("Should have failed due to invalid type.")
   152  	}
   153  
   154  	data.Type = ptrStr("I")
   155  	if err := validateTeamImportData(&data); err != nil {
   156  		t.Fatal("Should have succeeded with valid type.")
   157  	}
   158  
   159  	// Test with all the combinations of optional parameters.
   160  	data = TeamImportData{
   161  		Name:            ptrStr("teamname"),
   162  		DisplayName:     ptrStr("Display Name"),
   163  		Type:            ptrStr("O"),
   164  		Description:     ptrStr("The team description."),
   165  		AllowOpenInvite: ptrBool(true),
   166  	}
   167  	if err := validateTeamImportData(&data); err != nil {
   168  		t.Fatal("Should have succeeded with valid optional properties.")
   169  	}
   170  
   171  	data.AllowOpenInvite = ptrBool(false)
   172  	if err := validateTeamImportData(&data); err != nil {
   173  		t.Fatal("Should have succeeded with allow open invites false.")
   174  	}
   175  
   176  	data.Description = ptrStr(strings.Repeat("abcdefghij ", 26))
   177  	if err := validateTeamImportData(&data); err == nil {
   178  		t.Fatal("Should have failed due to too long description.")
   179  	}
   180  }
   181  
   182  func TestImportValidateChannelImportData(t *testing.T) {
   183  
   184  	// Test with minimum required valid properties.
   185  	data := ChannelImportData{
   186  		Team:        ptrStr("teamname"),
   187  		Name:        ptrStr("channelname"),
   188  		DisplayName: ptrStr("Display Name"),
   189  		Type:        ptrStr("O"),
   190  	}
   191  	if err := validateChannelImportData(&data); err != nil {
   192  		t.Fatal("Validation failed but should have been valid.")
   193  	}
   194  
   195  	// Test with missing team.
   196  	data = ChannelImportData{
   197  		Name:        ptrStr("channelname"),
   198  		DisplayName: ptrStr("Display Name"),
   199  		Type:        ptrStr("O"),
   200  	}
   201  	if err := validateChannelImportData(&data); err == nil {
   202  		t.Fatal("Should have failed due to missing team.")
   203  	}
   204  
   205  	// Test with various invalid names.
   206  	data = ChannelImportData{
   207  		Team:        ptrStr("teamname"),
   208  		DisplayName: ptrStr("Display Name"),
   209  		Type:        ptrStr("O"),
   210  	}
   211  	if err := validateChannelImportData(&data); err == nil {
   212  		t.Fatal("Should have failed due to missing name.")
   213  	}
   214  
   215  	data.Name = ptrStr(strings.Repeat("abcdefghij", 7))
   216  	if err := validateChannelImportData(&data); err == nil {
   217  		t.Fatal("Should have failed due to too long name.")
   218  	}
   219  
   220  	data.Name = ptrStr("Test::''ASD")
   221  	if err := validateChannelImportData(&data); err == nil {
   222  		t.Fatal("Should have failed due to non alphanum characters in name.")
   223  	}
   224  
   225  	data.Name = ptrStr("A")
   226  	if err := validateChannelImportData(&data); err == nil {
   227  		t.Fatal("Should have failed due to short name.")
   228  	}
   229  
   230  	// Test team various invalid display names.
   231  	data = ChannelImportData{
   232  		Team: ptrStr("teamname"),
   233  		Name: ptrStr("channelname"),
   234  		Type: ptrStr("O"),
   235  	}
   236  	if err := validateChannelImportData(&data); err == nil {
   237  		t.Fatal("Should have failed due to missing display_name.")
   238  	}
   239  
   240  	data.DisplayName = ptrStr("")
   241  	if err := validateChannelImportData(&data); err == nil {
   242  		t.Fatal("Should have failed due to empty display_name.")
   243  	}
   244  
   245  	data.DisplayName = ptrStr(strings.Repeat("abcdefghij", 7))
   246  	if err := validateChannelImportData(&data); err == nil {
   247  		t.Fatal("Should have failed due to too long display_name.")
   248  	}
   249  
   250  	// Test with various valid and invalid types.
   251  	data = ChannelImportData{
   252  		Team:        ptrStr("teamname"),
   253  		Name:        ptrStr("channelname"),
   254  		DisplayName: ptrStr("Display Name"),
   255  	}
   256  	if err := validateChannelImportData(&data); err == nil {
   257  		t.Fatal("Should have failed due to missing type.")
   258  	}
   259  
   260  	data.Type = ptrStr("A")
   261  	if err := validateChannelImportData(&data); err == nil {
   262  		t.Fatal("Should have failed due to invalid type.")
   263  	}
   264  
   265  	data.Type = ptrStr("P")
   266  	if err := validateChannelImportData(&data); err != nil {
   267  		t.Fatal("Should have succeeded with valid type.")
   268  	}
   269  
   270  	// Test with all the combinations of optional parameters.
   271  	data = ChannelImportData{
   272  		Team:        ptrStr("teamname"),
   273  		Name:        ptrStr("channelname"),
   274  		DisplayName: ptrStr("Display Name"),
   275  		Type:        ptrStr("O"),
   276  		Header:      ptrStr("Channel Header Here"),
   277  		Purpose:     ptrStr("Channel Purpose Here"),
   278  	}
   279  	if err := validateChannelImportData(&data); err != nil {
   280  		t.Fatal("Should have succeeded with valid optional properties.")
   281  	}
   282  
   283  	data.Header = ptrStr(strings.Repeat("abcdefghij ", 103))
   284  	if err := validateChannelImportData(&data); err == nil {
   285  		t.Fatal("Should have failed due to too long header.")
   286  	}
   287  
   288  	data.Header = ptrStr("Channel Header Here")
   289  	data.Purpose = ptrStr(strings.Repeat("abcdefghij ", 26))
   290  	if err := validateChannelImportData(&data); err == nil {
   291  		t.Fatal("Should have failed due to too long purpose.")
   292  	}
   293  }
   294  
   295  func TestImportValidateUserImportData(t *testing.T) {
   296  
   297  	// Test with minimum required valid properties.
   298  	data := UserImportData{
   299  		Username: ptrStr("bob"),
   300  		Email:    ptrStr("bob@example.com"),
   301  	}
   302  	if err := validateUserImportData(&data); err != nil {
   303  		t.Fatal("Validation failed but should have been valid.")
   304  	}
   305  
   306  	// Invalid Usernames.
   307  	data.Username = nil
   308  	if err := validateUserImportData(&data); err == nil {
   309  		t.Fatal("Validation should have failed due to nil Username.")
   310  	}
   311  
   312  	data.Username = ptrStr("")
   313  	if err := validateUserImportData(&data); err == nil {
   314  		t.Fatal("Validation should have failed due to 0 length Username.")
   315  	}
   316  
   317  	data.Username = ptrStr(strings.Repeat("abcdefghij", 7))
   318  	if err := validateUserImportData(&data); err == nil {
   319  		t.Fatal("Validation should have failed due to too long Username.")
   320  	}
   321  
   322  	data.Username = ptrStr("i am a username with spaces and !!!")
   323  	if err := validateUserImportData(&data); err == nil {
   324  		t.Fatal("Validation should have failed due to invalid characters in Username.")
   325  	}
   326  
   327  	data.Username = ptrStr("bob")
   328  
   329  	// Unexisting Picture Image
   330  	data.ProfileImage = ptrStr("not-existing-file")
   331  	if err := validateUserImportData(&data); err == nil {
   332  		t.Fatal("Validation should have failed due to not existing profile image file.")
   333  	}
   334  	data.ProfileImage = nil
   335  
   336  	// Invalid Emails
   337  	data.Email = nil
   338  	if err := validateUserImportData(&data); err == nil {
   339  		t.Fatal("Validation should have failed due to nil Email.")
   340  	}
   341  
   342  	data.Email = ptrStr("")
   343  	if err := validateUserImportData(&data); err == nil {
   344  		t.Fatal("Validation should have failed due to 0 length Email.")
   345  	}
   346  
   347  	data.Email = ptrStr(strings.Repeat("abcdefghij", 13))
   348  	if err := validateUserImportData(&data); err == nil {
   349  		t.Fatal("Validation should have failed due to too long Email.")
   350  	}
   351  
   352  	data.Email = ptrStr("bob@example.com")
   353  
   354  	data.AuthService = ptrStr("")
   355  	if err := validateUserImportData(&data); err == nil {
   356  		t.Fatal("Validation should have failed due to 0-length auth service.")
   357  	}
   358  
   359  	data.AuthService = ptrStr("saml")
   360  	data.AuthData = ptrStr(strings.Repeat("abcdefghij", 15))
   361  	if err := validateUserImportData(&data); err == nil {
   362  		t.Fatal("Validation should have failed due to too long auth data.")
   363  	}
   364  
   365  	data.AuthData = ptrStr("bobbytables")
   366  	if err := validateUserImportData(&data); err != nil {
   367  		t.Fatal("Validation should have succeeded with valid auth service and auth data.")
   368  	}
   369  
   370  	// Test a valid User with all fields populated.
   371  	testsDir, _ := utils.FindDir("tests")
   372  	data = UserImportData{
   373  		ProfileImage: ptrStr(testsDir + "test.png"),
   374  		Username:     ptrStr("bob"),
   375  		Email:        ptrStr("bob@example.com"),
   376  		AuthService:  ptrStr("ldap"),
   377  		AuthData:     ptrStr("bob"),
   378  		Nickname:     ptrStr("BobNick"),
   379  		FirstName:    ptrStr("Bob"),
   380  		LastName:     ptrStr("Blob"),
   381  		Position:     ptrStr("The Boss"),
   382  		Roles:        ptrStr("system_user"),
   383  		Locale:       ptrStr("en"),
   384  	}
   385  	if err := validateUserImportData(&data); err != nil {
   386  		t.Fatal("Validation failed but should have been valid.")
   387  	}
   388  
   389  	// Test various invalid optional field values.
   390  	data.Nickname = ptrStr(strings.Repeat("abcdefghij", 7))
   391  	if err := validateUserImportData(&data); err == nil {
   392  		t.Fatal("Validation should have failed due to too long Nickname.")
   393  	}
   394  	data.Nickname = ptrStr("BobNick")
   395  
   396  	data.FirstName = ptrStr(strings.Repeat("abcdefghij", 7))
   397  	if err := validateUserImportData(&data); err == nil {
   398  		t.Fatal("Validation should have failed due to too long First Name.")
   399  	}
   400  	data.FirstName = ptrStr("Bob")
   401  
   402  	data.LastName = ptrStr(strings.Repeat("abcdefghij", 7))
   403  	if err := validateUserImportData(&data); err == nil {
   404  		t.Fatal("Validation should have failed due to too long Last name.")
   405  	}
   406  	data.LastName = ptrStr("Blob")
   407  
   408  	data.Position = ptrStr(strings.Repeat("abcdefghij", 7))
   409  	if err := validateUserImportData(&data); err == nil {
   410  		t.Fatal("Validation should have failed due to too long Position.")
   411  	}
   412  	data.Position = ptrStr("The Boss")
   413  
   414  	data.Roles = ptrStr("system_user wat")
   415  	if err := validateUserImportData(&data); err == nil {
   416  		t.Fatal("Validation should have failed due to too unrecognised role.")
   417  	}
   418  	data.Roles = nil
   419  	if err := validateUserImportData(&data); err != nil {
   420  		t.Fatal("Validation failed but should have been valid.")
   421  	}
   422  
   423  	data.Roles = ptrStr("")
   424  	if err := validateUserImportData(&data); err != nil {
   425  		t.Fatal("Validation failed but should have been valid.")
   426  	}
   427  	data.Roles = ptrStr("system_user")
   428  
   429  	// Try various valid/invalid notify props.
   430  	data.NotifyProps = &UserNotifyPropsImportData{}
   431  
   432  	data.NotifyProps.Desktop = ptrStr("invalid")
   433  	checkError(t, validateUserImportData(&data))
   434  
   435  	data.NotifyProps.Desktop = ptrStr(model.USER_NOTIFY_ALL)
   436  	data.NotifyProps.DesktopDuration = ptrStr("invalid")
   437  	checkError(t, validateUserImportData(&data))
   438  
   439  	data.NotifyProps.DesktopDuration = ptrStr("5")
   440  	data.NotifyProps.DesktopSound = ptrStr("invalid")
   441  	checkError(t, validateUserImportData(&data))
   442  
   443  	data.NotifyProps.DesktopSound = ptrStr("true")
   444  	data.NotifyProps.Email = ptrStr("invalid")
   445  	checkError(t, validateUserImportData(&data))
   446  
   447  	data.NotifyProps.Email = ptrStr("true")
   448  	data.NotifyProps.Mobile = ptrStr("invalid")
   449  	checkError(t, validateUserImportData(&data))
   450  
   451  	data.NotifyProps.Mobile = ptrStr(model.USER_NOTIFY_ALL)
   452  	data.NotifyProps.MobilePushStatus = ptrStr("invalid")
   453  	checkError(t, validateUserImportData(&data))
   454  
   455  	data.NotifyProps.MobilePushStatus = ptrStr(model.STATUS_ONLINE)
   456  	data.NotifyProps.ChannelTrigger = ptrStr("invalid")
   457  	checkError(t, validateUserImportData(&data))
   458  
   459  	data.NotifyProps.ChannelTrigger = ptrStr("true")
   460  	data.NotifyProps.CommentsTrigger = ptrStr("invalid")
   461  	checkError(t, validateUserImportData(&data))
   462  
   463  	data.NotifyProps.CommentsTrigger = ptrStr(model.COMMENTS_NOTIFY_ROOT)
   464  	data.NotifyProps.MentionKeys = ptrStr("valid")
   465  	checkNoError(t, validateUserImportData(&data))
   466  }
   467  
   468  func TestImportValidateUserTeamsImportData(t *testing.T) {
   469  
   470  	// Invalid Name.
   471  	data := []UserTeamImportData{
   472  		{
   473  			Roles: ptrStr("team_admin team_user"),
   474  		},
   475  	}
   476  	if err := validateUserTeamsImportData(&data); err == nil {
   477  		t.Fatal("Should have failed due to invalid name.")
   478  	}
   479  	data[0].Name = ptrStr("teamname")
   480  
   481  	// Invalid Roles
   482  	data[0].Roles = ptrStr("wtf")
   483  	if err := validateUserTeamsImportData(&data); err == nil {
   484  		t.Fatal("Should have failed due to invalid roles.")
   485  	}
   486  
   487  	// Valid (nil roles)
   488  	data[0].Roles = nil
   489  	if err := validateUserTeamsImportData(&data); err != nil {
   490  		t.Fatal("Should have succeeded with empty roles.")
   491  	}
   492  
   493  	// Valid (empty roles)
   494  	data[0].Roles = ptrStr("")
   495  	if err := validateUserTeamsImportData(&data); err != nil {
   496  		t.Fatal("Should have succeeded with empty roles.")
   497  	}
   498  
   499  	// Valid (with roles)
   500  	data[0].Roles = ptrStr("team_admin team_user")
   501  	if err := validateUserTeamsImportData(&data); err != nil {
   502  		t.Fatal("Should have succeeded with valid roles.")
   503  	}
   504  }
   505  
   506  func TestImportValidateUserChannelsImportData(t *testing.T) {
   507  
   508  	// Invalid Name.
   509  	data := []UserChannelImportData{
   510  		{
   511  			Roles: ptrStr("channel_admin channel_user"),
   512  		},
   513  	}
   514  	if err := validateUserChannelsImportData(&data); err == nil {
   515  		t.Fatal("Should have failed due to invalid name.")
   516  	}
   517  	data[0].Name = ptrStr("channelname")
   518  
   519  	// Invalid Roles
   520  	data[0].Roles = ptrStr("wtf")
   521  	if err := validateUserChannelsImportData(&data); err == nil {
   522  		t.Fatal("Should have failed due to invalid roles.")
   523  	}
   524  
   525  	// Valid (nil roles)
   526  	data[0].Roles = nil
   527  	if err := validateUserChannelsImportData(&data); err != nil {
   528  		t.Fatal("Should have succeeded with empty roles.")
   529  	}
   530  
   531  	// Valid (empty roles)
   532  	data[0].Roles = ptrStr("")
   533  	if err := validateUserChannelsImportData(&data); err != nil {
   534  		t.Fatal("Should have succeeded with empty roles.")
   535  	}
   536  
   537  	// Valid (with roles)
   538  	data[0].Roles = ptrStr("channel_admin channel_user")
   539  	if err := validateUserChannelsImportData(&data); err != nil {
   540  		t.Fatal("Should have succeeded with valid roles.")
   541  	}
   542  
   543  	// Empty notify props.
   544  	data[0].NotifyProps = &UserChannelNotifyPropsImportData{}
   545  	if err := validateUserChannelsImportData(&data); err != nil {
   546  		t.Fatal("Should have succeeded with empty notify props.")
   547  	}
   548  
   549  	// Invalid desktop notify props.
   550  	data[0].NotifyProps.Desktop = ptrStr("invalid")
   551  	if err := validateUserChannelsImportData(&data); err == nil {
   552  		t.Fatal("Should have failed with invalid desktop notify props.")
   553  	}
   554  
   555  	// Invalid mobile notify props.
   556  	data[0].NotifyProps.Desktop = ptrStr("mention")
   557  	data[0].NotifyProps.Mobile = ptrStr("invalid")
   558  	if err := validateUserChannelsImportData(&data); err == nil {
   559  		t.Fatal("Should have failed with invalid mobile notify props.")
   560  	}
   561  
   562  	// Invalid mark_unread notify props.
   563  	data[0].NotifyProps.Mobile = ptrStr("mention")
   564  	data[0].NotifyProps.MarkUnread = ptrStr("invalid")
   565  	if err := validateUserChannelsImportData(&data); err == nil {
   566  		t.Fatal("Should have failed with invalid mark_unread notify props.")
   567  	}
   568  
   569  	// Valid notify props.
   570  	data[0].NotifyProps.MarkUnread = ptrStr("mention")
   571  	if err := validateUserChannelsImportData(&data); err != nil {
   572  		t.Fatal("Should have succeeded with valid notify props.")
   573  	}
   574  }
   575  
   576  func TestImportValidateReactionImportData(t *testing.T) {
   577  	// Test with minimum required valid properties.
   578  	parentCreateAt := model.GetMillis() - 100
   579  	data := ReactionImportData{
   580  		User:      ptrStr("username"),
   581  		EmojiName: ptrStr("emoji"),
   582  		CreateAt:  ptrInt64(model.GetMillis()),
   583  	}
   584  	if err := validateReactionImportData(&data, parentCreateAt); err != nil {
   585  		t.Fatal("Validation failed but should have been valid.")
   586  	}
   587  
   588  	// Test with missing required properties.
   589  	data = ReactionImportData{
   590  		EmojiName: ptrStr("emoji"),
   591  		CreateAt:  ptrInt64(model.GetMillis()),
   592  	}
   593  	if err := validateReactionImportData(&data, parentCreateAt); err == nil {
   594  		t.Fatal("Should have failed due to missing required property.")
   595  	}
   596  
   597  	data = ReactionImportData{
   598  		User:     ptrStr("username"),
   599  		CreateAt: ptrInt64(model.GetMillis()),
   600  	}
   601  	if err := validateReactionImportData(&data, parentCreateAt); err == nil {
   602  		t.Fatal("Should have failed due to missing required property.")
   603  	}
   604  
   605  	data = ReactionImportData{
   606  		User:      ptrStr("username"),
   607  		EmojiName: ptrStr("emoji"),
   608  	}
   609  	if err := validateReactionImportData(&data, parentCreateAt); err == nil {
   610  		t.Fatal("Should have failed due to missing required property.")
   611  	}
   612  
   613  	// Test with invalid emoji name.
   614  	data = ReactionImportData{
   615  		User:      ptrStr("username"),
   616  		EmojiName: ptrStr(strings.Repeat("1234567890", 500)),
   617  		CreateAt:  ptrInt64(model.GetMillis()),
   618  	}
   619  	if err := validateReactionImportData(&data, parentCreateAt); err == nil {
   620  		t.Fatal("Should have failed due to too long emoji name.")
   621  	}
   622  
   623  	// Test with invalid CreateAt
   624  	data = ReactionImportData{
   625  		User:      ptrStr("username"),
   626  		EmojiName: ptrStr("emoji"),
   627  		CreateAt:  ptrInt64(0),
   628  	}
   629  	if err := validateReactionImportData(&data, parentCreateAt); err == nil {
   630  		t.Fatal("Should have failed due to 0 create-at value.")
   631  	}
   632  
   633  	data = ReactionImportData{
   634  		User:      ptrStr("username"),
   635  		EmojiName: ptrStr("emoji"),
   636  		CreateAt:  ptrInt64(parentCreateAt - 100),
   637  	}
   638  	if err := validateReactionImportData(&data, parentCreateAt); err == nil {
   639  		t.Fatal("Should have failed due parent with newer create-at value.")
   640  	}
   641  }
   642  
   643  func TestImportValidateReplyImportData(t *testing.T) {
   644  	// Test with minimum required valid properties.
   645  	parentCreateAt := model.GetMillis() - 100
   646  	data := ReplyImportData{
   647  		User:     ptrStr("username"),
   648  		Message:  ptrStr("message"),
   649  		CreateAt: ptrInt64(model.GetMillis()),
   650  	}
   651  	if err := validateReplyImportData(&data, parentCreateAt); err != nil {
   652  		t.Fatal("Validation failed but should have been valid.")
   653  	}
   654  
   655  	// Test with missing required properties.
   656  	data = ReplyImportData{
   657  		Message:  ptrStr("message"),
   658  		CreateAt: ptrInt64(model.GetMillis()),
   659  	}
   660  	if err := validateReplyImportData(&data, parentCreateAt); err == nil {
   661  		t.Fatal("Should have failed due to missing required property.")
   662  	}
   663  
   664  	data = ReplyImportData{
   665  		User:     ptrStr("username"),
   666  		CreateAt: ptrInt64(model.GetMillis()),
   667  	}
   668  	if err := validateReplyImportData(&data, parentCreateAt); err == nil {
   669  		t.Fatal("Should have failed due to missing required property.")
   670  	}
   671  
   672  	data = ReplyImportData{
   673  		User:    ptrStr("username"),
   674  		Message: ptrStr("message"),
   675  	}
   676  	if err := validateReplyImportData(&data, parentCreateAt); err == nil {
   677  		t.Fatal("Should have failed due to missing required property.")
   678  	}
   679  
   680  	// Test with invalid message.
   681  	data = ReplyImportData{
   682  		User:     ptrStr("username"),
   683  		Message:  ptrStr(strings.Repeat("1234567890", 500)),
   684  		CreateAt: ptrInt64(model.GetMillis()),
   685  	}
   686  	if err := validateReplyImportData(&data, parentCreateAt); err == nil {
   687  		t.Fatal("Should have failed due to too long message.")
   688  	}
   689  
   690  	// Test with invalid CreateAt
   691  	data = ReplyImportData{
   692  		User:     ptrStr("username"),
   693  		Message:  ptrStr("message"),
   694  		CreateAt: ptrInt64(0),
   695  	}
   696  	if err := validateReplyImportData(&data, parentCreateAt); err == nil {
   697  		t.Fatal("Should have failed due to 0 create-at value.")
   698  	}
   699  
   700  	data = ReplyImportData{
   701  		User:     ptrStr("username"),
   702  		Message:  ptrStr("message"),
   703  		CreateAt: ptrInt64(parentCreateAt - 100),
   704  	}
   705  	if err := validateReplyImportData(&data, parentCreateAt); err == nil {
   706  		t.Fatal("Should have failed due parent with newer create-at value.")
   707  	}
   708  }
   709  
   710  func TestImportValidatePostImportData(t *testing.T) {
   711  
   712  	// Test with minimum required valid properties.
   713  	data := PostImportData{
   714  		Team:     ptrStr("teamname"),
   715  		Channel:  ptrStr("channelname"),
   716  		User:     ptrStr("username"),
   717  		Message:  ptrStr("message"),
   718  		CreateAt: ptrInt64(model.GetMillis()),
   719  	}
   720  	if err := validatePostImportData(&data); err != nil {
   721  		t.Fatal("Validation failed but should have been valid.")
   722  	}
   723  
   724  	// Test with missing required properties.
   725  	data = PostImportData{
   726  		Channel:  ptrStr("channelname"),
   727  		User:     ptrStr("username"),
   728  		Message:  ptrStr("message"),
   729  		CreateAt: ptrInt64(model.GetMillis()),
   730  	}
   731  	if err := validatePostImportData(&data); err == nil {
   732  		t.Fatal("Should have failed due to missing required property.")
   733  	}
   734  
   735  	data = PostImportData{
   736  		Team:     ptrStr("teamname"),
   737  		User:     ptrStr("username"),
   738  		Message:  ptrStr("message"),
   739  		CreateAt: ptrInt64(model.GetMillis()),
   740  	}
   741  	if err := validatePostImportData(&data); err == nil {
   742  		t.Fatal("Should have failed due to missing required property.")
   743  	}
   744  
   745  	data = PostImportData{
   746  		Team:     ptrStr("teamname"),
   747  		Channel:  ptrStr("channelname"),
   748  		Message:  ptrStr("message"),
   749  		CreateAt: ptrInt64(model.GetMillis()),
   750  	}
   751  	if err := validatePostImportData(&data); err == nil {
   752  		t.Fatal("Should have failed due to missing required property.")
   753  	}
   754  
   755  	data = PostImportData{
   756  		Team:     ptrStr("teamname"),
   757  		Channel:  ptrStr("channelname"),
   758  		User:     ptrStr("username"),
   759  		CreateAt: ptrInt64(model.GetMillis()),
   760  	}
   761  	if err := validatePostImportData(&data); err == nil {
   762  		t.Fatal("Should have failed due to missing required property.")
   763  	}
   764  
   765  	data = PostImportData{
   766  		Team:    ptrStr("teamname"),
   767  		Channel: ptrStr("channelname"),
   768  		User:    ptrStr("username"),
   769  		Message: ptrStr("message"),
   770  	}
   771  	if err := validatePostImportData(&data); err == nil {
   772  		t.Fatal("Should have failed due to missing required property.")
   773  	}
   774  
   775  	// Test with invalid message.
   776  	data = PostImportData{
   777  		Team:     ptrStr("teamname"),
   778  		Channel:  ptrStr("channelname"),
   779  		User:     ptrStr("username"),
   780  		Message:  ptrStr(strings.Repeat("1234567890", 500)),
   781  		CreateAt: ptrInt64(model.GetMillis()),
   782  	}
   783  	if err := validatePostImportData(&data); err == nil {
   784  		t.Fatal("Should have failed due to too long message.")
   785  	}
   786  
   787  	// Test with invalid CreateAt
   788  	data = PostImportData{
   789  		Team:     ptrStr("teamname"),
   790  		Channel:  ptrStr("channelname"),
   791  		User:     ptrStr("username"),
   792  		Message:  ptrStr("message"),
   793  		CreateAt: ptrInt64(0),
   794  	}
   795  	if err := validatePostImportData(&data); err == nil {
   796  		t.Fatal("Should have failed due to 0 create-at value.")
   797  	}
   798  
   799  	// Test with valid all optional parameters.
   800  	reactions := []ReactionImportData{ReactionImportData{
   801  		User:      ptrStr("username"),
   802  		EmojiName: ptrStr("emoji"),
   803  		CreateAt:  ptrInt64(model.GetMillis()),
   804  	}}
   805  	replies := []ReplyImportData{ReplyImportData{
   806  		User:     ptrStr("username"),
   807  		Message:  ptrStr("message"),
   808  		CreateAt: ptrInt64(model.GetMillis()),
   809  	}}
   810  	data = PostImportData{
   811  		Team:      ptrStr("teamname"),
   812  		Channel:   ptrStr("channelname"),
   813  		User:      ptrStr("username"),
   814  		Message:   ptrStr("message"),
   815  		CreateAt:  ptrInt64(model.GetMillis()),
   816  		Reactions: &reactions,
   817  		Replies:   &replies,
   818  	}
   819  	if err := validatePostImportData(&data); err != nil {
   820  		t.Fatal("Should have succeeded.")
   821  	}
   822  }
   823  
   824  func TestImportValidateDirectChannelImportData(t *testing.T) {
   825  
   826  	// Test with valid number of members for direct message.
   827  	data := DirectChannelImportData{
   828  		Members: &[]string{
   829  			model.NewId(),
   830  			model.NewId(),
   831  		},
   832  	}
   833  	if err := validateDirectChannelImportData(&data); err != nil {
   834  		t.Fatal("Validation failed but should have been valid.")
   835  	}
   836  
   837  	// Test with valid number of members for group message.
   838  	data = DirectChannelImportData{
   839  		Members: &[]string{
   840  			model.NewId(),
   841  			model.NewId(),
   842  			model.NewId(),
   843  		},
   844  	}
   845  	if err := validateDirectChannelImportData(&data); err != nil {
   846  		t.Fatal("Validation failed but should have been valid.")
   847  	}
   848  
   849  	// Test with all the combinations of optional parameters.
   850  	data = DirectChannelImportData{
   851  		Members: &[]string{
   852  			model.NewId(),
   853  			model.NewId(),
   854  		},
   855  		Header: ptrStr("Channel Header Here"),
   856  	}
   857  	if err := validateDirectChannelImportData(&data); err != nil {
   858  		t.Fatal("Should have succeeded with valid optional properties.")
   859  	}
   860  
   861  	// Test with invalid Header.
   862  	data.Header = ptrStr(strings.Repeat("abcdefghij ", 103))
   863  	if err := validateDirectChannelImportData(&data); err == nil {
   864  		t.Fatal("Should have failed due to too long header.")
   865  	}
   866  
   867  	// Test with different combinations of invalid member counts.
   868  	data = DirectChannelImportData{
   869  		Members: &[]string{},
   870  	}
   871  	if err := validateDirectChannelImportData(&data); err == nil {
   872  		t.Fatal("Validation should have failed due to invalid number of members.")
   873  	}
   874  
   875  	data = DirectChannelImportData{
   876  		Members: &[]string{
   877  			model.NewId(),
   878  		},
   879  	}
   880  	if err := validateDirectChannelImportData(&data); err == nil {
   881  		t.Fatal("Validation should have failed due to invalid number of members.")
   882  	}
   883  
   884  	data = DirectChannelImportData{
   885  		Members: &[]string{
   886  			model.NewId(),
   887  			model.NewId(),
   888  			model.NewId(),
   889  			model.NewId(),
   890  			model.NewId(),
   891  			model.NewId(),
   892  			model.NewId(),
   893  			model.NewId(),
   894  			model.NewId(),
   895  		},
   896  	}
   897  	if err := validateDirectChannelImportData(&data); err == nil {
   898  		t.Fatal("Validation should have failed due to invalid number of members.")
   899  	}
   900  
   901  	// Test with invalid FavoritedBy
   902  	member1 := model.NewId()
   903  	member2 := model.NewId()
   904  	data = DirectChannelImportData{
   905  		Members: &[]string{
   906  			member1,
   907  			member2,
   908  		},
   909  		FavoritedBy: &[]string{
   910  			member1,
   911  			model.NewId(),
   912  		},
   913  	}
   914  	if err := validateDirectChannelImportData(&data); err == nil {
   915  		t.Fatal("Validation should have failed due to non-member favorited.")
   916  	}
   917  
   918  	// Test with valid FavoritedBy
   919  	data = DirectChannelImportData{
   920  		Members: &[]string{
   921  			member1,
   922  			member2,
   923  		},
   924  		FavoritedBy: &[]string{
   925  			member1,
   926  			member2,
   927  		},
   928  	}
   929  	if err := validateDirectChannelImportData(&data); err != nil {
   930  		t.Fatal(err)
   931  	}
   932  }
   933  
   934  func TestImportValidateDirectPostImportData(t *testing.T) {
   935  
   936  	// Test with minimum required valid properties.
   937  	data := DirectPostImportData{
   938  		ChannelMembers: &[]string{
   939  			model.NewId(),
   940  			model.NewId(),
   941  		},
   942  		User:     ptrStr("username"),
   943  		Message:  ptrStr("message"),
   944  		CreateAt: ptrInt64(model.GetMillis()),
   945  	}
   946  	if err := validateDirectPostImportData(&data); err != nil {
   947  		t.Fatal("Validation failed but should have been valid.")
   948  	}
   949  
   950  	// Test with missing required properties.
   951  	data = DirectPostImportData{
   952  		User:     ptrStr("username"),
   953  		Message:  ptrStr("message"),
   954  		CreateAt: ptrInt64(model.GetMillis()),
   955  	}
   956  	if err := validateDirectPostImportData(&data); err == nil {
   957  		t.Fatal("Should have failed due to missing required property.")
   958  	}
   959  
   960  	data = DirectPostImportData{
   961  		ChannelMembers: &[]string{
   962  			model.NewId(),
   963  			model.NewId(),
   964  		},
   965  		Message:  ptrStr("message"),
   966  		CreateAt: ptrInt64(model.GetMillis()),
   967  	}
   968  	if err := validateDirectPostImportData(&data); err == nil {
   969  		t.Fatal("Should have failed due to missing required property.")
   970  	}
   971  
   972  	data = DirectPostImportData{
   973  		ChannelMembers: &[]string{
   974  			model.NewId(),
   975  			model.NewId(),
   976  		},
   977  		User:     ptrStr("username"),
   978  		CreateAt: ptrInt64(model.GetMillis()),
   979  	}
   980  	if err := validateDirectPostImportData(&data); err == nil {
   981  		t.Fatal("Should have failed due to missing required property.")
   982  	}
   983  
   984  	data = DirectPostImportData{
   985  		ChannelMembers: &[]string{
   986  			model.NewId(),
   987  			model.NewId(),
   988  		},
   989  		User:    ptrStr("username"),
   990  		Message: ptrStr("message"),
   991  	}
   992  	if err := validateDirectPostImportData(&data); err == nil {
   993  		t.Fatal("Should have failed due to missing required property.")
   994  	}
   995  
   996  	// Test with invalid numbers of channel members.
   997  	data = DirectPostImportData{
   998  		ChannelMembers: &[]string{},
   999  		User:           ptrStr("username"),
  1000  		Message:        ptrStr("message"),
  1001  		CreateAt:       ptrInt64(model.GetMillis()),
  1002  	}
  1003  	if err := validateDirectPostImportData(&data); err == nil {
  1004  		t.Fatal("Should have failed due to unsuitable number of members.")
  1005  	}
  1006  
  1007  	data = DirectPostImportData{
  1008  		ChannelMembers: &[]string{
  1009  			model.NewId(),
  1010  		},
  1011  		User:     ptrStr("username"),
  1012  		Message:  ptrStr("message"),
  1013  		CreateAt: ptrInt64(model.GetMillis()),
  1014  	}
  1015  	if err := validateDirectPostImportData(&data); err == nil {
  1016  		t.Fatal("Should have failed due to unsuitable number of members.")
  1017  	}
  1018  
  1019  	data = DirectPostImportData{
  1020  		ChannelMembers: &[]string{
  1021  			model.NewId(),
  1022  			model.NewId(),
  1023  			model.NewId(),
  1024  			model.NewId(),
  1025  			model.NewId(),
  1026  			model.NewId(),
  1027  			model.NewId(),
  1028  			model.NewId(),
  1029  			model.NewId(),
  1030  			model.NewId(),
  1031  		},
  1032  		User:     ptrStr("username"),
  1033  		Message:  ptrStr("message"),
  1034  		CreateAt: ptrInt64(model.GetMillis()),
  1035  	}
  1036  	if err := validateDirectPostImportData(&data); err == nil {
  1037  		t.Fatal("Should have failed due to unsuitable number of members.")
  1038  	}
  1039  
  1040  	// Test with group message number of members.
  1041  	data = DirectPostImportData{
  1042  		ChannelMembers: &[]string{
  1043  			model.NewId(),
  1044  			model.NewId(),
  1045  			model.NewId(),
  1046  		},
  1047  		User:     ptrStr("username"),
  1048  		Message:  ptrStr("message"),
  1049  		CreateAt: ptrInt64(model.GetMillis()),
  1050  	}
  1051  	if err := validateDirectPostImportData(&data); err != nil {
  1052  		t.Fatal("Validation failed but should have been valid.")
  1053  	}
  1054  
  1055  	// Test with invalid message.
  1056  	data = DirectPostImportData{
  1057  		ChannelMembers: &[]string{
  1058  			model.NewId(),
  1059  			model.NewId(),
  1060  		},
  1061  		User:     ptrStr("username"),
  1062  		Message:  ptrStr(strings.Repeat("1234567890", 500)),
  1063  		CreateAt: ptrInt64(model.GetMillis()),
  1064  	}
  1065  	if err := validateDirectPostImportData(&data); err == nil {
  1066  		t.Fatal("Should have failed due to too long message.")
  1067  	}
  1068  
  1069  	// Test with invalid CreateAt
  1070  	data = DirectPostImportData{
  1071  		ChannelMembers: &[]string{
  1072  			model.NewId(),
  1073  			model.NewId(),
  1074  		},
  1075  		User:     ptrStr("username"),
  1076  		Message:  ptrStr("message"),
  1077  		CreateAt: ptrInt64(0),
  1078  	}
  1079  	if err := validateDirectPostImportData(&data); err == nil {
  1080  		t.Fatal("Should have failed due to 0 create-at value.")
  1081  	}
  1082  
  1083  	// Test with invalid FlaggedBy
  1084  	member1 := model.NewId()
  1085  	member2 := model.NewId()
  1086  	data = DirectPostImportData{
  1087  		ChannelMembers: &[]string{
  1088  			member1,
  1089  			member2,
  1090  		},
  1091  		FlaggedBy: &[]string{
  1092  			member1,
  1093  			model.NewId(),
  1094  		},
  1095  		User:     ptrStr("username"),
  1096  		Message:  ptrStr("message"),
  1097  		CreateAt: ptrInt64(model.GetMillis()),
  1098  	}
  1099  	if err := validateDirectPostImportData(&data); err == nil {
  1100  		t.Fatal("Validation should have failed due to non-member flagged.")
  1101  	}
  1102  
  1103  	// Test with valid FlaggedBy
  1104  	data = DirectPostImportData{
  1105  		ChannelMembers: &[]string{
  1106  			member1,
  1107  			member2,
  1108  		},
  1109  		FlaggedBy: &[]string{
  1110  			member1,
  1111  			member2,
  1112  		},
  1113  		User:     ptrStr("username"),
  1114  		Message:  ptrStr("message"),
  1115  		CreateAt: ptrInt64(model.GetMillis()),
  1116  	}
  1117  	if err := validateDirectPostImportData(&data); err != nil {
  1118  		t.Fatal(err)
  1119  	}
  1120  
  1121  	// Test with valid all optional parameters.
  1122  	reactions := []ReactionImportData{ReactionImportData{
  1123  		User:      ptrStr("username"),
  1124  		EmojiName: ptrStr("emoji"),
  1125  		CreateAt:  ptrInt64(model.GetMillis()),
  1126  	}}
  1127  	replies := []ReplyImportData{ReplyImportData{
  1128  		User:     ptrStr("username"),
  1129  		Message:  ptrStr("message"),
  1130  		CreateAt: ptrInt64(model.GetMillis()),
  1131  	}}
  1132  	data = DirectPostImportData{
  1133  		ChannelMembers: &[]string{
  1134  			member1,
  1135  			member2,
  1136  		},
  1137  		FlaggedBy: &[]string{
  1138  			member1,
  1139  			member2,
  1140  		},
  1141  		User:      ptrStr("username"),
  1142  		Message:   ptrStr("message"),
  1143  		CreateAt:  ptrInt64(model.GetMillis()),
  1144  		Reactions: &reactions,
  1145  		Replies:   &replies,
  1146  	}
  1147  
  1148  	if err := validateDirectPostImportData(&data); err != nil {
  1149  		t.Fatal(err)
  1150  	}
  1151  }
  1152  
  1153  func TestImportImportTeam(t *testing.T) {
  1154  	th := Setup()
  1155  	defer th.TearDown()
  1156  
  1157  	// Check how many teams are in the database.
  1158  	var teamsCount int64
  1159  	if r := <-th.App.Srv.Store.Team().AnalyticsTeamCount(); r.Err == nil {
  1160  		teamsCount = r.Data.(int64)
  1161  	} else {
  1162  		t.Fatalf("Failed to get team count.")
  1163  	}
  1164  
  1165  	data := TeamImportData{
  1166  		Name:            ptrStr(model.NewId()),
  1167  		DisplayName:     ptrStr("Display Name"),
  1168  		Type:            ptrStr("XYZ"),
  1169  		Description:     ptrStr("The team description."),
  1170  		AllowOpenInvite: ptrBool(true),
  1171  	}
  1172  
  1173  	// Try importing an invalid team in dryRun mode.
  1174  	if err := th.App.ImportTeam(&data, true); err == nil {
  1175  		t.Fatalf("Should have received an error importing an invalid team.")
  1176  	}
  1177  
  1178  	// Do a valid team in dry-run mode.
  1179  	data.Type = ptrStr("O")
  1180  	if err := th.App.ImportTeam(&data, true); err != nil {
  1181  		t.Fatalf("Received an error validating valid team.")
  1182  	}
  1183  
  1184  	// Check that no more teams are in the DB.
  1185  	if r := <-th.App.Srv.Store.Team().AnalyticsTeamCount(); r.Err == nil {
  1186  		if r.Data.(int64) != teamsCount {
  1187  			t.Fatalf("Teams got persisted in dry run mode.")
  1188  		}
  1189  	} else {
  1190  		t.Fatalf("Failed to get team count.")
  1191  	}
  1192  
  1193  	// Do an invalid team in apply mode, check db changes.
  1194  	data.Type = ptrStr("XYZ")
  1195  	if err := th.App.ImportTeam(&data, false); err == nil {
  1196  		t.Fatalf("Import should have failed on invalid team.")
  1197  	}
  1198  
  1199  	// Check that no more teams are in the DB.
  1200  	if r := <-th.App.Srv.Store.Team().AnalyticsTeamCount(); r.Err == nil {
  1201  		if r.Data.(int64) != teamsCount {
  1202  			t.Fatalf("Invalid team got persisted.")
  1203  		}
  1204  	} else {
  1205  		t.Fatalf("Failed to get team count.")
  1206  	}
  1207  
  1208  	// Do a valid team in apply mode, check db changes.
  1209  	data.Type = ptrStr("O")
  1210  	if err := th.App.ImportTeam(&data, false); err != nil {
  1211  		t.Fatalf("Received an error importing valid team.")
  1212  	}
  1213  
  1214  	// Check that one more team is in the DB.
  1215  	if r := <-th.App.Srv.Store.Team().AnalyticsTeamCount(); r.Err == nil {
  1216  		if r.Data.(int64)-1 != teamsCount {
  1217  			t.Fatalf("Team did not get saved in apply run mode. analytics=%v teamcount=%v", r.Data.(int64), teamsCount)
  1218  		}
  1219  	} else {
  1220  		t.Fatalf("Failed to get team count.")
  1221  	}
  1222  
  1223  	// Get the team and check that all the fields are correct.
  1224  	if team, err := th.App.GetTeamByName(*data.Name); err != nil {
  1225  		t.Fatalf("Failed to get team from database.")
  1226  	} else {
  1227  		if team.DisplayName != *data.DisplayName || team.Type != *data.Type || team.Description != *data.Description || team.AllowOpenInvite != *data.AllowOpenInvite {
  1228  			t.Fatalf("Imported team properties do not match import data.")
  1229  		}
  1230  	}
  1231  
  1232  	// Alter all the fields of that team (apart from unique identifier) and import again.
  1233  	data.DisplayName = ptrStr("Display Name 2")
  1234  	data.Type = ptrStr("P")
  1235  	data.Description = ptrStr("The new description")
  1236  	data.AllowOpenInvite = ptrBool(false)
  1237  
  1238  	// Check that the original number of teams are again in the DB (because this query doesn't include deleted).
  1239  	data.Type = ptrStr("O")
  1240  	if err := th.App.ImportTeam(&data, false); err != nil {
  1241  		t.Fatalf("Received an error importing updated valid team.")
  1242  	}
  1243  
  1244  	if r := <-th.App.Srv.Store.Team().AnalyticsTeamCount(); r.Err == nil {
  1245  		if r.Data.(int64)-1 != teamsCount {
  1246  			t.Fatalf("Team alterations did not get saved in apply run mode. analytics=%v teamcount=%v", r.Data.(int64), teamsCount)
  1247  		}
  1248  	} else {
  1249  		t.Fatalf("Failed to get team count.")
  1250  	}
  1251  
  1252  	// Get the team and check that all fields are correct.
  1253  	if team, err := th.App.GetTeamByName(*data.Name); err != nil {
  1254  		t.Fatalf("Failed to get team from database.")
  1255  	} else {
  1256  		if team.DisplayName != *data.DisplayName || team.Type != *data.Type || team.Description != *data.Description || team.AllowOpenInvite != *data.AllowOpenInvite {
  1257  			t.Fatalf("Updated team properties do not match import data.")
  1258  		}
  1259  	}
  1260  }
  1261  
  1262  func TestImportImportChannel(t *testing.T) {
  1263  	th := Setup()
  1264  	defer th.TearDown()
  1265  
  1266  	// Import a Team.
  1267  	teamName := model.NewId()
  1268  	th.App.ImportTeam(&TeamImportData{
  1269  		Name:        &teamName,
  1270  		DisplayName: ptrStr("Display Name"),
  1271  		Type:        ptrStr("O"),
  1272  	}, false)
  1273  	team, err := th.App.GetTeamByName(teamName)
  1274  	if err != nil {
  1275  		t.Fatalf("Failed to get team from database.")
  1276  	}
  1277  
  1278  	// Check how many channels are in the database.
  1279  	var channelCount int64
  1280  	if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_OPEN); r.Err == nil {
  1281  		channelCount = r.Data.(int64)
  1282  	} else {
  1283  		t.Fatalf("Failed to get team count.")
  1284  	}
  1285  
  1286  	// Do an invalid channel in dry-run mode.
  1287  	data := ChannelImportData{
  1288  		Team:        &teamName,
  1289  		DisplayName: ptrStr("Display Name"),
  1290  		Type:        ptrStr("O"),
  1291  		Header:      ptrStr("Channe Header"),
  1292  		Purpose:     ptrStr("Channel Purpose"),
  1293  	}
  1294  	if err := th.App.ImportChannel(&data, true); err == nil {
  1295  		t.Fatalf("Expected error due to invalid name.")
  1296  	}
  1297  
  1298  	// Check that no more channels are in the DB.
  1299  	if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_OPEN); r.Err == nil {
  1300  		if r.Data.(int64) != channelCount {
  1301  			t.Fatalf("Channels got persisted in dry run mode.")
  1302  		}
  1303  	} else {
  1304  		t.Fatalf("Failed to get channel count.")
  1305  	}
  1306  
  1307  	// Do a valid channel with a nonexistent team in dry-run mode.
  1308  	data.Name = ptrStr("channelname")
  1309  	data.Team = ptrStr(model.NewId())
  1310  	if err := th.App.ImportChannel(&data, true); err != nil {
  1311  		t.Fatalf("Expected success as cannot validate channel name in dry run mode.")
  1312  	}
  1313  
  1314  	// Check that no more channels are in the DB.
  1315  	if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_OPEN); r.Err == nil {
  1316  		if r.Data.(int64) != channelCount {
  1317  			t.Fatalf("Channels got persisted in dry run mode.")
  1318  		}
  1319  	} else {
  1320  		t.Fatalf("Failed to get channel count.")
  1321  	}
  1322  
  1323  	// Do a valid channel in dry-run mode.
  1324  	data.Team = &teamName
  1325  	if err := th.App.ImportChannel(&data, true); err != nil {
  1326  		t.Fatalf("Expected success as valid team.")
  1327  	}
  1328  
  1329  	// Check that no more channels are in the DB.
  1330  	if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_OPEN); r.Err == nil {
  1331  		if r.Data.(int64) != channelCount {
  1332  			t.Fatalf("Channels got persisted in dry run mode.")
  1333  		}
  1334  	} else {
  1335  		t.Fatalf("Failed to get channel count.")
  1336  	}
  1337  
  1338  	// Do an invalid channel in apply mode.
  1339  	data.Name = nil
  1340  	if err := th.App.ImportChannel(&data, false); err == nil {
  1341  		t.Fatalf("Expected error due to invalid name (apply mode).")
  1342  	}
  1343  
  1344  	// Check that no more channels are in the DB.
  1345  	if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_OPEN); r.Err == nil {
  1346  		if r.Data.(int64) != channelCount {
  1347  			t.Fatalf("Invalid channel got persisted in apply mode.")
  1348  		}
  1349  	} else {
  1350  		t.Fatalf("Failed to get channel count.")
  1351  	}
  1352  
  1353  	// Do a valid channel in apply mode with a nonexistant team.
  1354  	data.Name = ptrStr("channelname")
  1355  	data.Team = ptrStr(model.NewId())
  1356  	if err := th.App.ImportChannel(&data, false); err == nil {
  1357  		t.Fatalf("Expected error due to non-existant team (apply mode).")
  1358  	}
  1359  
  1360  	// Check that no more channels are in the DB.
  1361  	if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_OPEN); r.Err == nil {
  1362  		if r.Data.(int64) != channelCount {
  1363  			t.Fatalf("Invalid team channel got persisted in apply mode.")
  1364  		}
  1365  	} else {
  1366  		t.Fatalf("Failed to get channel count.")
  1367  	}
  1368  
  1369  	// Do a valid channel in apply mode.
  1370  	data.Team = &teamName
  1371  	if err := th.App.ImportChannel(&data, false); err != nil {
  1372  		t.Fatalf("Expected success in apply mode: %v", err.Error())
  1373  	}
  1374  
  1375  	// Check that no more channels are in the DB.
  1376  	if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_OPEN); r.Err == nil {
  1377  		if r.Data.(int64) != channelCount+1 {
  1378  			t.Fatalf("Channels did not get persisted in apply mode: found %v expected %v + 1", r.Data.(int64), channelCount)
  1379  		}
  1380  	} else {
  1381  		t.Fatalf("Failed to get channel count.")
  1382  	}
  1383  
  1384  	// Get the Channel and check all the fields are correct.
  1385  	if channel, err := th.App.GetChannelByName(*data.Name, team.Id); err != nil {
  1386  		t.Fatalf("Failed to get channel from database.")
  1387  	} else {
  1388  		if channel.Name != *data.Name || channel.DisplayName != *data.DisplayName || channel.Type != *data.Type || channel.Header != *data.Header || channel.Purpose != *data.Purpose {
  1389  			t.Fatalf("Imported team properties do not match Import Data.")
  1390  		}
  1391  	}
  1392  
  1393  	// Alter all the fields of that channel.
  1394  	data.DisplayName = ptrStr("Chaned Disp Name")
  1395  	data.Type = ptrStr(model.CHANNEL_PRIVATE)
  1396  	data.Header = ptrStr("New Header")
  1397  	data.Purpose = ptrStr("New Purpose")
  1398  	if err := th.App.ImportChannel(&data, false); err != nil {
  1399  		t.Fatalf("Expected success in apply mode: %v", err.Error())
  1400  	}
  1401  
  1402  	// Check channel count the same.
  1403  	if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_OPEN); r.Err == nil {
  1404  		if r.Data.(int64) != channelCount {
  1405  			t.Fatalf("Updated channel did not get correctly persisted in apply mode.")
  1406  		}
  1407  	} else {
  1408  		t.Fatalf("Failed to get channel count.")
  1409  	}
  1410  
  1411  	// Get the Channel and check all the fields are correct.
  1412  	if channel, err := th.App.GetChannelByName(*data.Name, team.Id); err != nil {
  1413  		t.Fatalf("Failed to get channel from database.")
  1414  	} else {
  1415  		if channel.Name != *data.Name || channel.DisplayName != *data.DisplayName || channel.Type != *data.Type || channel.Header != *data.Header || channel.Purpose != *data.Purpose {
  1416  			t.Fatalf("Updated team properties do not match Import Data.")
  1417  		}
  1418  	}
  1419  
  1420  }
  1421  
  1422  func TestImportImportUser(t *testing.T) {
  1423  	th := Setup()
  1424  	defer th.TearDown()
  1425  
  1426  	// Check how many users are in the database.
  1427  	var userCount int64
  1428  	if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
  1429  		userCount = r.Data.(int64)
  1430  	} else {
  1431  		t.Fatalf("Failed to get user count.")
  1432  	}
  1433  
  1434  	// Do an invalid user in dry-run mode.
  1435  	data := UserImportData{
  1436  		Username: ptrStr(model.NewId()),
  1437  	}
  1438  	if err := th.App.ImportUser(&data, true); err == nil {
  1439  		t.Fatalf("Should have failed to import invalid user.")
  1440  	}
  1441  
  1442  	// Check that no more users are in the DB.
  1443  	if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
  1444  		if r.Data.(int64) != userCount {
  1445  			t.Fatalf("Unexpected number of users")
  1446  		}
  1447  	} else {
  1448  		t.Fatalf("Failed to get user count.")
  1449  	}
  1450  
  1451  	// Do a valid user in dry-run mode.
  1452  	data = UserImportData{
  1453  		Username: ptrStr(model.NewId()),
  1454  		Email:    ptrStr(model.NewId() + "@example.com"),
  1455  	}
  1456  	if err := th.App.ImportUser(&data, true); err != nil {
  1457  		t.Fatalf("Should have succeeded to import valid user.")
  1458  	}
  1459  
  1460  	// Check that no more users are in the DB.
  1461  	if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
  1462  		if r.Data.(int64) != userCount {
  1463  			t.Fatalf("Unexpected number of users")
  1464  		}
  1465  	} else {
  1466  		t.Fatalf("Failed to get user count.")
  1467  	}
  1468  
  1469  	// Do an invalid user in apply mode.
  1470  	data = UserImportData{
  1471  		Username: ptrStr(model.NewId()),
  1472  	}
  1473  	if err := th.App.ImportUser(&data, false); err == nil {
  1474  		t.Fatalf("Should have failed to import invalid user.")
  1475  	}
  1476  
  1477  	// Check that no more users are in the DB.
  1478  	if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
  1479  		if r.Data.(int64) != userCount {
  1480  			t.Fatalf("Unexpected number of users")
  1481  		}
  1482  	} else {
  1483  		t.Fatalf("Failed to get user count.")
  1484  	}
  1485  
  1486  	// Do a valid user in apply mode.
  1487  	username := model.NewId()
  1488  	testsDir, _ := utils.FindDir("tests")
  1489  	data = UserImportData{
  1490  		ProfileImage: ptrStr(testsDir + "test.png"),
  1491  		Username:     &username,
  1492  		Email:        ptrStr(model.NewId() + "@example.com"),
  1493  		Nickname:     ptrStr(model.NewId()),
  1494  		FirstName:    ptrStr(model.NewId()),
  1495  		LastName:     ptrStr(model.NewId()),
  1496  		Position:     ptrStr(model.NewId()),
  1497  	}
  1498  	if err := th.App.ImportUser(&data, false); err != nil {
  1499  		t.Fatalf("Should have succeeded to import valid user.")
  1500  	}
  1501  
  1502  	// Check that one more user is in the DB.
  1503  	if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
  1504  		if r.Data.(int64) != userCount+1 {
  1505  			t.Fatalf("Unexpected number of users")
  1506  		}
  1507  	} else {
  1508  		t.Fatalf("Failed to get user count.")
  1509  	}
  1510  
  1511  	// Get the user and check all the fields are correct.
  1512  	if user, err := th.App.GetUserByUsername(username); err != nil {
  1513  		t.Fatalf("Failed to get user from database.")
  1514  	} else {
  1515  		if user.Email != *data.Email || user.Nickname != *data.Nickname || user.FirstName != *data.FirstName || user.LastName != *data.LastName || user.Position != *data.Position {
  1516  			t.Fatalf("User properties do not match Import Data.")
  1517  		}
  1518  		// Check calculated properties.
  1519  		if user.AuthService != "" {
  1520  			t.Fatalf("Expected Auth Service to be empty.")
  1521  		}
  1522  
  1523  		if !(user.AuthData == nil || *user.AuthData == "") {
  1524  			t.Fatalf("Expected AuthData to be empty.")
  1525  		}
  1526  
  1527  		if len(user.Password) == 0 {
  1528  			t.Fatalf("Expected password to be set.")
  1529  		}
  1530  
  1531  		if !user.EmailVerified {
  1532  			t.Fatalf("Expected EmailVerified to be true.")
  1533  		}
  1534  
  1535  		if user.Locale != *th.App.Config().LocalizationSettings.DefaultClientLocale {
  1536  			t.Fatalf("Expected Locale to be the default.")
  1537  		}
  1538  
  1539  		if user.Roles != "system_user" {
  1540  			t.Fatalf("Expected roles to be system_user")
  1541  		}
  1542  	}
  1543  
  1544  	// Alter all the fields of that user.
  1545  	data.Email = ptrStr(model.NewId() + "@example.com")
  1546  	data.ProfileImage = ptrStr(testsDir + "testgif.gif")
  1547  	data.AuthService = ptrStr("ldap")
  1548  	data.AuthData = &username
  1549  	data.Nickname = ptrStr(model.NewId())
  1550  	data.FirstName = ptrStr(model.NewId())
  1551  	data.LastName = ptrStr(model.NewId())
  1552  	data.Position = ptrStr(model.NewId())
  1553  	data.Roles = ptrStr("system_admin system_user")
  1554  	data.Locale = ptrStr("zh_CN")
  1555  	if err := th.App.ImportUser(&data, false); err != nil {
  1556  		t.Fatalf("Should have succeeded to update valid user %v", err)
  1557  	}
  1558  
  1559  	// Check user count the same.
  1560  	if r := <-th.App.Srv.Store.User().GetTotalUsersCount(); r.Err == nil {
  1561  		if r.Data.(int64) != userCount+1 {
  1562  			t.Fatalf("Unexpected number of users")
  1563  		}
  1564  	} else {
  1565  		t.Fatalf("Failed to get user count.")
  1566  	}
  1567  
  1568  	// Get the user and check all the fields are correct.
  1569  	if user, err := th.App.GetUserByUsername(username); err != nil {
  1570  		t.Fatalf("Failed to get user from database.")
  1571  	} else {
  1572  		if user.Email != *data.Email || user.Nickname != *data.Nickname || user.FirstName != *data.FirstName || user.LastName != *data.LastName || user.Position != *data.Position {
  1573  			t.Fatalf("Updated User properties do not match Import Data.")
  1574  		}
  1575  		// Check calculated properties.
  1576  		if user.AuthService != "ldap" {
  1577  			t.Fatalf("Expected Auth Service to be ldap \"%v\"", user.AuthService)
  1578  		}
  1579  
  1580  		if !(user.AuthData == data.AuthData || *user.AuthData == *data.AuthData) {
  1581  			t.Fatalf("Expected AuthData to be set.")
  1582  		}
  1583  
  1584  		if len(user.Password) != 0 {
  1585  			t.Fatalf("Expected password to be empty.")
  1586  		}
  1587  
  1588  		if !user.EmailVerified {
  1589  			t.Fatalf("Expected EmailVerified to be true.")
  1590  		}
  1591  
  1592  		if user.Locale != *data.Locale {
  1593  			t.Fatalf("Expected Locale to be the set.")
  1594  		}
  1595  
  1596  		if user.Roles != *data.Roles {
  1597  			t.Fatalf("Expected roles to be set: %v", user.Roles)
  1598  		}
  1599  	}
  1600  
  1601  	// Check Password and AuthData together.
  1602  	data.Password = ptrStr("PasswordTest")
  1603  	if err := th.App.ImportUser(&data, false); err == nil {
  1604  		t.Fatalf("Should have failed to import invalid user.")
  1605  	}
  1606  
  1607  	data.AuthData = nil
  1608  	if err := th.App.ImportUser(&data, false); err != nil {
  1609  		t.Fatalf("Should have succeeded to update valid user %v", err)
  1610  	}
  1611  
  1612  	data.Password = ptrStr("")
  1613  	if err := th.App.ImportUser(&data, false); err == nil {
  1614  		t.Fatalf("Should have failed to import invalid user.")
  1615  	}
  1616  
  1617  	data.Password = ptrStr(strings.Repeat("0123456789", 10))
  1618  	if err := th.App.ImportUser(&data, false); err == nil {
  1619  		t.Fatalf("Should have failed to import invalid user.")
  1620  	}
  1621  
  1622  	data.Password = ptrStr("TestPassword")
  1623  
  1624  	// Test team and channel memberships
  1625  	teamName := model.NewId()
  1626  	th.App.ImportTeam(&TeamImportData{
  1627  		Name:        &teamName,
  1628  		DisplayName: ptrStr("Display Name"),
  1629  		Type:        ptrStr("O"),
  1630  	}, false)
  1631  	team, err := th.App.GetTeamByName(teamName)
  1632  	if err != nil {
  1633  		t.Fatalf("Failed to get team from database.")
  1634  	}
  1635  
  1636  	channelName := model.NewId()
  1637  	th.App.ImportChannel(&ChannelImportData{
  1638  		Team:        &teamName,
  1639  		Name:        &channelName,
  1640  		DisplayName: ptrStr("Display Name"),
  1641  		Type:        ptrStr("O"),
  1642  	}, false)
  1643  	channel, err := th.App.GetChannelByName(channelName, team.Id)
  1644  	if err != nil {
  1645  		t.Fatalf("Failed to get channel from database.")
  1646  	}
  1647  
  1648  	username = model.NewId()
  1649  	data = UserImportData{
  1650  		Username:  &username,
  1651  		Email:     ptrStr(model.NewId() + "@example.com"),
  1652  		Nickname:  ptrStr(model.NewId()),
  1653  		FirstName: ptrStr(model.NewId()),
  1654  		LastName:  ptrStr(model.NewId()),
  1655  		Position:  ptrStr(model.NewId()),
  1656  	}
  1657  
  1658  	teamMembers, err := th.App.GetTeamMembers(team.Id, 0, 1000)
  1659  	if err != nil {
  1660  		t.Fatalf("Failed to get team member count")
  1661  	}
  1662  	teamMemberCount := len(teamMembers)
  1663  
  1664  	channelMemberCount, err := th.App.GetChannelMemberCount(channel.Id)
  1665  	if err != nil {
  1666  		t.Fatalf("Failed to get channel member count")
  1667  	}
  1668  
  1669  	// Test with an invalid team & channel membership in dry-run mode.
  1670  	data.Teams = &[]UserTeamImportData{
  1671  		{
  1672  			Roles: ptrStr("invalid"),
  1673  			Channels: &[]UserChannelImportData{
  1674  				{
  1675  					Roles: ptrStr("invalid"),
  1676  				},
  1677  			},
  1678  		},
  1679  	}
  1680  	if err := th.App.ImportUser(&data, true); err == nil {
  1681  		t.Fatalf("Should have failed.")
  1682  	}
  1683  
  1684  	// Test with an unknown team name & invalid channel membership in dry-run mode.
  1685  	data.Teams = &[]UserTeamImportData{
  1686  		{
  1687  			Name: ptrStr(model.NewId()),
  1688  			Channels: &[]UserChannelImportData{
  1689  				{
  1690  					Roles: ptrStr("invalid"),
  1691  				},
  1692  			},
  1693  		},
  1694  	}
  1695  	if err := th.App.ImportUser(&data, true); err == nil {
  1696  		t.Fatalf("Should have failed.")
  1697  	}
  1698  
  1699  	// Test with a valid team & invalid channel membership in dry-run mode.
  1700  	data.Teams = &[]UserTeamImportData{
  1701  		{
  1702  			Name: &teamName,
  1703  			Channels: &[]UserChannelImportData{
  1704  				{
  1705  					Roles: ptrStr("invalid"),
  1706  				},
  1707  			},
  1708  		},
  1709  	}
  1710  	if err := th.App.ImportUser(&data, true); err == nil {
  1711  		t.Fatalf("Should have failed.")
  1712  	}
  1713  
  1714  	// Test with a valid team & unknown channel name in dry-run mode.
  1715  	data.Teams = &[]UserTeamImportData{
  1716  		{
  1717  			Name: &teamName,
  1718  			Channels: &[]UserChannelImportData{
  1719  				{
  1720  					Name: ptrStr(model.NewId()),
  1721  				},
  1722  			},
  1723  		},
  1724  	}
  1725  	if err := th.App.ImportUser(&data, true); err != nil {
  1726  		t.Fatalf("Should have succeeded.")
  1727  	}
  1728  
  1729  	// Test with a valid team & valid channel name in dry-run mode.
  1730  	data.Teams = &[]UserTeamImportData{
  1731  		{
  1732  			Name: &teamName,
  1733  			Channels: &[]UserChannelImportData{
  1734  				{
  1735  					Name: &channelName,
  1736  				},
  1737  			},
  1738  		},
  1739  	}
  1740  	if err := th.App.ImportUser(&data, true); err != nil {
  1741  		t.Fatalf("Should have succeeded.")
  1742  	}
  1743  
  1744  	// Check no new member objects were created because dry run mode.
  1745  	if tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000); err != nil {
  1746  		t.Fatalf("Failed to get Team Member Count")
  1747  	} else if len(tmc) != teamMemberCount {
  1748  		t.Fatalf("Number of team members not as expected")
  1749  	}
  1750  
  1751  	if cmc, err := th.App.GetChannelMemberCount(channel.Id); err != nil {
  1752  		t.Fatalf("Failed to get Channel Member Count")
  1753  	} else if cmc != channelMemberCount {
  1754  		t.Fatalf("Number of channel members not as expected")
  1755  	}
  1756  
  1757  	// Test with an invalid team & channel membership in apply mode.
  1758  	data.Teams = &[]UserTeamImportData{
  1759  		{
  1760  			Roles: ptrStr("invalid"),
  1761  			Channels: &[]UserChannelImportData{
  1762  				{
  1763  					Roles: ptrStr("invalid"),
  1764  				},
  1765  			},
  1766  		},
  1767  	}
  1768  	if err := th.App.ImportUser(&data, false); err == nil {
  1769  		t.Fatalf("Should have failed.")
  1770  	}
  1771  
  1772  	// Test with an unknown team name & invalid channel membership in apply mode.
  1773  	data.Teams = &[]UserTeamImportData{
  1774  		{
  1775  			Name: ptrStr(model.NewId()),
  1776  			Channels: &[]UserChannelImportData{
  1777  				{
  1778  					Roles: ptrStr("invalid"),
  1779  				},
  1780  			},
  1781  		},
  1782  	}
  1783  	if err := th.App.ImportUser(&data, false); err == nil {
  1784  		t.Fatalf("Should have failed.")
  1785  	}
  1786  
  1787  	// Test with a valid team & invalid channel membership in apply mode.
  1788  	data.Teams = &[]UserTeamImportData{
  1789  		{
  1790  			Name: &teamName,
  1791  			Channels: &[]UserChannelImportData{
  1792  				{
  1793  					Roles: ptrStr("invalid"),
  1794  				},
  1795  			},
  1796  		},
  1797  	}
  1798  	if err := th.App.ImportUser(&data, false); err == nil {
  1799  		t.Fatalf("Should have failed.")
  1800  	}
  1801  
  1802  	// Check no new member objects were created because all tests should have failed so far.
  1803  	if tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000); err != nil {
  1804  		t.Fatalf("Failed to get Team Member Count")
  1805  	} else if len(tmc) != teamMemberCount {
  1806  		t.Fatalf("Number of team members not as expected")
  1807  	}
  1808  
  1809  	if cmc, err := th.App.GetChannelMemberCount(channel.Id); err != nil {
  1810  		t.Fatalf("Failed to get Channel Member Count")
  1811  	} else if cmc != channelMemberCount {
  1812  		t.Fatalf("Number of channel members not as expected")
  1813  	}
  1814  
  1815  	// Test with a valid team & unknown channel name in apply mode.
  1816  	data.Teams = &[]UserTeamImportData{
  1817  		{
  1818  			Name: &teamName,
  1819  			Channels: &[]UserChannelImportData{
  1820  				{
  1821  					Name: ptrStr(model.NewId()),
  1822  				},
  1823  			},
  1824  		},
  1825  	}
  1826  	if err := th.App.ImportUser(&data, false); err == nil {
  1827  		t.Fatalf("Should have failed.")
  1828  	}
  1829  
  1830  	// Check only new team member object created because dry run mode.
  1831  	if tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000); err != nil {
  1832  		t.Fatalf("Failed to get Team Member Count")
  1833  	} else if len(tmc) != teamMemberCount+1 {
  1834  		t.Fatalf("Number of team members not as expected")
  1835  	}
  1836  
  1837  	if cmc, err := th.App.GetChannelMemberCount(channel.Id); err != nil {
  1838  		t.Fatalf("Failed to get Channel Member Count")
  1839  	} else if cmc != channelMemberCount {
  1840  		t.Fatalf("Number of channel members not as expected")
  1841  	}
  1842  
  1843  	// Check team member properties.
  1844  	user, err := th.App.GetUserByUsername(username)
  1845  	if err != nil {
  1846  		t.Fatalf("Failed to get user from database.")
  1847  	}
  1848  	if teamMember, err := th.App.GetTeamMember(team.Id, user.Id); err != nil {
  1849  		t.Fatalf("Failed to get team member from database.")
  1850  	} else if teamMember.Roles != "team_user" {
  1851  		t.Fatalf("Team member properties not as expected")
  1852  	}
  1853  
  1854  	// Test with a valid team & valid channel name in apply mode.
  1855  	data.Teams = &[]UserTeamImportData{
  1856  		{
  1857  			Name: &teamName,
  1858  			Channels: &[]UserChannelImportData{
  1859  				{
  1860  					Name: &channelName,
  1861  				},
  1862  			},
  1863  		},
  1864  	}
  1865  	if err := th.App.ImportUser(&data, false); err != nil {
  1866  		t.Fatalf("Should have succeeded.")
  1867  	}
  1868  
  1869  	// Check only new channel member object created because dry run mode.
  1870  	if tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000); err != nil {
  1871  		t.Fatalf("Failed to get Team Member Count")
  1872  	} else if len(tmc) != teamMemberCount+1 {
  1873  		t.Fatalf("Number of team members not as expected")
  1874  	}
  1875  
  1876  	if cmc, err := th.App.GetChannelMemberCount(channel.Id); err != nil {
  1877  		t.Fatalf("Failed to get Channel Member Count")
  1878  	} else if cmc != channelMemberCount+1 {
  1879  		t.Fatalf("Number of channel members not as expected")
  1880  	}
  1881  
  1882  	// Check channel member properties.
  1883  	if channelMember, err := th.App.GetChannelMember(channel.Id, user.Id); err != nil {
  1884  		t.Fatalf("Failed to get channel member from database.")
  1885  	} else if channelMember.Roles != "channel_user" || channelMember.NotifyProps[model.DESKTOP_NOTIFY_PROP] != "default" || channelMember.NotifyProps[model.PUSH_NOTIFY_PROP] != "default" || channelMember.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != "all" {
  1886  		t.Fatalf("Channel member properties not as expected")
  1887  	}
  1888  
  1889  	// Test with the properties of the team and channel membership changed.
  1890  	data.Teams = &[]UserTeamImportData{
  1891  		{
  1892  			Name:  &teamName,
  1893  			Roles: ptrStr("team_user team_admin"),
  1894  			Channels: &[]UserChannelImportData{
  1895  				{
  1896  					Name:  &channelName,
  1897  					Roles: ptrStr("channel_user channel_admin"),
  1898  					NotifyProps: &UserChannelNotifyPropsImportData{
  1899  						Desktop:    ptrStr(model.USER_NOTIFY_MENTION),
  1900  						Mobile:     ptrStr(model.USER_NOTIFY_MENTION),
  1901  						MarkUnread: ptrStr(model.USER_NOTIFY_MENTION),
  1902  					},
  1903  					Favorite: ptrBool(true),
  1904  				},
  1905  			},
  1906  		},
  1907  	}
  1908  	if err := th.App.ImportUser(&data, false); err != nil {
  1909  		t.Fatalf("Should have succeeded.")
  1910  	}
  1911  
  1912  	// Check both member properties.
  1913  	if teamMember, err := th.App.GetTeamMember(team.Id, user.Id); err != nil {
  1914  		t.Fatalf("Failed to get team member from database.")
  1915  	} else if teamMember.Roles != "team_user team_admin" {
  1916  		t.Fatalf("Team member properties not as expected: %v", teamMember.Roles)
  1917  	}
  1918  
  1919  	if channelMember, err := th.App.GetChannelMember(channel.Id, user.Id); err != nil {
  1920  		t.Fatalf("Failed to get channel member Desktop from database.")
  1921  	} else if channelMember.Roles != "channel_user channel_admin" || channelMember.NotifyProps[model.DESKTOP_NOTIFY_PROP] != model.USER_NOTIFY_MENTION || channelMember.NotifyProps[model.PUSH_NOTIFY_PROP] != model.USER_NOTIFY_MENTION || channelMember.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.USER_NOTIFY_MENTION {
  1922  		t.Fatalf("Channel member properties not as expected")
  1923  	}
  1924  
  1925  	checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL, channel.Id, "true")
  1926  
  1927  	// No more new member objects.
  1928  	if tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000); err != nil {
  1929  		t.Fatalf("Failed to get Team Member Count")
  1930  	} else if len(tmc) != teamMemberCount+1 {
  1931  		t.Fatalf("Number of team members not as expected")
  1932  	}
  1933  
  1934  	if cmc, err := th.App.GetChannelMemberCount(channel.Id); err != nil {
  1935  		t.Fatalf("Failed to get Channel Member Count")
  1936  	} else if cmc != channelMemberCount+1 {
  1937  		t.Fatalf("Number of channel members not as expected")
  1938  	}
  1939  
  1940  	// Add a user with some preferences.
  1941  	username = model.NewId()
  1942  	data = UserImportData{
  1943  		Username:           &username,
  1944  		Email:              ptrStr(model.NewId() + "@example.com"),
  1945  		Theme:              ptrStr(`{"awayIndicator":"#DCBD4E","buttonBg":"#23A2FF","buttonColor":"#FFFFFF","centerChannelBg":"#ffffff","centerChannelColor":"#333333","codeTheme":"github","image":"/static/files/a4a388b38b32678e83823ef1b3e17766.png","linkColor":"#2389d7","mentionBj":"#2389d7","mentionColor":"#ffffff","mentionHighlightBg":"#fff2bb","mentionHighlightLink":"#2f81b7","newMessageSeparator":"#FF8800","onlineIndicator":"#7DBE00","sidebarBg":"#fafafa","sidebarHeaderBg":"#3481B9","sidebarHeaderTextColor":"#ffffff","sidebarText":"#333333","sidebarTextActiveBorder":"#378FD2","sidebarTextActiveColor":"#111111","sidebarTextHoverBg":"#e6f2fa","sidebarUnreadText":"#333333","type":"Mattermost"}`),
  1946  		UseMilitaryTime:    ptrStr("true"),
  1947  		CollapsePreviews:   ptrStr("true"),
  1948  		MessageDisplay:     ptrStr("compact"),
  1949  		ChannelDisplayMode: ptrStr("centered"),
  1950  		TutorialStep:       ptrStr("3"),
  1951  	}
  1952  	if err := th.App.ImportUser(&data, false); err != nil {
  1953  		t.Fatalf("Should have succeeded.")
  1954  	}
  1955  
  1956  	// Check their values.
  1957  	user, err = th.App.GetUserByUsername(username)
  1958  	if err != nil {
  1959  		t.Fatalf("Failed to get user from database.")
  1960  	}
  1961  
  1962  	checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_THEME, "", *data.Theme)
  1963  	checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "use_military_time", *data.UseMilitaryTime)
  1964  	checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "collapse_previews", *data.CollapsePreviews)
  1965  	checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "message_display", *data.MessageDisplay)
  1966  	checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "channel_display_mode", *data.ChannelDisplayMode)
  1967  	checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_TUTORIAL_STEPS, user.Id, *data.TutorialStep)
  1968  
  1969  	// Change those preferences.
  1970  	data = UserImportData{
  1971  		Username:           &username,
  1972  		Email:              ptrStr(model.NewId() + "@example.com"),
  1973  		Theme:              ptrStr(`{"awayIndicator":"#123456","buttonBg":"#23A2FF","buttonColor":"#FFFFFF","centerChannelBg":"#ffffff","centerChannelColor":"#333333","codeTheme":"github","image":"/static/files/a4a388b38b32678e83823ef1b3e17766.png","linkColor":"#2389d7","mentionBj":"#2389d7","mentionColor":"#ffffff","mentionHighlightBg":"#fff2bb","mentionHighlightLink":"#2f81b7","newMessageSeparator":"#FF8800","onlineIndicator":"#7DBE00","sidebarBg":"#fafafa","sidebarHeaderBg":"#3481B9","sidebarHeaderTextColor":"#ffffff","sidebarText":"#333333","sidebarTextActiveBorder":"#378FD2","sidebarTextActiveColor":"#111111","sidebarTextHoverBg":"#e6f2fa","sidebarUnreadText":"#333333","type":"Mattermost"}`),
  1974  		UseMilitaryTime:    ptrStr("false"),
  1975  		CollapsePreviews:   ptrStr("false"),
  1976  		MessageDisplay:     ptrStr("clean"),
  1977  		ChannelDisplayMode: ptrStr("full"),
  1978  		TutorialStep:       ptrStr("2"),
  1979  	}
  1980  	if err := th.App.ImportUser(&data, false); err != nil {
  1981  		t.Fatalf("Should have succeeded.")
  1982  	}
  1983  
  1984  	// Check their values again.
  1985  	checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_THEME, "", *data.Theme)
  1986  	checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "use_military_time", *data.UseMilitaryTime)
  1987  	checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "collapse_previews", *data.CollapsePreviews)
  1988  	checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "message_display", *data.MessageDisplay)
  1989  	checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "channel_display_mode", *data.ChannelDisplayMode)
  1990  	checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_TUTORIAL_STEPS, user.Id, *data.TutorialStep)
  1991  
  1992  	// Set Notify Props
  1993  	data.NotifyProps = &UserNotifyPropsImportData{
  1994  		Desktop:          ptrStr(model.USER_NOTIFY_ALL),
  1995  		DesktopDuration:  ptrStr("5"),
  1996  		DesktopSound:     ptrStr("true"),
  1997  		Email:            ptrStr("true"),
  1998  		Mobile:           ptrStr(model.USER_NOTIFY_ALL),
  1999  		MobilePushStatus: ptrStr(model.STATUS_ONLINE),
  2000  		ChannelTrigger:   ptrStr("true"),
  2001  		CommentsTrigger:  ptrStr(model.COMMENTS_NOTIFY_ROOT),
  2002  		MentionKeys:      ptrStr("valid,misc"),
  2003  	}
  2004  	if err := th.App.ImportUser(&data, false); err != nil {
  2005  		t.Fatalf("Should have succeeded.")
  2006  	}
  2007  
  2008  	user, err = th.App.GetUserByUsername(username)
  2009  	if err != nil {
  2010  		t.Fatalf("Failed to get user from database.")
  2011  	}
  2012  
  2013  	checkNotifyProp(t, user, model.DESKTOP_NOTIFY_PROP, model.USER_NOTIFY_ALL)
  2014  	checkNotifyProp(t, user, model.DESKTOP_DURATION_NOTIFY_PROP, "5")
  2015  	checkNotifyProp(t, user, model.DESKTOP_SOUND_NOTIFY_PROP, "true")
  2016  	checkNotifyProp(t, user, model.EMAIL_NOTIFY_PROP, "true")
  2017  	checkNotifyProp(t, user, model.PUSH_NOTIFY_PROP, model.USER_NOTIFY_ALL)
  2018  	checkNotifyProp(t, user, model.PUSH_STATUS_NOTIFY_PROP, model.STATUS_ONLINE)
  2019  	checkNotifyProp(t, user, model.CHANNEL_MENTIONS_NOTIFY_PROP, "true")
  2020  	checkNotifyProp(t, user, model.COMMENTS_NOTIFY_PROP, model.COMMENTS_NOTIFY_ROOT)
  2021  	checkNotifyProp(t, user, model.MENTION_KEYS_NOTIFY_PROP, "valid,misc")
  2022  
  2023  	// Change Notify Props
  2024  	data.NotifyProps = &UserNotifyPropsImportData{
  2025  		Desktop:          ptrStr(model.USER_NOTIFY_MENTION),
  2026  		DesktopDuration:  ptrStr("3"),
  2027  		DesktopSound:     ptrStr("false"),
  2028  		Email:            ptrStr("false"),
  2029  		Mobile:           ptrStr(model.USER_NOTIFY_NONE),
  2030  		MobilePushStatus: ptrStr(model.STATUS_AWAY),
  2031  		ChannelTrigger:   ptrStr("false"),
  2032  		CommentsTrigger:  ptrStr(model.COMMENTS_NOTIFY_ANY),
  2033  		MentionKeys:      ptrStr("misc"),
  2034  	}
  2035  	if err := th.App.ImportUser(&data, false); err != nil {
  2036  		t.Fatalf("Should have succeeded.")
  2037  	}
  2038  
  2039  	user, err = th.App.GetUserByUsername(username)
  2040  	if err != nil {
  2041  		t.Fatalf("Failed to get user from database.")
  2042  	}
  2043  
  2044  	checkNotifyProp(t, user, model.DESKTOP_NOTIFY_PROP, model.USER_NOTIFY_MENTION)
  2045  	checkNotifyProp(t, user, model.DESKTOP_DURATION_NOTIFY_PROP, "3")
  2046  	checkNotifyProp(t, user, model.DESKTOP_SOUND_NOTIFY_PROP, "false")
  2047  	checkNotifyProp(t, user, model.EMAIL_NOTIFY_PROP, "false")
  2048  	checkNotifyProp(t, user, model.PUSH_NOTIFY_PROP, model.USER_NOTIFY_NONE)
  2049  	checkNotifyProp(t, user, model.PUSH_STATUS_NOTIFY_PROP, model.STATUS_AWAY)
  2050  	checkNotifyProp(t, user, model.CHANNEL_MENTIONS_NOTIFY_PROP, "false")
  2051  	checkNotifyProp(t, user, model.COMMENTS_NOTIFY_PROP, model.COMMENTS_NOTIFY_ANY)
  2052  	checkNotifyProp(t, user, model.MENTION_KEYS_NOTIFY_PROP, "misc")
  2053  
  2054  	// Check Notify Props get set on *create* user.
  2055  	username = model.NewId()
  2056  	data = UserImportData{
  2057  		Username: &username,
  2058  		Email:    ptrStr(model.NewId() + "@example.com"),
  2059  	}
  2060  	data.NotifyProps = &UserNotifyPropsImportData{
  2061  		Desktop:          ptrStr(model.USER_NOTIFY_MENTION),
  2062  		DesktopDuration:  ptrStr("3"),
  2063  		DesktopSound:     ptrStr("false"),
  2064  		Email:            ptrStr("false"),
  2065  		Mobile:           ptrStr(model.USER_NOTIFY_NONE),
  2066  		MobilePushStatus: ptrStr(model.STATUS_AWAY),
  2067  		ChannelTrigger:   ptrStr("false"),
  2068  		CommentsTrigger:  ptrStr(model.COMMENTS_NOTIFY_ANY),
  2069  		MentionKeys:      ptrStr("misc"),
  2070  	}
  2071  
  2072  	if err := th.App.ImportUser(&data, false); err != nil {
  2073  		t.Fatalf("Should have succeeded.")
  2074  	}
  2075  
  2076  	user, err = th.App.GetUserByUsername(username)
  2077  	if err != nil {
  2078  		t.Fatalf("Failed to get user from database.")
  2079  	}
  2080  
  2081  	checkNotifyProp(t, user, model.DESKTOP_NOTIFY_PROP, model.USER_NOTIFY_MENTION)
  2082  	checkNotifyProp(t, user, model.DESKTOP_DURATION_NOTIFY_PROP, "3")
  2083  	checkNotifyProp(t, user, model.DESKTOP_SOUND_NOTIFY_PROP, "false")
  2084  	checkNotifyProp(t, user, model.EMAIL_NOTIFY_PROP, "false")
  2085  	checkNotifyProp(t, user, model.PUSH_NOTIFY_PROP, model.USER_NOTIFY_NONE)
  2086  	checkNotifyProp(t, user, model.PUSH_STATUS_NOTIFY_PROP, model.STATUS_AWAY)
  2087  	checkNotifyProp(t, user, model.CHANNEL_MENTIONS_NOTIFY_PROP, "false")
  2088  	checkNotifyProp(t, user, model.COMMENTS_NOTIFY_PROP, model.COMMENTS_NOTIFY_ANY)
  2089  	checkNotifyProp(t, user, model.MENTION_KEYS_NOTIFY_PROP, "misc")
  2090  }
  2091  
  2092  func AssertAllPostsCount(t *testing.T, a *App, initialCount int64, change int64, teamName string) {
  2093  	if result := <-a.Srv.Store.Post().AnalyticsPostCount(teamName, false, false); result.Err != nil {
  2094  		t.Fatal(result.Err)
  2095  	} else {
  2096  		if initialCount+change != result.Data.(int64) {
  2097  			debug.PrintStack()
  2098  			t.Fatalf("Did not find the expected number of posts.")
  2099  		}
  2100  	}
  2101  }
  2102  
  2103  func TestImportImportPost(t *testing.T) {
  2104  	th := Setup()
  2105  	defer th.TearDown()
  2106  
  2107  	// Create a Team.
  2108  	teamName := model.NewId()
  2109  	th.App.ImportTeam(&TeamImportData{
  2110  		Name:        &teamName,
  2111  		DisplayName: ptrStr("Display Name"),
  2112  		Type:        ptrStr("O"),
  2113  	}, false)
  2114  	team, err := th.App.GetTeamByName(teamName)
  2115  	if err != nil {
  2116  		t.Fatalf("Failed to get team from database.")
  2117  	}
  2118  
  2119  	// Create a Channel.
  2120  	channelName := model.NewId()
  2121  	th.App.ImportChannel(&ChannelImportData{
  2122  		Team:        &teamName,
  2123  		Name:        &channelName,
  2124  		DisplayName: ptrStr("Display Name"),
  2125  		Type:        ptrStr("O"),
  2126  	}, false)
  2127  	channel, err := th.App.GetChannelByName(channelName, team.Id)
  2128  	if err != nil {
  2129  		t.Fatalf("Failed to get channel from database.")
  2130  	}
  2131  
  2132  	// Create a user.
  2133  	username := model.NewId()
  2134  	th.App.ImportUser(&UserImportData{
  2135  		Username: &username,
  2136  		Email:    ptrStr(model.NewId() + "@example.com"),
  2137  	}, false)
  2138  	user, err := th.App.GetUserByUsername(username)
  2139  	if err != nil {
  2140  		t.Fatalf("Failed to get user from database.")
  2141  	}
  2142  
  2143  	// Count the number of posts in the testing team.
  2144  	var initialPostCount int64
  2145  	if result := <-th.App.Srv.Store.Post().AnalyticsPostCount(team.Id, false, false); result.Err != nil {
  2146  		t.Fatal(result.Err)
  2147  	} else {
  2148  		initialPostCount = result.Data.(int64)
  2149  	}
  2150  
  2151  	// Try adding an invalid post in dry run mode.
  2152  	data := &PostImportData{
  2153  		Team:    &teamName,
  2154  		Channel: &channelName,
  2155  		User:    &username,
  2156  	}
  2157  	if err := th.App.ImportPost(data, true); err == nil {
  2158  		t.Fatalf("Expected error.")
  2159  	}
  2160  	AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
  2161  
  2162  	// Try adding a valid post in dry run mode.
  2163  	data = &PostImportData{
  2164  		Team:     &teamName,
  2165  		Channel:  &channelName,
  2166  		User:     &username,
  2167  		Message:  ptrStr("Hello"),
  2168  		CreateAt: ptrInt64(model.GetMillis()),
  2169  	}
  2170  	if err := th.App.ImportPost(data, true); err != nil {
  2171  		t.Fatalf("Expected success.")
  2172  	}
  2173  	AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
  2174  
  2175  	// Try adding an invalid post in apply mode.
  2176  	data = &PostImportData{
  2177  		Team:     &teamName,
  2178  		Channel:  &channelName,
  2179  		User:     &username,
  2180  		CreateAt: ptrInt64(model.GetMillis()),
  2181  	}
  2182  	if err := th.App.ImportPost(data, false); err == nil {
  2183  		t.Fatalf("Expected error.")
  2184  	}
  2185  	AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
  2186  
  2187  	// Try adding a valid post with invalid team in apply mode.
  2188  	data = &PostImportData{
  2189  		Team:     ptrStr(model.NewId()),
  2190  		Channel:  &channelName,
  2191  		User:     &username,
  2192  		Message:  ptrStr("Message"),
  2193  		CreateAt: ptrInt64(model.GetMillis()),
  2194  	}
  2195  	if err := th.App.ImportPost(data, false); err == nil {
  2196  		t.Fatalf("Expected error.")
  2197  	}
  2198  	AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
  2199  
  2200  	// Try adding a valid post with invalid channel in apply mode.
  2201  	data = &PostImportData{
  2202  		Team:     &teamName,
  2203  		Channel:  ptrStr(model.NewId()),
  2204  		User:     &username,
  2205  		Message:  ptrStr("Message"),
  2206  		CreateAt: ptrInt64(model.GetMillis()),
  2207  	}
  2208  	if err := th.App.ImportPost(data, false); err == nil {
  2209  		t.Fatalf("Expected error.")
  2210  	}
  2211  	AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
  2212  
  2213  	// Try adding a valid post with invalid user in apply mode.
  2214  	data = &PostImportData{
  2215  		Team:     &teamName,
  2216  		Channel:  &channelName,
  2217  		User:     ptrStr(model.NewId()),
  2218  		Message:  ptrStr("Message"),
  2219  		CreateAt: ptrInt64(model.GetMillis()),
  2220  	}
  2221  	if err := th.App.ImportPost(data, false); err == nil {
  2222  		t.Fatalf("Expected error.")
  2223  	}
  2224  	AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
  2225  
  2226  	// Try adding a valid post in apply mode.
  2227  	time := model.GetMillis()
  2228  	data = &PostImportData{
  2229  		Team:     &teamName,
  2230  		Channel:  &channelName,
  2231  		User:     &username,
  2232  		Message:  ptrStr("Message"),
  2233  		CreateAt: &time,
  2234  	}
  2235  	if err := th.App.ImportPost(data, false); err != nil {
  2236  		t.Fatalf("Expected success.")
  2237  	}
  2238  	AssertAllPostsCount(t, th.App, initialPostCount, 1, team.Id)
  2239  
  2240  	// Check the post values.
  2241  	if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, time); result.Err != nil {
  2242  		t.Fatal(result.Err.Error())
  2243  	} else {
  2244  		posts := result.Data.([]*model.Post)
  2245  		if len(posts) != 1 {
  2246  			t.Fatal("Unexpected number of posts found.")
  2247  		}
  2248  		post := posts[0]
  2249  		if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id {
  2250  			t.Fatal("Post properties not as expected")
  2251  		}
  2252  	}
  2253  
  2254  	// Update the post.
  2255  	data = &PostImportData{
  2256  		Team:     &teamName,
  2257  		Channel:  &channelName,
  2258  		User:     &username,
  2259  		Message:  ptrStr("Message"),
  2260  		CreateAt: &time,
  2261  	}
  2262  	if err := th.App.ImportPost(data, false); err != nil {
  2263  		t.Fatalf("Expected success.")
  2264  	}
  2265  	AssertAllPostsCount(t, th.App, initialPostCount, 1, team.Id)
  2266  
  2267  	// Check the post values.
  2268  	if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, time); result.Err != nil {
  2269  		t.Fatal(result.Err.Error())
  2270  	} else {
  2271  		posts := result.Data.([]*model.Post)
  2272  		if len(posts) != 1 {
  2273  			t.Fatal("Unexpected number of posts found.")
  2274  		}
  2275  		post := posts[0]
  2276  		if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id {
  2277  			t.Fatal("Post properties not as expected")
  2278  		}
  2279  	}
  2280  
  2281  	// Save the post with a different time.
  2282  	newTime := time + 1
  2283  	data = &PostImportData{
  2284  		Team:     &teamName,
  2285  		Channel:  &channelName,
  2286  		User:     &username,
  2287  		Message:  ptrStr("Message"),
  2288  		CreateAt: &newTime,
  2289  	}
  2290  	if err := th.App.ImportPost(data, false); err != nil {
  2291  		t.Fatalf("Expected success.")
  2292  	}
  2293  	AssertAllPostsCount(t, th.App, initialPostCount, 2, team.Id)
  2294  
  2295  	// Save the post with a different message.
  2296  	data = &PostImportData{
  2297  		Team:     &teamName,
  2298  		Channel:  &channelName,
  2299  		User:     &username,
  2300  		Message:  ptrStr("Message 2"),
  2301  		CreateAt: &time,
  2302  	}
  2303  	if err := th.App.ImportPost(data, false); err != nil {
  2304  		t.Fatalf("Expected success.")
  2305  	}
  2306  	AssertAllPostsCount(t, th.App, initialPostCount, 3, team.Id)
  2307  
  2308  	// Test with hashtags
  2309  	hashtagTime := time + 2
  2310  	data = &PostImportData{
  2311  		Team:     &teamName,
  2312  		Channel:  &channelName,
  2313  		User:     &username,
  2314  		Message:  ptrStr("Message 2 #hashtagmashupcity"),
  2315  		CreateAt: &hashtagTime,
  2316  	}
  2317  	if err := th.App.ImportPost(data, false); err != nil {
  2318  		t.Fatalf("Expected success.")
  2319  	}
  2320  	AssertAllPostsCount(t, th.App, initialPostCount, 4, team.Id)
  2321  
  2322  	if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, hashtagTime); result.Err != nil {
  2323  		t.Fatal(result.Err.Error())
  2324  	} else {
  2325  		posts := result.Data.([]*model.Post)
  2326  		if len(posts) != 1 {
  2327  			t.Fatal("Unexpected number of posts found.")
  2328  		}
  2329  		post := posts[0]
  2330  		if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id {
  2331  			t.Fatal("Post properties not as expected")
  2332  		}
  2333  		if post.Hashtags != "#hashtagmashupcity" {
  2334  			t.Fatalf("Hashtags not as expected: %s", post.Hashtags)
  2335  		}
  2336  	}
  2337  
  2338  	// Post with flags.
  2339  	username2 := model.NewId()
  2340  	th.App.ImportUser(&UserImportData{
  2341  		Username: &username2,
  2342  		Email:    ptrStr(model.NewId() + "@example.com"),
  2343  	}, false)
  2344  	user2, err := th.App.GetUserByUsername(username2)
  2345  	if err != nil {
  2346  		t.Fatalf("Failed to get user from database.")
  2347  	}
  2348  
  2349  	flagsTime := hashtagTime + 1
  2350  	data = &PostImportData{
  2351  		Team:     &teamName,
  2352  		Channel:  &channelName,
  2353  		User:     &username,
  2354  		Message:  ptrStr("Message with Favorites"),
  2355  		CreateAt: &flagsTime,
  2356  		FlaggedBy: &[]string{
  2357  			username,
  2358  			username2,
  2359  		},
  2360  	}
  2361  	if err := th.App.ImportPost(data, false); err != nil {
  2362  		t.Fatalf("Expected success.")
  2363  	}
  2364  	AssertAllPostsCount(t, th.App, initialPostCount, 5, team.Id)
  2365  
  2366  	// Check the post values.
  2367  	if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, flagsTime); result.Err != nil {
  2368  		t.Fatal(result.Err.Error())
  2369  	} else {
  2370  		posts := result.Data.([]*model.Post)
  2371  		if len(posts) != 1 {
  2372  			t.Fatal("Unexpected number of posts found.")
  2373  		}
  2374  		post := posts[0]
  2375  		if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id {
  2376  			t.Fatal("Post properties not as expected")
  2377  		}
  2378  
  2379  		checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
  2380  		checkPreference(t, th.App, user2.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
  2381  	}
  2382  
  2383  	// Post with reaction.
  2384  	reactionPostTime := hashtagTime + 2
  2385  	reactionTime := hashtagTime + 3
  2386  	data = &PostImportData{
  2387  		Team:     &teamName,
  2388  		Channel:  &channelName,
  2389  		User:     &username,
  2390  		Message:  ptrStr("Message with reaction"),
  2391  		CreateAt: &reactionPostTime,
  2392  		Reactions: &[]ReactionImportData{{
  2393  			User:      &user2.Username,
  2394  			EmojiName: ptrStr("+1"),
  2395  			CreateAt:  &reactionTime,
  2396  		}},
  2397  	}
  2398  	if err := th.App.ImportPost(data, false); err != nil {
  2399  		t.Fatalf("Expected success.")
  2400  	}
  2401  	AssertAllPostsCount(t, th.App, initialPostCount, 6, team.Id)
  2402  
  2403  	// Check the post values.
  2404  	if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, reactionPostTime); result.Err != nil {
  2405  		t.Fatal(result.Err.Error())
  2406  	} else {
  2407  		posts := result.Data.([]*model.Post)
  2408  		if len(posts) != 1 {
  2409  			t.Fatal("Unexpected number of posts found.")
  2410  		}
  2411  		post := posts[0]
  2412  		if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id || !post.HasReactions {
  2413  			t.Fatal("Post properties not as expected")
  2414  		}
  2415  
  2416  		if result := <-th.App.Srv.Store.Reaction().GetForPost(post.Id, false); result.Err != nil {
  2417  			t.Fatal("Can't get reaction")
  2418  		} else if len(result.Data.([]*model.Reaction)) != 1 {
  2419  			t.Fatal("Invalid number of reactions")
  2420  		}
  2421  	}
  2422  
  2423  	// Post with reply.
  2424  	replyPostTime := hashtagTime + 4
  2425  	replyTime := hashtagTime + 5
  2426  	data = &PostImportData{
  2427  		Team:     &teamName,
  2428  		Channel:  &channelName,
  2429  		User:     &username,
  2430  		Message:  ptrStr("Message with reply"),
  2431  		CreateAt: &replyPostTime,
  2432  		Replies: &[]ReplyImportData{{
  2433  			User:     &user2.Username,
  2434  			Message:  ptrStr("Message reply"),
  2435  			CreateAt: &replyTime,
  2436  		}},
  2437  	}
  2438  	if err := th.App.ImportPost(data, false); err != nil {
  2439  		t.Fatalf("Expected success.")
  2440  	}
  2441  	AssertAllPostsCount(t, th.App, initialPostCount, 8, team.Id)
  2442  
  2443  	// Check the post values.
  2444  	if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, replyPostTime); result.Err != nil {
  2445  		t.Fatal(result.Err.Error())
  2446  	} else {
  2447  		posts := result.Data.([]*model.Post)
  2448  		if len(posts) != 1 {
  2449  			t.Fatal("Unexpected number of posts found.")
  2450  		}
  2451  		post := posts[0]
  2452  		if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != user.Id {
  2453  			t.Fatal("Post properties not as expected")
  2454  		}
  2455  
  2456  		// Check the reply values.
  2457  		if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(channel.Id, replyTime); result.Err != nil {
  2458  			t.Fatal(result.Err.Error())
  2459  		} else {
  2460  			replies := result.Data.([]*model.Post)
  2461  			if len(replies) != 1 {
  2462  				t.Fatal("Unexpected number of posts found.")
  2463  			}
  2464  			reply := replies[0]
  2465  			if reply.Message != *(*data.Replies)[0].Message || reply.CreateAt != *(*data.Replies)[0].CreateAt || reply.UserId != user2.Id {
  2466  				t.Fatal("Post properties not as expected")
  2467  			}
  2468  
  2469  			if reply.RootId != post.Id {
  2470  				t.Fatal("Unexpected reply RootId")
  2471  			}
  2472  		}
  2473  	}
  2474  }
  2475  
  2476  func TestImportImportDirectChannel(t *testing.T) {
  2477  	th := Setup().InitBasic()
  2478  	defer th.TearDown()
  2479  
  2480  	// Check how many channels are in the database.
  2481  	var directChannelCount int64
  2482  	if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_DIRECT); r.Err == nil {
  2483  		directChannelCount = r.Data.(int64)
  2484  	} else {
  2485  		t.Fatalf("Failed to get direct channel count.")
  2486  	}
  2487  
  2488  	var groupChannelCount int64
  2489  	if r := <-th.App.Srv.Store.Channel().AnalyticsTypeCount("", model.CHANNEL_GROUP); r.Err == nil {
  2490  		groupChannelCount = r.Data.(int64)
  2491  	} else {
  2492  		t.Fatalf("Failed to get group channel count.")
  2493  	}
  2494  
  2495  	// Do an invalid channel in dry-run mode.
  2496  	data := DirectChannelImportData{
  2497  		Members: &[]string{
  2498  			model.NewId(),
  2499  		},
  2500  		Header: ptrStr("Channel Header"),
  2501  	}
  2502  	if err := th.App.ImportDirectChannel(&data, true); err == nil {
  2503  		t.Fatalf("Expected error due to invalid name.")
  2504  	}
  2505  
  2506  	// Check that no more channels are in the DB.
  2507  	AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount)
  2508  	AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
  2509  
  2510  	// Do a valid DIRECT channel with a nonexistent member in dry-run mode.
  2511  	data.Members = &[]string{
  2512  		model.NewId(),
  2513  		model.NewId(),
  2514  	}
  2515  	if err := th.App.ImportDirectChannel(&data, true); err != nil {
  2516  		t.Fatalf("Expected success as cannot validate existance of channel members in dry run mode.")
  2517  	}
  2518  
  2519  	// Check that no more channels are in the DB.
  2520  	AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount)
  2521  	AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
  2522  
  2523  	// Do a valid GROUP channel with a nonexistent member in dry-run mode.
  2524  	data.Members = &[]string{
  2525  		model.NewId(),
  2526  		model.NewId(),
  2527  		model.NewId(),
  2528  	}
  2529  	if err := th.App.ImportDirectChannel(&data, true); err != nil {
  2530  		t.Fatalf("Expected success as cannot validate existance of channel members in dry run mode.")
  2531  	}
  2532  
  2533  	// Check that no more channels are in the DB.
  2534  	AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount)
  2535  	AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
  2536  
  2537  	// Do an invalid channel in apply mode.
  2538  	data.Members = &[]string{
  2539  		model.NewId(),
  2540  	}
  2541  	if err := th.App.ImportDirectChannel(&data, false); err == nil {
  2542  		t.Fatalf("Expected error due to invalid member (apply mode).")
  2543  	}
  2544  
  2545  	// Check that no more channels are in the DB.
  2546  	AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount)
  2547  	AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
  2548  
  2549  	// Do a valid DIRECT channel.
  2550  	data.Members = &[]string{
  2551  		th.BasicUser.Username,
  2552  		th.BasicUser2.Username,
  2553  	}
  2554  	if err := th.App.ImportDirectChannel(&data, false); err != nil {
  2555  		t.Fatalf("Expected success: %v", err.Error())
  2556  	}
  2557  
  2558  	// Check that one more DIRECT channel is in the DB.
  2559  	AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
  2560  	AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
  2561  
  2562  	// Do the same DIRECT channel again.
  2563  	if err := th.App.ImportDirectChannel(&data, false); err != nil {
  2564  		t.Fatalf("Expected success.")
  2565  	}
  2566  
  2567  	// Check that no more channels are in the DB.
  2568  	AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
  2569  	AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
  2570  
  2571  	// Update the channel's HEADER
  2572  	data.Header = ptrStr("New Channel Header 2")
  2573  	if err := th.App.ImportDirectChannel(&data, false); err != nil {
  2574  		t.Fatalf("Expected success.")
  2575  	}
  2576  
  2577  	// Check that no more channels are in the DB.
  2578  	AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
  2579  	AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
  2580  
  2581  	// Get the channel to check that the header was updated.
  2582  	if channel, err := th.App.createDirectChannel(th.BasicUser.Id, th.BasicUser2.Id); err == nil || err.Id != store.CHANNEL_EXISTS_ERROR {
  2583  		t.Fatal("Should have got store.CHANNEL_EXISTS_ERROR")
  2584  	} else {
  2585  		if channel.Header != *data.Header {
  2586  			t.Fatal("Channel header has not been updated successfully.")
  2587  		}
  2588  	}
  2589  
  2590  	// Do a GROUP channel with an extra invalid member.
  2591  	user3 := th.CreateUser()
  2592  	data.Members = &[]string{
  2593  		th.BasicUser.Username,
  2594  		th.BasicUser2.Username,
  2595  		user3.Username,
  2596  		model.NewId(),
  2597  	}
  2598  	if err := th.App.ImportDirectChannel(&data, false); err == nil {
  2599  		t.Fatalf("Should have failed due to invalid member in list.")
  2600  	}
  2601  
  2602  	// Check that no more channels are in the DB.
  2603  	AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
  2604  	AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount)
  2605  
  2606  	// Do a valid GROUP channel.
  2607  	data.Members = &[]string{
  2608  		th.BasicUser.Username,
  2609  		th.BasicUser2.Username,
  2610  		user3.Username,
  2611  	}
  2612  	if err := th.App.ImportDirectChannel(&data, false); err != nil {
  2613  		t.Fatalf("Expected success.")
  2614  	}
  2615  
  2616  	// Check that one more GROUP channel is in the DB.
  2617  	AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
  2618  	AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount+1)
  2619  
  2620  	// Do the same DIRECT channel again.
  2621  	if err := th.App.ImportDirectChannel(&data, false); err != nil {
  2622  		t.Fatalf("Expected success.")
  2623  	}
  2624  
  2625  	// Check that no more channels are in the DB.
  2626  	AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
  2627  	AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount+1)
  2628  
  2629  	// Update the channel's HEADER
  2630  	data.Header = ptrStr("New Channel Header 3")
  2631  	if err := th.App.ImportDirectChannel(&data, false); err != nil {
  2632  		t.Fatalf("Expected success.")
  2633  	}
  2634  
  2635  	// Check that no more channels are in the DB.
  2636  	AssertChannelCount(t, th.App, model.CHANNEL_DIRECT, directChannelCount+1)
  2637  	AssertChannelCount(t, th.App, model.CHANNEL_GROUP, groupChannelCount+1)
  2638  
  2639  	// Get the channel to check that the header was updated.
  2640  	userIds := []string{
  2641  		th.BasicUser.Id,
  2642  		th.BasicUser2.Id,
  2643  		user3.Id,
  2644  	}
  2645  	if channel, err := th.App.createGroupChannel(userIds, th.BasicUser.Id); err.Id != store.CHANNEL_EXISTS_ERROR {
  2646  		t.Fatal("Should have got store.CHANNEL_EXISTS_ERROR")
  2647  	} else {
  2648  		if channel.Header != *data.Header {
  2649  			t.Fatal("Channel header has not been updated successfully.")
  2650  		}
  2651  	}
  2652  
  2653  	// Import a channel with some favorites.
  2654  	data.Members = &[]string{
  2655  		th.BasicUser.Username,
  2656  		th.BasicUser2.Username,
  2657  	}
  2658  	data.FavoritedBy = &[]string{
  2659  		th.BasicUser.Username,
  2660  		th.BasicUser2.Username,
  2661  	}
  2662  	if err := th.App.ImportDirectChannel(&data, false); err != nil {
  2663  		t.Fatal(err)
  2664  	}
  2665  
  2666  	if channel, err := th.App.createDirectChannel(th.BasicUser.Id, th.BasicUser2.Id); err == nil || err.Id != store.CHANNEL_EXISTS_ERROR {
  2667  		t.Fatal("Should have got store.CHANNEL_EXISTS_ERROR")
  2668  	} else {
  2669  		checkPreference(t, th.App, th.BasicUser.Id, model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL, channel.Id, "true")
  2670  		checkPreference(t, th.App, th.BasicUser2.Id, model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL, channel.Id, "true")
  2671  	}
  2672  }
  2673  
  2674  func AssertChannelCount(t *testing.T, a *App, channelType string, expectedCount int64) {
  2675  	if r := <-a.Srv.Store.Channel().AnalyticsTypeCount("", channelType); r.Err == nil {
  2676  		count := r.Data.(int64)
  2677  		if count != expectedCount {
  2678  			debug.PrintStack()
  2679  			t.Fatalf("Channel count of type: %v. Expected: %v, Got: %v", channelType, expectedCount, count)
  2680  		}
  2681  	} else {
  2682  		debug.PrintStack()
  2683  		t.Fatalf("Failed to get channel count.")
  2684  	}
  2685  }
  2686  
  2687  func TestImportImportDirectPost(t *testing.T) {
  2688  	th := Setup().InitBasic()
  2689  	defer th.TearDown()
  2690  
  2691  	// Create the DIRECT channel.
  2692  	channelData := DirectChannelImportData{
  2693  		Members: &[]string{
  2694  			th.BasicUser.Username,
  2695  			th.BasicUser2.Username,
  2696  		},
  2697  	}
  2698  	if err := th.App.ImportDirectChannel(&channelData, false); err != nil {
  2699  		t.Fatalf("Expected success: %v", err.Error())
  2700  	}
  2701  
  2702  	// Get the channel.
  2703  	var directChannel *model.Channel
  2704  	if channel, err := th.App.createDirectChannel(th.BasicUser.Id, th.BasicUser2.Id); err.Id != store.CHANNEL_EXISTS_ERROR {
  2705  		t.Fatal("Should have got store.CHANNEL_EXISTS_ERROR")
  2706  	} else {
  2707  		directChannel = channel
  2708  	}
  2709  
  2710  	// Get the number of posts in the system.
  2711  	var initialPostCount int64
  2712  	if result := <-th.App.Srv.Store.Post().AnalyticsPostCount("", false, false); result.Err != nil {
  2713  		t.Fatal(result.Err)
  2714  	} else {
  2715  		initialPostCount = result.Data.(int64)
  2716  	}
  2717  
  2718  	// Try adding an invalid post in dry run mode.
  2719  	data := &DirectPostImportData{
  2720  		ChannelMembers: &[]string{
  2721  			th.BasicUser.Username,
  2722  			th.BasicUser2.Username,
  2723  		},
  2724  		User:     ptrStr(th.BasicUser.Username),
  2725  		CreateAt: ptrInt64(model.GetMillis()),
  2726  	}
  2727  	if err := th.App.ImportDirectPost(data, true); err == nil {
  2728  		t.Fatalf("Expected error.")
  2729  	}
  2730  	AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
  2731  
  2732  	// Try adding a valid post in dry run mode.
  2733  	data = &DirectPostImportData{
  2734  		ChannelMembers: &[]string{
  2735  			th.BasicUser.Username,
  2736  			th.BasicUser2.Username,
  2737  		},
  2738  		User:     ptrStr(th.BasicUser.Username),
  2739  		Message:  ptrStr("Message"),
  2740  		CreateAt: ptrInt64(model.GetMillis()),
  2741  	}
  2742  	if err := th.App.ImportDirectPost(data, true); err != nil {
  2743  		t.Fatalf("Expected success.")
  2744  	}
  2745  	AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
  2746  
  2747  	// Try adding an invalid post in apply mode.
  2748  	data = &DirectPostImportData{
  2749  		ChannelMembers: &[]string{
  2750  			th.BasicUser.Username,
  2751  			model.NewId(),
  2752  		},
  2753  		User:     ptrStr(th.BasicUser.Username),
  2754  		Message:  ptrStr("Message"),
  2755  		CreateAt: ptrInt64(model.GetMillis()),
  2756  	}
  2757  	if err := th.App.ImportDirectPost(data, false); err == nil {
  2758  		t.Fatalf("Expected error.")
  2759  	}
  2760  	AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
  2761  
  2762  	// Try adding a valid post in apply mode.
  2763  	data = &DirectPostImportData{
  2764  		ChannelMembers: &[]string{
  2765  			th.BasicUser.Username,
  2766  			th.BasicUser2.Username,
  2767  		},
  2768  		User:     ptrStr(th.BasicUser.Username),
  2769  		Message:  ptrStr("Message"),
  2770  		CreateAt: ptrInt64(model.GetMillis()),
  2771  	}
  2772  	if err := th.App.ImportDirectPost(data, false); err != nil {
  2773  		t.Fatalf("Expected success: %v", err.Error())
  2774  	}
  2775  	AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
  2776  
  2777  	// Check the post values.
  2778  	if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(directChannel.Id, *data.CreateAt); result.Err != nil {
  2779  		t.Fatal(result.Err.Error())
  2780  	} else {
  2781  		posts := result.Data.([]*model.Post)
  2782  		if len(posts) != 1 {
  2783  			t.Fatal("Unexpected number of posts found.")
  2784  		}
  2785  		post := posts[0]
  2786  		if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
  2787  			t.Fatal("Post properties not as expected")
  2788  		}
  2789  	}
  2790  
  2791  	// Import the post again.
  2792  	if err := th.App.ImportDirectPost(data, false); err != nil {
  2793  		t.Fatalf("Expected success.")
  2794  	}
  2795  	AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
  2796  
  2797  	// Check the post values.
  2798  	if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(directChannel.Id, *data.CreateAt); result.Err != nil {
  2799  		t.Fatal(result.Err.Error())
  2800  	} else {
  2801  		posts := result.Data.([]*model.Post)
  2802  		if len(posts) != 1 {
  2803  			t.Fatal("Unexpected number of posts found.")
  2804  		}
  2805  		post := posts[0]
  2806  		if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
  2807  			t.Fatal("Post properties not as expected")
  2808  		}
  2809  	}
  2810  
  2811  	// Save the post with a different time.
  2812  	data.CreateAt = ptrInt64(*data.CreateAt + 1)
  2813  	if err := th.App.ImportDirectPost(data, false); err != nil {
  2814  		t.Fatalf("Expected success.")
  2815  	}
  2816  	AssertAllPostsCount(t, th.App, initialPostCount, 2, "")
  2817  
  2818  	// Save the post with a different message.
  2819  	data.Message = ptrStr("Message 2")
  2820  	if err := th.App.ImportDirectPost(data, false); err != nil {
  2821  		t.Fatalf("Expected success.")
  2822  	}
  2823  	AssertAllPostsCount(t, th.App, initialPostCount, 3, "")
  2824  
  2825  	// Test with hashtags
  2826  	data.Message = ptrStr("Message 2 #hashtagmashupcity")
  2827  	data.CreateAt = ptrInt64(*data.CreateAt + 1)
  2828  	if err := th.App.ImportDirectPost(data, false); err != nil {
  2829  		t.Fatalf("Expected success.")
  2830  	}
  2831  	AssertAllPostsCount(t, th.App, initialPostCount, 4, "")
  2832  
  2833  	if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(directChannel.Id, *data.CreateAt); result.Err != nil {
  2834  		t.Fatal(result.Err.Error())
  2835  	} else {
  2836  		posts := result.Data.([]*model.Post)
  2837  		if len(posts) != 1 {
  2838  			t.Fatal("Unexpected number of posts found.")
  2839  		}
  2840  		post := posts[0]
  2841  		if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
  2842  			t.Fatal("Post properties not as expected")
  2843  		}
  2844  		if post.Hashtags != "#hashtagmashupcity" {
  2845  			t.Fatalf("Hashtags not as expected: %s", post.Hashtags)
  2846  		}
  2847  	}
  2848  
  2849  	// Test with some flags.
  2850  	data = &DirectPostImportData{
  2851  		ChannelMembers: &[]string{
  2852  			th.BasicUser.Username,
  2853  			th.BasicUser2.Username,
  2854  		},
  2855  		FlaggedBy: &[]string{
  2856  			th.BasicUser.Username,
  2857  			th.BasicUser2.Username,
  2858  		},
  2859  		User:     ptrStr(th.BasicUser.Username),
  2860  		Message:  ptrStr("Message"),
  2861  		CreateAt: ptrInt64(model.GetMillis()),
  2862  	}
  2863  
  2864  	if err := th.App.ImportDirectPost(data, false); err != nil {
  2865  		t.Fatalf("Expected success: %v", err.Error())
  2866  	}
  2867  
  2868  	// Check the post values.
  2869  	if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(directChannel.Id, *data.CreateAt); result.Err != nil {
  2870  		t.Fatal(result.Err.Error())
  2871  	} else {
  2872  		posts := result.Data.([]*model.Post)
  2873  		if len(posts) != 1 {
  2874  			t.Fatal("Unexpected number of posts found.")
  2875  		}
  2876  		post := posts[0]
  2877  		checkPreference(t, th.App, th.BasicUser.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
  2878  		checkPreference(t, th.App, th.BasicUser2.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
  2879  	}
  2880  
  2881  	// ------------------ Group Channel -------------------------
  2882  
  2883  	// Create the GROUP channel.
  2884  	user3 := th.CreateUser()
  2885  	channelData = DirectChannelImportData{
  2886  		Members: &[]string{
  2887  			th.BasicUser.Username,
  2888  			th.BasicUser2.Username,
  2889  			user3.Username,
  2890  		},
  2891  	}
  2892  	if err := th.App.ImportDirectChannel(&channelData, false); err != nil {
  2893  		t.Fatalf("Expected success: %v", err.Error())
  2894  	}
  2895  
  2896  	// Get the channel.
  2897  	var groupChannel *model.Channel
  2898  	userIds := []string{
  2899  		th.BasicUser.Id,
  2900  		th.BasicUser2.Id,
  2901  		user3.Id,
  2902  	}
  2903  	if channel, err := th.App.createGroupChannel(userIds, th.BasicUser.Id); err.Id != store.CHANNEL_EXISTS_ERROR {
  2904  		t.Fatal("Should have got store.CHANNEL_EXISTS_ERROR")
  2905  	} else {
  2906  		groupChannel = channel
  2907  	}
  2908  
  2909  	// Get the number of posts in the system.
  2910  	if result := <-th.App.Srv.Store.Post().AnalyticsPostCount("", false, false); result.Err != nil {
  2911  		t.Fatal(result.Err)
  2912  	} else {
  2913  		initialPostCount = result.Data.(int64)
  2914  	}
  2915  
  2916  	// Try adding an invalid post in dry run mode.
  2917  	data = &DirectPostImportData{
  2918  		ChannelMembers: &[]string{
  2919  			th.BasicUser.Username,
  2920  			th.BasicUser2.Username,
  2921  			user3.Username,
  2922  		},
  2923  		User:     ptrStr(th.BasicUser.Username),
  2924  		CreateAt: ptrInt64(model.GetMillis()),
  2925  	}
  2926  	if err := th.App.ImportDirectPost(data, true); err == nil {
  2927  		t.Fatalf("Expected error.")
  2928  	}
  2929  	AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
  2930  
  2931  	// Try adding a valid post in dry run mode.
  2932  	data = &DirectPostImportData{
  2933  		ChannelMembers: &[]string{
  2934  			th.BasicUser.Username,
  2935  			th.BasicUser2.Username,
  2936  			user3.Username,
  2937  		},
  2938  		User:     ptrStr(th.BasicUser.Username),
  2939  		Message:  ptrStr("Message"),
  2940  		CreateAt: ptrInt64(model.GetMillis()),
  2941  	}
  2942  	if err := th.App.ImportDirectPost(data, true); err != nil {
  2943  		t.Fatalf("Expected success.")
  2944  	}
  2945  	AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
  2946  
  2947  	// Try adding an invalid post in apply mode.
  2948  	data = &DirectPostImportData{
  2949  		ChannelMembers: &[]string{
  2950  			th.BasicUser.Username,
  2951  			th.BasicUser2.Username,
  2952  			user3.Username,
  2953  			model.NewId(),
  2954  		},
  2955  		User:     ptrStr(th.BasicUser.Username),
  2956  		Message:  ptrStr("Message"),
  2957  		CreateAt: ptrInt64(model.GetMillis()),
  2958  	}
  2959  	if err := th.App.ImportDirectPost(data, false); err == nil {
  2960  		t.Fatalf("Expected error.")
  2961  	}
  2962  	AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
  2963  
  2964  	// Try adding a valid post in apply mode.
  2965  	data = &DirectPostImportData{
  2966  		ChannelMembers: &[]string{
  2967  			th.BasicUser.Username,
  2968  			th.BasicUser2.Username,
  2969  			user3.Username,
  2970  		},
  2971  		User:     ptrStr(th.BasicUser.Username),
  2972  		Message:  ptrStr("Message"),
  2973  		CreateAt: ptrInt64(model.GetMillis()),
  2974  	}
  2975  	if err := th.App.ImportDirectPost(data, false); err != nil {
  2976  		t.Fatalf("Expected success: %v", err.Error())
  2977  	}
  2978  	AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
  2979  
  2980  	// Check the post values.
  2981  	if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(groupChannel.Id, *data.CreateAt); result.Err != nil {
  2982  		t.Fatal(result.Err.Error())
  2983  	} else {
  2984  		posts := result.Data.([]*model.Post)
  2985  		if len(posts) != 1 {
  2986  			t.Fatal("Unexpected number of posts found.")
  2987  		}
  2988  		post := posts[0]
  2989  		if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
  2990  			t.Fatal("Post properties not as expected")
  2991  		}
  2992  	}
  2993  
  2994  	// Import the post again.
  2995  	if err := th.App.ImportDirectPost(data, false); err != nil {
  2996  		t.Fatalf("Expected success.")
  2997  	}
  2998  	AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
  2999  
  3000  	// Check the post values.
  3001  	if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(groupChannel.Id, *data.CreateAt); result.Err != nil {
  3002  		t.Fatal(result.Err.Error())
  3003  	} else {
  3004  		posts := result.Data.([]*model.Post)
  3005  		if len(posts) != 1 {
  3006  			t.Fatal("Unexpected number of posts found.")
  3007  		}
  3008  		post := posts[0]
  3009  		if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
  3010  			t.Fatal("Post properties not as expected")
  3011  		}
  3012  	}
  3013  
  3014  	// Save the post with a different time.
  3015  	data.CreateAt = ptrInt64(*data.CreateAt + 1)
  3016  	if err := th.App.ImportDirectPost(data, false); err != nil {
  3017  		t.Fatalf("Expected success.")
  3018  	}
  3019  	AssertAllPostsCount(t, th.App, initialPostCount, 2, "")
  3020  
  3021  	// Save the post with a different message.
  3022  	data.Message = ptrStr("Message 2")
  3023  	if err := th.App.ImportDirectPost(data, false); err != nil {
  3024  		t.Fatalf("Expected success.")
  3025  	}
  3026  	AssertAllPostsCount(t, th.App, initialPostCount, 3, "")
  3027  
  3028  	// Test with hashtags
  3029  	data.Message = ptrStr("Message 2 #hashtagmashupcity")
  3030  	data.CreateAt = ptrInt64(*data.CreateAt + 1)
  3031  	if err := th.App.ImportDirectPost(data, false); err != nil {
  3032  		t.Fatalf("Expected success.")
  3033  	}
  3034  	AssertAllPostsCount(t, th.App, initialPostCount, 4, "")
  3035  
  3036  	if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(groupChannel.Id, *data.CreateAt); result.Err != nil {
  3037  		t.Fatal(result.Err.Error())
  3038  	} else {
  3039  		posts := result.Data.([]*model.Post)
  3040  		if len(posts) != 1 {
  3041  			t.Fatal("Unexpected number of posts found.")
  3042  		}
  3043  		post := posts[0]
  3044  		if post.Message != *data.Message || post.CreateAt != *data.CreateAt || post.UserId != th.BasicUser.Id {
  3045  			t.Fatal("Post properties not as expected")
  3046  		}
  3047  		if post.Hashtags != "#hashtagmashupcity" {
  3048  			t.Fatalf("Hashtags not as expected: %s", post.Hashtags)
  3049  		}
  3050  	}
  3051  
  3052  	// Test with some flags.
  3053  	data = &DirectPostImportData{
  3054  		ChannelMembers: &[]string{
  3055  			th.BasicUser.Username,
  3056  			th.BasicUser2.Username,
  3057  			user3.Username,
  3058  		},
  3059  		FlaggedBy: &[]string{
  3060  			th.BasicUser.Username,
  3061  			th.BasicUser2.Username,
  3062  		},
  3063  		User:     ptrStr(th.BasicUser.Username),
  3064  		Message:  ptrStr("Message"),
  3065  		CreateAt: ptrInt64(model.GetMillis()),
  3066  	}
  3067  
  3068  	if err := th.App.ImportDirectPost(data, false); err != nil {
  3069  		t.Fatalf("Expected success: %v", err.Error())
  3070  	}
  3071  
  3072  	// Check the post values.
  3073  	if result := <-th.App.Srv.Store.Post().GetPostsCreatedAt(groupChannel.Id, *data.CreateAt); result.Err != nil {
  3074  		t.Fatal(result.Err.Error())
  3075  	} else {
  3076  		posts := result.Data.([]*model.Post)
  3077  		if len(posts) != 1 {
  3078  			t.Fatal("Unexpected number of posts found.")
  3079  		}
  3080  		post := posts[0]
  3081  		checkPreference(t, th.App, th.BasicUser.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
  3082  		checkPreference(t, th.App, th.BasicUser2.Id, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id, "true")
  3083  	}
  3084  }
  3085  
  3086  func TestImportImportLine(t *testing.T) {
  3087  	th := Setup()
  3088  	defer th.TearDown()
  3089  
  3090  	// Try import line with an invalid type.
  3091  	line := LineImportData{
  3092  		Type: "gibberish",
  3093  	}
  3094  
  3095  	if err := th.App.ImportLine(line, false); err == nil {
  3096  		t.Fatalf("Expected an error when importing a line with invalid type.")
  3097  	}
  3098  
  3099  	// Try import line with team type but nil team.
  3100  	line.Type = "team"
  3101  	if err := th.App.ImportLine(line, false); err == nil {
  3102  		t.Fatalf("Expected an error when importing a line of type team with a nil team.")
  3103  	}
  3104  
  3105  	// Try import line with channel type but nil channel.
  3106  	line.Type = "channel"
  3107  	if err := th.App.ImportLine(line, false); err == nil {
  3108  		t.Fatalf("Expected an error when importing a line with type channel with a nil channel.")
  3109  	}
  3110  
  3111  	// Try import line with user type but nil user.
  3112  	line.Type = "user"
  3113  	if err := th.App.ImportLine(line, false); err == nil {
  3114  		t.Fatalf("Expected an error when importing a line with type uesr with a nil user.")
  3115  	}
  3116  
  3117  	// Try import line with post type but nil post.
  3118  	line.Type = "post"
  3119  	if err := th.App.ImportLine(line, false); err == nil {
  3120  		t.Fatalf("Expected an error when importing a line with type post with a nil post.")
  3121  	}
  3122  
  3123  	// Try import line with direct_channel type but nil direct_channel.
  3124  	line.Type = "direct_channel"
  3125  	if err := th.App.ImportLine(line, false); err == nil {
  3126  		t.Fatalf("Expected an error when importing a line with type direct_channel with a nil direct_channel.")
  3127  	}
  3128  
  3129  	// Try import line with direct_post type but nil direct_post.
  3130  	line.Type = "direct_post"
  3131  	if err := th.App.ImportLine(line, false); err == nil {
  3132  		t.Fatalf("Expected an error when importing a line with type direct_post with a nil direct_post.")
  3133  	}
  3134  }
  3135  
  3136  func TestImportBulkImport(t *testing.T) {
  3137  	th := Setup()
  3138  	defer th.TearDown()
  3139  
  3140  	teamName := model.NewId()
  3141  	channelName := model.NewId()
  3142  	username := model.NewId()
  3143  	username2 := model.NewId()
  3144  	username3 := model.NewId()
  3145  
  3146  	// Run bulk import with a valid 1 of everything.
  3147  	data1 := `{"type": "version", "version": 1}
  3148  {"type": "team", "team": {"type": "O", "display_name": "lskmw2d7a5ao7ppwqh5ljchvr4", "name": "` + teamName + `"}}
  3149  {"type": "channel", "channel": {"type": "O", "display_name": "xr6m6udffngark2uekvr3hoeny", "team": "` + teamName + `", "name": "` + channelName + `"}}
  3150  {"type": "user", "user": {"username": "` + username + `", "email": "` + username + `@example.com", "teams": [{"name": "` + teamName + `", "channels": [{"name": "` + channelName + `"}]}]}}
  3151  {"type": "user", "user": {"username": "` + username2 + `", "email": "` + username2 + `@example.com", "teams": [{"name": "` + teamName + `", "channels": [{"name": "` + channelName + `"}]}]}}
  3152  {"type": "user", "user": {"username": "` + username3 + `", "email": "` + username3 + `@example.com", "teams": [{"name": "` + teamName + `", "channels": [{"name": "` + channelName + `"}]}]}}
  3153  {"type": "post", "post": {"team": "` + teamName + `", "channel": "` + channelName + `", "user": "` + username + `", "message": "Hello World", "create_at": 123456789012}}
  3154  {"type": "direct_channel", "direct_channel": {"members": ["` + username + `", "` + username2 + `"]}}
  3155  {"type": "direct_channel", "direct_channel": {"members": ["` + username + `", "` + username2 + `", "` + username3 + `"]}}
  3156  {"type": "direct_post", "direct_post": {"channel_members": ["` + username + `", "` + username2 + `"], "user": "` + username + `", "message": "Hello Direct Channel", "create_at": 123456789013}}
  3157  {"type": "direct_post", "direct_post": {"channel_members": ["` + username + `", "` + username2 + `", "` + username3 + `"], "user": "` + username + `", "message": "Hello Group Channel", "create_at": 123456789014}}`
  3158  
  3159  	if err, line := th.App.BulkImport(strings.NewReader(data1), false, 2); err != nil || line != 0 {
  3160  		t.Fatalf("BulkImport should have succeeded: %v, %v", err.Error(), line)
  3161  	}
  3162  
  3163  	// Run bulk import using a string that contains a line with invalid json.
  3164  	data2 := `{"type": "version", "version": 1`
  3165  	if err, line := th.App.BulkImport(strings.NewReader(data2), false, 2); err == nil || line != 1 {
  3166  		t.Fatalf("Should have failed due to invalid JSON on line 1.")
  3167  	}
  3168  
  3169  	// Run bulk import using valid JSON but missing version line at the start.
  3170  	data3 := `{"type": "team", "team": {"type": "O", "display_name": "lskmw2d7a5ao7ppwqh5ljchvr4", "name": "` + teamName + `"}}
  3171  {"type": "channel", "channel": {"type": "O", "display_name": "xr6m6udffngark2uekvr3hoeny", "team": "` + teamName + `", "name": "` + channelName + `"}}
  3172  {"type": "user", "user": {"username": "kufjgnkxkrhhfgbrip6qxkfsaa", "email": "kufjgnkxkrhhfgbrip6qxkfsaa@example.com"}}
  3173  {"type": "user", "user": {"username": "bwshaim6qnc2ne7oqkd5b2s2rq", "email": "bwshaim6qnc2ne7oqkd5b2s2rq@example.com", "teams": [{"name": "` + teamName + `", "channels": [{"name": "` + channelName + `"}]}]}}`
  3174  	if err, line := th.App.BulkImport(strings.NewReader(data3), false, 2); err == nil || line != 1 {
  3175  		t.Fatalf("Should have failed due to missing version line on line 1.")
  3176  	}
  3177  }
  3178  
  3179  func TestImportProcessImportDataFileVersionLine(t *testing.T) {
  3180  	data := LineImportData{
  3181  		Type:    "version",
  3182  		Version: ptrInt(1),
  3183  	}
  3184  	if version, err := processImportDataFileVersionLine(data); err != nil || version != 1 {
  3185  		t.Fatalf("Expected no error and version 1.")
  3186  	}
  3187  
  3188  	data.Type = "NotVersion"
  3189  	if _, err := processImportDataFileVersionLine(data); err == nil {
  3190  		t.Fatalf("Expected error on invalid version line.")
  3191  	}
  3192  
  3193  	data.Type = "version"
  3194  	data.Version = nil
  3195  	if _, err := processImportDataFileVersionLine(data); err == nil {
  3196  		t.Fatalf("Expected error on invalid version line.")
  3197  	}
  3198  }