core: relax contact probing: don't send probe hashes to new contacts except group link hosts; still send probe hashes to group members (#3180)

This commit is contained in:
spaced4ndy
2023-10-09 09:46:58 +04:00
committed by GitHub
parent c738c6c522
commit ab46cbc5dd
7 changed files with 176 additions and 473 deletions
+42 -59
View File
@@ -41,9 +41,9 @@ chatDirectTests = do
it "direct timed message" testDirectTimedMessage
it "repeat AUTH errors disable contact" testRepeatAuthErrorsDisableContact
it "should send multiline message" testMultilineMessage
describe "contact merge" $ do
it "merge duplicate contacts" testContactMerge
it "new contact should merge with multiple existing contacts" testMergeContactMultipleContacts
describe "duplicate contacts" $ do
it "duplicate contacts are separate (contacts don't merge)" testDuplicateContactsSeparate
it "new contact is separate with multiple duplicate contacts (contacts don't merge)" testDuplicateContactsMultipleSeparate
describe "SMP servers" $ do
it "get and set SMP servers" testGetSetSMPServers
it "test SMP server connection" testTestSMPServerConnection
@@ -170,44 +170,13 @@ testAddContact = versionTestMatrix2 runTestAddContact
alice #$> ("/_read chat @2", id, "ok")
bob #$> ("/_read chat @2", id, "ok")
testContactMerge :: HasCallStack => FilePath -> IO ()
testContactMerge =
testDuplicateContactsSeparate :: HasCallStack => FilePath -> IO ()
testDuplicateContactsSeparate =
testChat2 aliceProfile bobProfile $
\alice bob -> do
connectUsers alice bob
alice <##> bob
alice ##> "/c"
inv' <- getInvitation alice
bob ##> ("/c " <> inv')
bob <## "confirmation sent!"
concurrentlyN_
[ alice
<### [ "bob_1 (Bob): contact is connected",
"contact bob_1 is merged into bob",
"use @bob <message> to send messages"
],
bob
<### [ "alice_1 (Alice): contact is connected",
"contact alice_1 is merged into alice",
"use @alice <message> to send messages"
]
]
alice <##> bob
alice @@@ [("@bob", "hey")]
alice `hasContactProfiles` ["alice", "bob"]
bob @@@ [("@alice", "hey")]
bob `hasContactProfiles` ["bob", "alice"]
testMergeContactMultipleContacts :: HasCallStack => FilePath -> IO ()
testMergeContactMultipleContacts =
testChat2 aliceProfile bobProfile $
\alice bob -> do
bob ##> "/contact_merge off"
bob <## "ok"
connectUsers alice bob
alice ##> "/c"
inv' <- getInvitation alice
bob ##> ("/c " <> inv')
@@ -216,42 +185,56 @@ testMergeContactMultipleContacts =
(alice <## "bob_1 (Bob): contact is connected")
(bob <## "alice_1 (Alice): contact is connected")
alice <##> bob
alice #> "@bob_1 1"
bob <# "alice_1> 1"
bob #> "@alice_1 2"
alice <# "bob_1> 2"
alice @@@ [("@bob", "hey"), ("@bob_1", "2")]
alice `hasContactProfiles` ["alice", "bob", "bob"]
bob @@@ [("@alice", "hey"), ("@alice_1", "2")]
bob `hasContactProfiles` ["bob", "alice", "alice"]
threadDelay 500000
testDuplicateContactsMultipleSeparate :: HasCallStack => FilePath -> IO ()
testDuplicateContactsMultipleSeparate =
testChat2 aliceProfile bobProfile $
\alice bob -> do
connectUsers alice bob
alice <##> bob
bob ##> "/contact_merge on"
bob <## "ok"
alice ##> "/c"
inv' <- getInvitation alice
bob ##> ("/c " <> inv')
bob <## "confirmation sent!"
concurrently_
(alice <## "bob_1 (Bob): contact is connected")
(bob <## "alice_1 (Alice): contact is connected")
alice ##> "/c"
inv'' <- getInvitation alice
bob ##> ("/c " <> inv'')
bob <## "confirmation sent!"
concurrentlyN_
[ alice
<### [ "bob_2 (Bob): contact is connected",
StartsWith "contact bob_2 is merged into bob",
StartsWith "use @bob",
StartsWith "contact bob_1 is merged into bob",
StartsWith "use @bob"
],
bob
<### [ "alice_2 (Alice): contact is connected",
StartsWith "contact alice_2 is merged into alice",
StartsWith "use @alice",
StartsWith "contact alice_1 is merged into alice",
StartsWith "use @alice"
]
]
concurrently_
(alice <## "bob_2 (Bob): contact is connected")
(bob <## "alice_2 (Alice): contact is connected")
alice <##> bob
alice #> "@bob_1 1"
bob <# "alice_1> 1"
bob #> "@alice_1 2"
alice <# "bob_1> 2"
alice #> "@bob_2 3"
bob <# "alice_2> 3"
bob #> "@alice_2 4"
alice <# "bob_2> 4"
alice ##> "/contacts"
alice <## "bob (Bob)"
alice <### ["bob (Bob)", "bob_1 (Bob)", "bob_2 (Bob)"]
bob ##> "/contacts"
bob <## "alice (Alice)"
alice `hasContactProfiles` ["alice", "bob"]
bob `hasContactProfiles` ["bob", "alice"]
bob <### ["alice (Alice)", "alice_1 (Alice)", "alice_2 (Alice)"]
alice `hasContactProfiles` ["alice", "bob", "bob", "bob"]
bob `hasContactProfiles` ["bob", "alice", "alice", "alice"]
testContactClear :: HasCallStack => FilePath -> IO ()
testContactClear =
+29 -242
View File
@@ -75,12 +75,9 @@ chatGroupTests = do
it "members have different local display names in different groups" testNoDirectDifferentLDNs
describe "merge members and contacts" $ do
it "new member should merge with existing contact" testMergeMemberExistingContact
it "new member should merge with multiple existing contacts" testMergeMemberMultipleContacts
it "new contact should merge with existing member" testMergeContactExistingMember
it "new contact should merge with existing member with associated contact" testMergeContactExistingMemberWithContact
it "new contact should merge with multiple existing members" testMergeContactMultipleMembers
it "new contact should merge with both existing members and contacts" testMergeContactExistingMembersAndContacts
it "new member contact is merged with existing contact" testMergeMemberContact
it "new group link host contact should merge with single existing contact out of multiple" testMergeGroupLinkHostMultipleContacts
describe "create member contact" $ do
it "create contact with group member with invitation message" testMemberContactMessage
it "create contact with group member without invitation message" testMemberContactNoMessage
@@ -2788,76 +2785,6 @@ testMergeMemberExistingContact =
alice `hasContactProfiles` ["alice", "bob", "cath"]
cath `hasContactProfiles` ["cath", "alice", "bob"]
testMergeMemberMultipleContacts :: HasCallStack => FilePath -> IO ()
testMergeMemberMultipleContacts =
testChat3 aliceProfile bobProfile cathProfile $
\alice bob cath -> do
alice ##> "/contact_merge off"
alice <## "ok"
connectUsers alice bob
connectUsers alice cath
alice ##> "/c"
inv' <- getInvitation alice
cath ##> ("/c " <> inv')
cath <## "confirmation sent!"
concurrently_
(alice <## "cath_1 (Catherine): contact is connected")
(cath <## "alice_1 (Alice): contact is connected")
alice `hasContactProfiles` ["alice", "bob", "cath", "cath"]
cath `hasContactProfiles` ["cath", "alice", "alice"]
alice ##> "/contact_merge on"
alice <## "ok"
createGroup2 "team" bob cath
bob ##> "/a #team alice"
bob <## "invitation to join the group #team sent to alice"
alice <## "#team: bob invites you to join the group as member"
alice <## "use /j team to accept"
alice ##> "/j team"
concurrentlyN_
[ alice
<### [ "#team: you joined the group",
"#team: member cath_2 (Catherine) is connected",
StartsWith "contact and member are merged: cath",
StartsWith "use @cath",
StartsWith "contact cath_",
StartsWith "use @cath"
],
bob <## "#team: alice joined the group",
cath
<### [ "#team: bob added alice_2 (Alice) to the group (connecting...)",
"#team: new member alice_2 is connected",
StartsWith "contact and member are merged: alice",
StartsWith "use @alice",
StartsWith "contact alice_",
StartsWith "use @alice"
]
]
alice <##> cath
alice #> "#team hello"
bob <# "#team alice> hello"
cath <# "#team alice> hello"
cath #> "#team hello too"
bob <# "#team cath> hello too"
alice <# "#team cath> hello too"
alice ##> "/contacts"
alice
<### [ "bob (Bob)",
"cath (Catherine)"
]
cath ##> "/contacts"
cath
<### [ "alice (Alice)",
"bob (Bob)"
]
alice `hasContactProfiles` ["alice", "bob", "cath"]
cath `hasContactProfiles` ["cath", "alice", "bob"]
testMergeContactExistingMember :: HasCallStack => FilePath -> IO ()
testMergeContactExistingMember =
testChat3 aliceProfile bobProfile cathProfile $
@@ -2889,66 +2816,6 @@ testMergeContactExistingMember =
bob `hasContactProfiles` ["alice", "bob", "cath"]
cath `hasContactProfiles` ["cath", "alice", "bob"]
testMergeContactExistingMemberWithContact :: HasCallStack => FilePath -> IO ()
testMergeContactExistingMemberWithContact =
testChat3 aliceProfile bobProfile cathProfile $
\alice bob cath -> do
createGroup3 "team" alice bob cath
-- create contact, delete only for bob so he would send probe hash to member
bob ##> "/_create member contact #1 3"
bob <## "contact for member #team cath is created"
bob ##> "/_invite member contact @3 text hi"
bob
<### [ "sent invitation to connect directly to member #team cath",
WithTime "@cath hi"
]
cath
<### [ "#team bob is creating direct contact bob with you",
WithTime "bob> hi"
]
concurrently_
(bob <## "cath (Catherine): contact is connected")
(cath <## "bob (Bob): contact is connected")
bob <##> cath
bob ##> "/_delete @3 notify=off"
bob <## "cath: contact is deleted"
bob ##> "/contacts"
bob <### ["alice (Alice)"]
cath ##> "/contacts"
cath <### ["alice (Alice)", "bob (Bob)"]
bob `hasContactProfiles` ["alice", "bob", "cath"]
cath `hasContactProfiles` ["cath", "alice", "bob"]
-- contact connects, member is merged
bob ##> "/c"
inv' <- getInvitation bob
cath ##> ("/c " <> inv')
cath <## "confirmation sent!"
concurrentlyN_
[ bob
<### [ "cath_1 (Catherine): contact is connected",
"contact and member are merged: cath_1, #team cath",
"use @cath <message> to send messages"
],
cath
<### [ "bob_1 (Bob): contact is connected",
"contact bob_1 is merged into bob",
"use @bob <message> to send messages"
]
]
bob <##> cath
bob ##> "/contacts"
bob <### ["alice (Alice)", "cath (Catherine)"]
cath ##> "/contacts"
cath <### ["alice (Alice)", "bob (Bob)"]
bob `hasContactProfiles` ["alice", "bob", "cath"]
cath `hasContactProfiles` ["cath", "alice", "bob"]
testMergeContactMultipleMembers :: HasCallStack => FilePath -> IO ()
testMergeContactMultipleMembers =
testChat3 aliceProfile bobProfile cathProfile $
@@ -2987,70 +2854,11 @@ testMergeContactMultipleMembers =
bob `hasContactProfiles` ["alice", "bob", "cath"]
cath `hasContactProfiles` ["cath", "alice", "bob"]
testMergeContactExistingMembersAndContacts :: HasCallStack => FilePath -> IO ()
testMergeContactExistingMembersAndContacts =
testChat3 aliceProfile bobProfile cathProfile $
\alice bob cath -> do
bob ##> "/contact_merge off"
bob <## "ok"
create2Groups3 "team" "club" alice bob cath
bob ##> "/c"
inv' <- getInvitation bob
cath ##> ("/c " <> inv')
cath <## "confirmation sent!"
concurrently_
(bob <## "cath_2 (Catherine): contact is connected")
(cath <## "bob_2 (Bob): contact is connected")
bob `hasContactProfiles` ["alice", "bob", "cath", "cath", "cath"]
cath `hasContactProfiles` ["cath", "alice", "bob", "bob", "bob"]
bob ##> "/contact_merge on"
bob <## "ok"
bob ##> "/c"
inv'' <- getInvitation bob
cath ##> ("/c " <> inv'')
cath <## "confirmation sent!"
concurrentlyN_
[ bob
<### [ "cath_3 (Catherine): contact is connected",
StartsWith "contact and member are merged: cath",
StartsWith "use @cath",
StartsWith "contact and member are merged: cath",
StartsWith "use @cath",
StartsWith "contact cath_3 is merged into cath",
StartsWith "use @cath"
],
cath
<### [ "bob_3 (Bob): contact is connected",
StartsWith "contact and member are merged: bob",
StartsWith "use @bob",
StartsWith "contact and member are merged: bob",
StartsWith "use @bob",
StartsWith "contact bob_3 is merged into bob",
StartsWith "use @bob"
]
]
bob <##> cath
bob ##> "/contacts"
bob <### ["alice (Alice)", "cath (Catherine)"]
cath ##> "/contacts"
cath <### ["alice (Alice)", "bob (Bob)"]
bob `hasContactProfiles` ["alice", "bob", "cath"]
cath `hasContactProfiles` ["cath", "alice", "bob"]
testMergeMemberContact :: HasCallStack => FilePath -> IO ()
testMergeMemberContact =
testChat3 aliceProfile bobProfile cathProfile $
\alice bob cath -> do
bob ##> "/contact_merge off"
bob <## "ok"
createGroup3 "team" alice bob cath
testMergeGroupLinkHostMultipleContacts :: HasCallStack => FilePath -> IO ()
testMergeGroupLinkHostMultipleContacts =
testChat2 bobProfile cathProfile $
\bob cath -> do
connectUsers bob cath
bob ##> "/c"
inv' <- getInvitation bob
@@ -3060,61 +2868,40 @@ testMergeMemberContact =
(bob <## "cath_1 (Catherine): contact is connected")
(cath <## "bob_1 (Bob): contact is connected")
bob `hasContactProfiles` ["alice", "bob", "cath", "cath"]
cath `hasContactProfiles` ["cath", "alice", "bob", "bob"]
bob `hasContactProfiles` ["bob", "cath", "cath"]
cath `hasContactProfiles` ["cath", "bob", "bob"]
bob ##> "/contact_merge on"
bob <## "ok"
-- bob and cath connect
bob ##> "/_create member contact #1 3"
bob <## "contact for member #team cath is created"
bob ##> "/_invite member contact @4 text hi"
bob
<### [ "sent invitation to connect directly to member #team cath",
WithTime "@cath hi"
]
cath
<### [ "#team bob is creating direct contact bob with you",
WithTime "bob> hi"
]
bob ##> "/g party"
bob <## "group #party is created"
bob <## "to add members use /a party <name> or /create link #party"
bob ##> "/create link #party"
gLink <- getGroupLink bob "party" GRMember True
cath ##> ("/c " <> gLink)
cath <## "connection request sent!"
bob <## "cath_2 (Catherine): accepting request to join group #party..."
concurrentlyN_
[ bob
<### [ "cath (Catherine): contact is connected",
"contact cath_1 is merged into cath",
-- StartsWith "use @cath"
"use @cath <message> to send messages"
<### [ "cath_2 (Catherine): contact is connected",
EndsWith "invited to group #party via your group link",
EndsWith "joined the group",
StartsWith "contact cath_2 is merged into cath",
StartsWith "use @cath"
],
cath
<### [ "bob (Bob): contact is connected",
"contact bob_1 is merged into bob",
-- StartsWith "use @bob"
"use @bob <message> to send messages"
<### [ "bob_2 (Bob): contact is connected",
"#party: you joined the group",
StartsWith "contact bob_2 is merged into bob",
StartsWith "use @bob"
]
]
bob <##> cath
bob ##> "/contacts"
bob <### ["alice (Alice)", "cath (Catherine)"]
bob <### ["cath (Catherine)", "cath_1 (Catherine)"]
cath ##> "/contacts"
cath <### ["alice (Alice)", "bob (Bob)"]
bob `hasContactProfiles` ["alice", "bob", "cath"]
cath `hasContactProfiles` ["cath", "alice", "bob"]
-- group messages work
alice #> "#team hello"
concurrently_
(bob <# "#team alice> hello")
(cath <# "#team alice> hello")
bob #> "#team hi there"
concurrently_
(alice <# "#team bob> hi there")
(cath <# "#team bob> hi there")
cath #> "#team hey team"
concurrently_
(alice <# "#team cath> hey team")
(bob <# "#team cath> hey team")
cath <### ["bob (Bob)", "bob_1 (Bob)"]
bob `hasContactProfiles` ["bob", "cath", "cath"]
cath `hasContactProfiles` ["cath", "bob", "bob"]
testMemberContactMessage :: HasCallStack => FilePath -> IO ()
testMemberContactMessage =
-34
View File
@@ -20,7 +20,6 @@ chatProfileTests = do
it "use multiword profile names" testMultiWordProfileNames
describe "user contact link" $ do
it "create and connect via contact link" testUserContactLink
it "merge existing contact when connecting via contact link" testUserContactLinkMerge
it "add contact link to profile" testProfileLink
it "auto accept contact requests" testUserContactLinkAutoAccept
it "deduplicate contact requests" testDeduplicateContactRequests
@@ -219,39 +218,6 @@ testUserContactLink =
alice @@@ [("@cath", lastChatFeature), ("@bob", "hey")]
alice <##> cath
testUserContactLinkMerge :: HasCallStack => FilePath -> IO ()
testUserContactLinkMerge =
testChat2 aliceProfile bobProfile $
\alice bob -> do
connectUsers alice bob
alice <##> bob
alice ##> "/ad"
cLink <- getContactLink alice True
bob ##> ("/c " <> cLink)
bob <## "connection request sent!"
alice <## "bob_1 (Bob) wants to connect to you!"
alice <## "to accept: /ac bob_1"
alice <## "to reject: /rc bob_1 (the sender will NOT be notified)"
alice @@@ [("@bob", "hey"), ("<@bob_1", "")]
alice ##> "/ac bob_1"
alice <## "bob_1 (Bob): accepting contact request..."
concurrentlyN_
[ alice
<### [ "bob_1 (Bob): contact is connected",
"contact bob_1 is merged into bob",
"use @bob <message> to send messages"
],
bob
<### [ "alice_1 (Alice): contact is connected",
"contact alice_1 is merged into alice",
"use @alice <message> to send messages"
]
]
threadDelay 100000
alice @@@ [("@bob", lastChatFeature)]
alice <##> bob
testProfileLink :: HasCallStack => FilePath -> IO ()
testProfileLink =
testChat3 aliceProfile bobProfile cathProfile $