github.com/status-im/status-go@v1.1.0/protocol/contact_test.go (about)

     1  package protocol
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/status-im/status-go/eth-node/crypto"
    12  	"github.com/status-im/status-go/protocol/common"
    13  	"github.com/status-im/status-go/protocol/protobuf"
    14  )
    15  
    16  type contactTest struct {
    17  	actualLocalState    ContactRequestState
    18  	expectedLocalState  ContactRequestState
    19  	actualRemoteState   ContactRequestState
    20  	expectedRemoteState ContactRequestState
    21  	expectedAdded       bool
    22  	expectedHasAddedUs  bool
    23  	expectedMutual      bool
    24  }
    25  
    26  func (ct contactTest) Contact() Contact {
    27  	return Contact{
    28  		ContactRequestLocalState:  ct.actualLocalState,
    29  		ContactRequestRemoteState: ct.actualRemoteState,
    30  	}
    31  }
    32  
    33  func validateContactTest(t *testing.T, contact Contact, tc contactTest, testNum int) {
    34  	failedMessage := fmt.Sprintf("test failed: %d", testNum)
    35  	require.Equal(t, tc.expectedLocalState, contact.ContactRequestLocalState, failedMessage+", contact request local state not matching")
    36  	require.Equal(t, tc.expectedRemoteState, contact.ContactRequestRemoteState, failedMessage+", contact request remote state not matching")
    37  
    38  	require.Equal(t, tc.expectedAdded, contact.added(), failedMessage+", added() not matching")
    39  	require.Equal(t, tc.expectedHasAddedUs, contact.hasAddedUs(), failedMessage+", hasAddedUs() not matching")
    40  	require.Equal(t, tc.expectedMutual, contact.mutual(), failedMessage+", mutual() not matching")
    41  }
    42  
    43  /*
    44  none/none
    45  sent/none
    46  dismissed/none
    47  none/received
    48  sent/received
    49  dismissed/received
    50  */
    51  
    52  func TestContactContactRequestSent(t *testing.T) {
    53  
    54  	clock := uint64(1)
    55  
    56  	/* Cases to consider are:
    57  	   Local = none Remote = none
    58  	   Local = none Remote = received
    59  	   Local = sent Remote = none
    60  	   Local = sent Remote = received
    61  	   Local = dismissed Remote = none
    62  	   Local = dismissed Remote = received
    63  	*/
    64  
    65  	tests := []contactTest{
    66  		{
    67  			actualLocalState:    ContactRequestStateNone,
    68  			actualRemoteState:   ContactRequestStateNone,
    69  			expectedLocalState:  ContactRequestStateSent,
    70  			expectedRemoteState: ContactRequestStateNone,
    71  			expectedAdded:       true,
    72  			expectedHasAddedUs:  false,
    73  			expectedMutual:      false,
    74  		},
    75  		{
    76  			actualLocalState:    ContactRequestStateNone,
    77  			actualRemoteState:   ContactRequestStateReceived,
    78  			expectedLocalState:  ContactRequestStateSent,
    79  			expectedRemoteState: ContactRequestStateReceived,
    80  			expectedAdded:       true,
    81  			expectedHasAddedUs:  true,
    82  			expectedMutual:      true,
    83  		},
    84  		{
    85  			actualLocalState:    ContactRequestStateSent,
    86  			actualRemoteState:   ContactRequestStateNone,
    87  			expectedLocalState:  ContactRequestStateSent,
    88  			expectedRemoteState: ContactRequestStateNone,
    89  			expectedAdded:       true,
    90  			expectedHasAddedUs:  false,
    91  			expectedMutual:      false,
    92  		},
    93  		{
    94  			actualLocalState:    ContactRequestStateSent,
    95  			actualRemoteState:   ContactRequestStateReceived,
    96  			expectedLocalState:  ContactRequestStateSent,
    97  			expectedRemoteState: ContactRequestStateReceived,
    98  			expectedAdded:       true,
    99  			expectedHasAddedUs:  true,
   100  			expectedMutual:      true,
   101  		},
   102  		{
   103  			actualLocalState:    ContactRequestStateDismissed,
   104  			actualRemoteState:   ContactRequestStateNone,
   105  			expectedLocalState:  ContactRequestStateSent,
   106  			expectedRemoteState: ContactRequestStateNone,
   107  			expectedAdded:       true,
   108  			expectedHasAddedUs:  false,
   109  			expectedMutual:      false,
   110  		},
   111  		{
   112  			actualLocalState:    ContactRequestStateDismissed,
   113  			actualRemoteState:   ContactRequestStateReceived,
   114  			expectedLocalState:  ContactRequestStateSent,
   115  			expectedRemoteState: ContactRequestStateReceived,
   116  			expectedAdded:       true,
   117  			expectedHasAddedUs:  true,
   118  			expectedMutual:      true,
   119  		},
   120  	}
   121  
   122  	for testNum, tc := range tests {
   123  		contact := tc.Contact()
   124  
   125  		contact.ContactRequestSent(clock)
   126  		validateContactTest(t, contact, tc, testNum+1)
   127  
   128  	}
   129  }
   130  
   131  func TestContactAcceptContactRequest(t *testing.T) {
   132  
   133  	clock := uint64(1)
   134  
   135  	tests := []contactTest{
   136  		{
   137  			actualLocalState:    ContactRequestStateNone,
   138  			actualRemoteState:   ContactRequestStateNone,
   139  			expectedLocalState:  ContactRequestStateSent,
   140  			expectedRemoteState: ContactRequestStateNone,
   141  			expectedAdded:       true,
   142  			expectedHasAddedUs:  false,
   143  			expectedMutual:      false,
   144  		},
   145  		{
   146  			actualLocalState:    ContactRequestStateNone,
   147  			actualRemoteState:   ContactRequestStateReceived,
   148  			expectedLocalState:  ContactRequestStateSent,
   149  			expectedRemoteState: ContactRequestStateReceived,
   150  			expectedAdded:       true,
   151  			expectedHasAddedUs:  true,
   152  			expectedMutual:      true,
   153  		},
   154  		{
   155  			actualLocalState:    ContactRequestStateSent,
   156  			actualRemoteState:   ContactRequestStateNone,
   157  			expectedLocalState:  ContactRequestStateSent,
   158  			expectedRemoteState: ContactRequestStateNone,
   159  			expectedAdded:       true,
   160  			expectedHasAddedUs:  false,
   161  			expectedMutual:      false,
   162  		},
   163  		{
   164  			actualLocalState:    ContactRequestStateSent,
   165  			actualRemoteState:   ContactRequestStateReceived,
   166  			expectedLocalState:  ContactRequestStateSent,
   167  			expectedRemoteState: ContactRequestStateReceived,
   168  			expectedAdded:       true,
   169  			expectedHasAddedUs:  true,
   170  			expectedMutual:      true,
   171  		},
   172  		{
   173  			actualLocalState:    ContactRequestStateDismissed,
   174  			actualRemoteState:   ContactRequestStateNone,
   175  			expectedLocalState:  ContactRequestStateSent,
   176  			expectedRemoteState: ContactRequestStateNone,
   177  			expectedAdded:       true,
   178  			expectedHasAddedUs:  false,
   179  			expectedMutual:      false,
   180  		},
   181  		{
   182  			actualLocalState:    ContactRequestStateDismissed,
   183  			actualRemoteState:   ContactRequestStateReceived,
   184  			expectedLocalState:  ContactRequestStateSent,
   185  			expectedRemoteState: ContactRequestStateReceived,
   186  			expectedAdded:       true,
   187  			expectedHasAddedUs:  true,
   188  			expectedMutual:      true,
   189  		},
   190  	}
   191  
   192  	for testNum, tc := range tests {
   193  		contact := tc.Contact()
   194  
   195  		contact.AcceptContactRequest(clock)
   196  		validateContactTest(t, contact, tc, testNum+1)
   197  
   198  	}
   199  }
   200  
   201  func TestContactRetractContactRequest(t *testing.T) {
   202  
   203  	clock := uint64(1)
   204  
   205  	tests := []contactTest{
   206  		{
   207  			actualLocalState:    ContactRequestStateNone,
   208  			actualRemoteState:   ContactRequestStateNone,
   209  			expectedLocalState:  ContactRequestStateNone,
   210  			expectedRemoteState: ContactRequestStateNone,
   211  			expectedAdded:       false,
   212  			expectedHasAddedUs:  false,
   213  			expectedMutual:      false,
   214  		},
   215  		{
   216  			actualLocalState:    ContactRequestStateNone,
   217  			actualRemoteState:   ContactRequestStateReceived,
   218  			expectedLocalState:  ContactRequestStateNone,
   219  			expectedRemoteState: ContactRequestStateNone,
   220  			expectedAdded:       false,
   221  			expectedHasAddedUs:  false,
   222  			expectedMutual:      false,
   223  		},
   224  		{
   225  			actualLocalState:    ContactRequestStateSent,
   226  			actualRemoteState:   ContactRequestStateNone,
   227  			expectedLocalState:  ContactRequestStateNone,
   228  			expectedRemoteState: ContactRequestStateNone,
   229  			expectedAdded:       false,
   230  			expectedHasAddedUs:  false,
   231  			expectedMutual:      false,
   232  		},
   233  		{
   234  			actualLocalState:    ContactRequestStateSent,
   235  			actualRemoteState:   ContactRequestStateReceived,
   236  			expectedLocalState:  ContactRequestStateNone,
   237  			expectedRemoteState: ContactRequestStateNone,
   238  			expectedAdded:       false,
   239  			expectedHasAddedUs:  false,
   240  			expectedMutual:      false,
   241  		},
   242  		{
   243  			actualLocalState:    ContactRequestStateDismissed,
   244  			actualRemoteState:   ContactRequestStateNone,
   245  			expectedLocalState:  ContactRequestStateNone,
   246  			expectedRemoteState: ContactRequestStateNone,
   247  			expectedAdded:       false,
   248  			expectedHasAddedUs:  false,
   249  			expectedMutual:      false,
   250  		},
   251  		{
   252  			actualLocalState:    ContactRequestStateDismissed,
   253  			actualRemoteState:   ContactRequestStateReceived,
   254  			expectedLocalState:  ContactRequestStateNone,
   255  			expectedRemoteState: ContactRequestStateNone,
   256  			expectedAdded:       false,
   257  			expectedHasAddedUs:  false,
   258  			expectedMutual:      false,
   259  		},
   260  	}
   261  
   262  	for testNum, tc := range tests {
   263  		contact := tc.Contact()
   264  
   265  		contact.RetractContactRequest(clock)
   266  		validateContactTest(t, contact, tc, testNum+1)
   267  
   268  	}
   269  }
   270  
   271  func TestContactDismissContactRequest(t *testing.T) {
   272  
   273  	clock := uint64(1)
   274  
   275  	tests := []contactTest{
   276  		{
   277  			actualLocalState:    ContactRequestStateNone,
   278  			actualRemoteState:   ContactRequestStateNone,
   279  			expectedLocalState:  ContactRequestStateDismissed,
   280  			expectedRemoteState: ContactRequestStateNone,
   281  			expectedAdded:       false,
   282  			expectedHasAddedUs:  false,
   283  			expectedMutual:      false,
   284  		},
   285  		{
   286  			actualLocalState:    ContactRequestStateNone,
   287  			actualRemoteState:   ContactRequestStateReceived,
   288  			expectedLocalState:  ContactRequestStateDismissed,
   289  			expectedRemoteState: ContactRequestStateReceived,
   290  			expectedAdded:       false,
   291  			expectedHasAddedUs:  true,
   292  			expectedMutual:      false,
   293  		},
   294  		{
   295  			actualLocalState:    ContactRequestStateSent,
   296  			actualRemoteState:   ContactRequestStateNone,
   297  			expectedLocalState:  ContactRequestStateDismissed,
   298  			expectedRemoteState: ContactRequestStateNone,
   299  			expectedAdded:       false,
   300  			expectedHasAddedUs:  false,
   301  			expectedMutual:      false,
   302  		},
   303  		{
   304  			actualLocalState:    ContactRequestStateSent,
   305  			actualRemoteState:   ContactRequestStateReceived,
   306  			expectedLocalState:  ContactRequestStateDismissed,
   307  			expectedRemoteState: ContactRequestStateReceived,
   308  			expectedAdded:       false,
   309  			expectedHasAddedUs:  true,
   310  			expectedMutual:      false,
   311  		},
   312  		{
   313  			actualLocalState:    ContactRequestStateDismissed,
   314  			actualRemoteState:   ContactRequestStateNone,
   315  			expectedLocalState:  ContactRequestStateDismissed,
   316  			expectedRemoteState: ContactRequestStateNone,
   317  			expectedAdded:       false,
   318  			expectedHasAddedUs:  false,
   319  			expectedMutual:      false,
   320  		},
   321  		{
   322  			actualLocalState:    ContactRequestStateDismissed,
   323  			actualRemoteState:   ContactRequestStateReceived,
   324  			expectedLocalState:  ContactRequestStateDismissed,
   325  			expectedRemoteState: ContactRequestStateReceived,
   326  			expectedAdded:       false,
   327  			expectedHasAddedUs:  true,
   328  			expectedMutual:      false,
   329  		},
   330  	}
   331  
   332  	for testNum, tc := range tests {
   333  		contact := tc.Contact()
   334  
   335  		contact.DismissContactRequest(clock)
   336  		validateContactTest(t, contact, tc, testNum+1)
   337  
   338  	}
   339  }
   340  
   341  func TestContactContactRequestRetracted(t *testing.T) {
   342  
   343  	clock := uint64(1)
   344  
   345  	tests := []contactTest{
   346  		{
   347  			actualLocalState:    ContactRequestStateNone,
   348  			actualRemoteState:   ContactRequestStateNone,
   349  			expectedLocalState:  ContactRequestStateNone,
   350  			expectedRemoteState: ContactRequestStateNone,
   351  			expectedAdded:       false,
   352  			expectedHasAddedUs:  false,
   353  			expectedMutual:      false,
   354  		},
   355  		{
   356  			actualLocalState:    ContactRequestStateNone,
   357  			actualRemoteState:   ContactRequestStateReceived,
   358  			expectedLocalState:  ContactRequestStateNone,
   359  			expectedRemoteState: ContactRequestStateNone,
   360  			expectedAdded:       false,
   361  			expectedHasAddedUs:  false,
   362  			expectedMutual:      false,
   363  		},
   364  		{
   365  			actualLocalState:    ContactRequestStateSent,
   366  			actualRemoteState:   ContactRequestStateNone,
   367  			expectedLocalState:  ContactRequestStateNone,
   368  			expectedRemoteState: ContactRequestStateNone,
   369  			expectedAdded:       false,
   370  			expectedHasAddedUs:  false,
   371  			expectedMutual:      false,
   372  		},
   373  		{
   374  			actualLocalState:    ContactRequestStateSent,
   375  			actualRemoteState:   ContactRequestStateReceived,
   376  			expectedLocalState:  ContactRequestStateNone,
   377  			expectedRemoteState: ContactRequestStateNone,
   378  			expectedAdded:       false,
   379  			expectedHasAddedUs:  false,
   380  			expectedMutual:      false,
   381  		},
   382  		{
   383  			actualLocalState:    ContactRequestStateDismissed,
   384  			actualRemoteState:   ContactRequestStateNone,
   385  			expectedLocalState:  ContactRequestStateDismissed,
   386  			expectedRemoteState: ContactRequestStateNone,
   387  			expectedAdded:       false,
   388  			expectedHasAddedUs:  false,
   389  			expectedMutual:      false,
   390  		},
   391  		{
   392  			actualLocalState:    ContactRequestStateDismissed,
   393  			actualRemoteState:   ContactRequestStateReceived,
   394  			expectedLocalState:  ContactRequestStateDismissed,
   395  			expectedRemoteState: ContactRequestStateNone,
   396  			expectedAdded:       false,
   397  			expectedHasAddedUs:  false,
   398  			expectedMutual:      false,
   399  		},
   400  	}
   401  
   402  	for testNum, tc := range tests {
   403  		contact := tc.Contact()
   404  
   405  		contact.ContactRequestRetracted(clock, false)
   406  		validateContactTest(t, contact, tc, testNum+1)
   407  
   408  	}
   409  }
   410  
   411  func TestContactContactRequestReceived(t *testing.T) {
   412  
   413  	clock := uint64(1)
   414  
   415  	tests := []contactTest{
   416  		{
   417  			actualLocalState:    ContactRequestStateNone,
   418  			actualRemoteState:   ContactRequestStateNone,
   419  			expectedLocalState:  ContactRequestStateNone,
   420  			expectedRemoteState: ContactRequestStateReceived,
   421  			expectedAdded:       false,
   422  			expectedHasAddedUs:  true,
   423  			expectedMutual:      false,
   424  		},
   425  		{
   426  			actualLocalState:    ContactRequestStateNone,
   427  			actualRemoteState:   ContactRequestStateReceived,
   428  			expectedLocalState:  ContactRequestStateNone,
   429  			expectedRemoteState: ContactRequestStateReceived,
   430  			expectedAdded:       false,
   431  			expectedHasAddedUs:  true,
   432  			expectedMutual:      false,
   433  		},
   434  		{
   435  			actualLocalState:    ContactRequestStateSent,
   436  			actualRemoteState:   ContactRequestStateNone,
   437  			expectedLocalState:  ContactRequestStateSent,
   438  			expectedRemoteState: ContactRequestStateReceived,
   439  			expectedAdded:       true,
   440  			expectedHasAddedUs:  true,
   441  			expectedMutual:      true,
   442  		},
   443  		{
   444  			actualLocalState:    ContactRequestStateSent,
   445  			actualRemoteState:   ContactRequestStateReceived,
   446  			expectedLocalState:  ContactRequestStateSent,
   447  			expectedRemoteState: ContactRequestStateReceived,
   448  			expectedAdded:       true,
   449  			expectedHasAddedUs:  true,
   450  			expectedMutual:      true,
   451  		},
   452  		{
   453  			actualLocalState:    ContactRequestStateDismissed,
   454  			actualRemoteState:   ContactRequestStateNone,
   455  			expectedLocalState:  ContactRequestStateDismissed,
   456  			expectedRemoteState: ContactRequestStateReceived,
   457  			expectedAdded:       false,
   458  			expectedHasAddedUs:  true,
   459  			expectedMutual:      false,
   460  		},
   461  		{
   462  			actualLocalState:    ContactRequestStateDismissed,
   463  			actualRemoteState:   ContactRequestStateReceived,
   464  			expectedLocalState:  ContactRequestStateDismissed,
   465  			expectedRemoteState: ContactRequestStateReceived,
   466  			expectedAdded:       false,
   467  			expectedHasAddedUs:  true,
   468  			expectedMutual:      false,
   469  		},
   470  	}
   471  
   472  	for testNum, tc := range tests {
   473  		contact := tc.Contact()
   474  
   475  		contact.ContactRequestReceived(clock)
   476  		validateContactTest(t, contact, tc, testNum+1)
   477  
   478  	}
   479  }
   480  
   481  func TestContactContactRequestAccepted(t *testing.T) {
   482  
   483  	clock := uint64(1)
   484  
   485  	tests := []contactTest{
   486  		{
   487  			actualLocalState:    ContactRequestStateNone,
   488  			actualRemoteState:   ContactRequestStateNone,
   489  			expectedLocalState:  ContactRequestStateNone,
   490  			expectedRemoteState: ContactRequestStateReceived,
   491  			expectedAdded:       false,
   492  			expectedHasAddedUs:  true,
   493  			expectedMutual:      false,
   494  		},
   495  		{
   496  			actualLocalState:    ContactRequestStateNone,
   497  			actualRemoteState:   ContactRequestStateReceived,
   498  			expectedLocalState:  ContactRequestStateNone,
   499  			expectedRemoteState: ContactRequestStateReceived,
   500  			expectedAdded:       false,
   501  			expectedHasAddedUs:  true,
   502  			expectedMutual:      false,
   503  		},
   504  		{
   505  			actualLocalState:    ContactRequestStateSent,
   506  			actualRemoteState:   ContactRequestStateNone,
   507  			expectedLocalState:  ContactRequestStateSent,
   508  			expectedRemoteState: ContactRequestStateReceived,
   509  			expectedAdded:       true,
   510  			expectedHasAddedUs:  true,
   511  			expectedMutual:      true,
   512  		},
   513  		{
   514  			actualLocalState:    ContactRequestStateSent,
   515  			actualRemoteState:   ContactRequestStateReceived,
   516  			expectedLocalState:  ContactRequestStateSent,
   517  			expectedRemoteState: ContactRequestStateReceived,
   518  			expectedAdded:       true,
   519  			expectedHasAddedUs:  true,
   520  			expectedMutual:      true,
   521  		},
   522  		{
   523  			actualLocalState:    ContactRequestStateDismissed,
   524  			actualRemoteState:   ContactRequestStateNone,
   525  			expectedLocalState:  ContactRequestStateDismissed,
   526  			expectedRemoteState: ContactRequestStateReceived,
   527  			expectedAdded:       false,
   528  			expectedHasAddedUs:  true,
   529  			expectedMutual:      false,
   530  		},
   531  		{
   532  			actualLocalState:    ContactRequestStateDismissed,
   533  			actualRemoteState:   ContactRequestStateReceived,
   534  			expectedLocalState:  ContactRequestStateDismissed,
   535  			expectedRemoteState: ContactRequestStateReceived,
   536  			expectedAdded:       false,
   537  			expectedHasAddedUs:  true,
   538  			expectedMutual:      false,
   539  		},
   540  	}
   541  
   542  	for testNum, tc := range tests {
   543  		contact := tc.Contact()
   544  
   545  		contact.ContactRequestAccepted(clock)
   546  		validateContactTest(t, contact, tc, testNum+1)
   547  
   548  	}
   549  }
   550  
   551  func TestMarshalContactJSON(t *testing.T) {
   552  	contact := &Contact{
   553  		LocalNickname:             "primary-name",
   554  		Alias:                     "secondary-name",
   555  		ContactRequestLocalState:  ContactRequestStateSent,
   556  		ContactRequestRemoteState: ContactRequestStateReceived,
   557  	}
   558  	id, err := crypto.GenerateKey()
   559  	require.NoError(t, err)
   560  	contact.ID = common.PubkeyToHex(&id.PublicKey)
   561  
   562  	encodedContact, err := json.Marshal(contact)
   563  
   564  	require.NoError(t, err)
   565  
   566  	require.True(t, strings.Contains(string(encodedContact), "compressedKey\":\"zQ"))
   567  	require.True(t, strings.Contains(string(encodedContact), "mutual\":true"))
   568  	require.True(t, strings.Contains(string(encodedContact), "added\":true"))
   569  	require.True(t, strings.Contains(string(encodedContact), "hasAddedUs\":true"))
   570  	require.True(t, strings.Contains(string(encodedContact), "active\":true"))
   571  	require.True(t, strings.Contains(string(encodedContact), "primaryName\":\"primary-name"))
   572  	require.True(t, strings.Contains(string(encodedContact), "secondaryName\":\"secondary-name"))
   573  	require.True(t, strings.Contains(string(encodedContact), "emojiHash"))
   574  }
   575  
   576  func TestContactContactRequestPropagatedStateReceivedOutOfDateLocalStateOnTheirSide(t *testing.T) {
   577  	// We receive a message with expected contact request state != our state
   578  	// and clock < our clock, we ping back the user to reach consistency
   579  
   580  	c := &Contact{}
   581  	c.ContactRequestLocalState = ContactRequestStateSent
   582  	c.ContactRequestLocalClock = 1
   583  
   584  	result := c.ContactRequestPropagatedStateReceived(
   585  		&protobuf.ContactRequestPropagatedState{
   586  			RemoteState: uint64(ContactRequestStateNone),
   587  			RemoteClock: 0,
   588  			LocalState:  uint64(ContactRequestStateNone),
   589  			LocalClock:  1,
   590  		},
   591  	)
   592  
   593  	require.True(t, result.sendBackState)
   594  
   595  	// if the state is the same, it should not send back a message
   596  
   597  	c = &Contact{}
   598  	c.ContactRequestLocalState = ContactRequestStateNone
   599  	c.ContactRequestLocalClock = 1
   600  
   601  	result = c.ContactRequestPropagatedStateReceived(
   602  		&protobuf.ContactRequestPropagatedState{
   603  			RemoteState: uint64(ContactRequestStateNone),
   604  			RemoteClock: 0,
   605  			LocalState:  uint64(ContactRequestStateNone),
   606  			LocalClock:  1,
   607  		},
   608  	)
   609  
   610  	require.False(t, result.sendBackState)
   611  
   612  	// If the clock is the same, it should not send back a message
   613  	c = &Contact{}
   614  	c.ContactRequestLocalState = ContactRequestStateSent
   615  	c.ContactRequestLocalClock = 1
   616  
   617  	result = c.ContactRequestPropagatedStateReceived(
   618  		&protobuf.ContactRequestPropagatedState{
   619  			RemoteState: uint64(ContactRequestStateNone),
   620  			RemoteClock: 1,
   621  			LocalState:  uint64(ContactRequestStateNone),
   622  			LocalClock:  1,
   623  		},
   624  	)
   625  
   626  	require.False(t, result.sendBackState)
   627  
   628  }
   629  
   630  func TestContactContactRequestPropagatedStateReceivedOutOfDateLocalStateOnOurSide(t *testing.T) {
   631  	// We receive a message with expected contact request state == none
   632  	// and clock > our clock. We consider this a retraction, unless we are
   633  	// in the dismissed state, since that should be only changed by a
   634  	// trusted device
   635  
   636  	c := &Contact{}
   637  	c.ContactRequestLocalState = ContactRequestStateSent
   638  	c.ContactRequestLocalClock = 1
   639  
   640  	c.ContactRequestPropagatedStateReceived(
   641  		&protobuf.ContactRequestPropagatedState{
   642  			RemoteState: uint64(ContactRequestStateNone),
   643  			RemoteClock: 2,
   644  			LocalState:  uint64(ContactRequestStateNone),
   645  			LocalClock:  1,
   646  		},
   647  	)
   648  
   649  	require.False(t, c.added())
   650  
   651  	// But if it's dismissed, we don't change it
   652  	c = &Contact{}
   653  	c.ContactRequestLocalState = ContactRequestStateDismissed
   654  	c.ContactRequestLocalClock = 1
   655  
   656  	c.ContactRequestPropagatedStateReceived(
   657  		&protobuf.ContactRequestPropagatedState{
   658  			RemoteState: uint64(ContactRequestStateNone),
   659  			RemoteClock: 1,
   660  			LocalState:  uint64(ContactRequestStateNone),
   661  			LocalClock:  2,
   662  		},
   663  	)
   664  
   665  	require.False(t, c.added())
   666  	require.True(t, c.dismissed())
   667  
   668  	// or if it's lower clock
   669  
   670  	c = &Contact{}
   671  	c.ContactRequestLocalState = ContactRequestStateSent
   672  	c.ContactRequestLocalClock = 1
   673  
   674  	c.ContactRequestPropagatedStateReceived(
   675  		&protobuf.ContactRequestPropagatedState{
   676  			RemoteState: uint64(ContactRequestStateNone),
   677  			RemoteClock: 1,
   678  			LocalState:  uint64(ContactRequestStateNone),
   679  			LocalClock:  0,
   680  		},
   681  	)
   682  
   683  	require.True(t, c.added())
   684  }
   685  
   686  func TestContactContactRequestPropagatedStateReceivedOutOfDateRemoteState(t *testing.T) {
   687  	// We receive a message with newer remote state, we process it as we would for a normal contact request
   688  
   689  	c := &Contact{}
   690  
   691  	c.ContactRequestLocalState = ContactRequestStateSent
   692  	c.ContactRequestLocalClock = 1
   693  
   694  	c.ContactRequestPropagatedStateReceived(
   695  		&protobuf.ContactRequestPropagatedState{
   696  			RemoteState: uint64(ContactRequestStateSent),
   697  			RemoteClock: 1,
   698  			LocalState:  uint64(ContactRequestStateSent),
   699  			LocalClock:  1,
   700  		},
   701  	)
   702  
   703  	require.True(t, c.added())
   704  	require.True(t, c.mutual())
   705  
   706  	// and retraction
   707  	c = &Contact{}
   708  	c.ContactRequestLocalState = ContactRequestStateSent
   709  	c.ContactRequestLocalClock = 1
   710  	c.ContactRequestRemoteState = ContactRequestStateReceived
   711  	c.ContactRequestRemoteClock = 1
   712  
   713  	c.ContactRequestPropagatedStateReceived(
   714  		&protobuf.ContactRequestPropagatedState{
   715  			RemoteState: uint64(ContactRequestStateSent),
   716  			RemoteClock: 1,
   717  			LocalState:  uint64(ContactRequestStateNone),
   718  			LocalClock:  2,
   719  		},
   720  	)
   721  
   722  	require.False(t, c.added())
   723  	require.False(t, c.hasAddedUs())
   724  	require.False(t, c.mutual())
   725  }
   726  
   727  func TestPrimaryName(t *testing.T) {
   728  	// Has only Alias
   729  
   730  	contact := &Contact{
   731  		Alias: "alias",
   732  	}
   733  
   734  	require.Equal(t, "alias", contact.PrimaryName())
   735  
   736  	// Has display name
   737  
   738  	contact.DisplayName = "display-name"
   739  
   740  	require.Equal(t, "display-name", contact.PrimaryName())
   741  	require.Equal(t, "", contact.SecondaryName())
   742  
   743  	// Has non verified ens name
   744  
   745  	contact.EnsName = "ens-name"
   746  	require.Equal(t, "display-name", contact.PrimaryName())
   747  	require.Equal(t, "", contact.SecondaryName())
   748  
   749  	// Has verified ens name
   750  	contact.ENSVerified = true
   751  	require.Equal(t, "ens-name", contact.PrimaryName())
   752  	require.Equal(t, "", contact.SecondaryName())
   753  
   754  	contact.LocalNickname = "nickname"
   755  	// Has nickname and ENS name
   756  	require.Equal(t, "nickname", contact.PrimaryName())
   757  	require.Equal(t, "ens-name", contact.SecondaryName())
   758  
   759  	// Has nickname and display name
   760  	contact.EnsName = ""
   761  	require.Equal(t, "nickname", contact.PrimaryName())
   762  	require.Equal(t, "display-name", contact.SecondaryName())
   763  
   764  	// Has nickname and alias
   765  	contact.DisplayName = ""
   766  	require.Equal(t, "nickname", contact.PrimaryName())
   767  	require.Equal(t, "alias", contact.SecondaryName())
   768  }
   769  
   770  func TestProcessSyncContactRequestState(t *testing.T) {
   771  	c := &Contact{}
   772  	c.ContactRequestLocalState = ContactRequestStateNone
   773  	c.ContactRequestLocalClock = 1
   774  	c.ContactRequestRemoteState = ContactRequestStateNone
   775  	c.ContactRequestRemoteClock = 1
   776  
   777  	c.ProcessSyncContactRequestState(ContactRequestStateNone, 2, ContactRequestStateSent, 2)
   778  
   779  	// Here we need to confirm that resulting Local/RemoteState is equal
   780  	// to what comes from the contact sync message, otherwise it will be inconsistent
   781  	require.Equal(t, ContactRequestStateSent, c.ContactRequestLocalState)
   782  	require.Equal(t, ContactRequestStateNone, c.ContactRequestRemoteState)
   783  }