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