2022-01-11 12:27:57 +00:00
{- # LANGUAGE DataKinds # -}
{- # LANGUAGE DuplicateRecordFields # -}
{- # LANGUAGE OverloadedLists # -}
{- # LANGUAGE OverloadedStrings # -}
2021-07-04 18:42:24 +01:00
module ProtocolTests where
2022-01-17 12:24:55 +00:00
import qualified Data.Aeson as J
2022-01-11 12:27:57 +00:00
import Data.ByteString.Char8 ( ByteString )
2022-03-13 19:34:03 +00:00
import Data.Time.Clock.System ( SystemTime ( .. ) , systemToUTCTime )
2022-01-11 12:27:57 +00:00
import Simplex.Chat.Protocol
import Simplex.Chat.Types
import Simplex.Messaging.Agent.Protocol
import qualified Simplex.Messaging.Crypto as C
import Simplex.Messaging.Crypto.Ratchet
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Parsers ( parseAll )
import Simplex.Messaging.Protocol ( smpClientVRange )
import Test.Hspec
protocolTests :: Spec
protocolTests = decodeChatMessageTest
srv :: SMPServer
srv =
SMPServer
{ host = " smp.simplex.im " ,
2022-01-11 21:23:57 +00:00
port = " 5223 " ,
2022-01-11 12:27:57 +00:00
keyHash = C . KeyHash " \ 215 m \ 248 \ 251 "
}
queue :: SMPQueueUri
queue =
SMPQueueUri
{ smpServer = srv ,
senderId = " \ 223 \ 142 z \ 251 " ,
clientVRange = smpClientVRange ,
dhPublicKey = " MCowBQYDK2VuAyEAjiswwI3O/NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o= "
}
connReqData :: ConnReqUriData
connReqData =
ConnReqUriData
{ crScheme = simplexChat ,
crAgentVRange = smpAgentVRange ,
crSmpQueues = [ queue ]
}
testDhPubKey :: C . PublicKeyX448
testDhPubKey = " MEIwBQYDK2VvAzkAmKuSYeQ/m0SixPDS8Wq8VBaTS1cW+Lp0n0h4Diu+kUpR+qXx4SDJ32YGEFoGFGSbGPry5Ychr6U= "
testE2ERatchetParams :: E2ERatchetParamsUri 'C . X448
testE2ERatchetParams = E2ERatchetParamsUri e2eEncryptVRange testDhPubKey testDhPubKey
testConnReq :: ConnectionRequestUri 'CMInvitation
testConnReq = CRInvitationUri connReqData testE2ERatchetParams
2022-03-13 19:34:03 +00:00
( ==## ) :: ByteString -> ChatMessage -> Expectation
s ==## msg = do
strDecode s ` shouldBe ` Right msg
parseAll strP s ` shouldBe ` Right msg
( ##== ) :: ByteString -> ChatMessage -> Expectation
s ##== msg =
J . eitherDecodeStrict' ( strEncode msg )
` shouldBe ` ( J . eitherDecodeStrict' s :: Either String J . Value )
( ##==## ) :: ByteString -> ChatMessage -> Expectation
s ##==## msg = do
s ##== msg
s ==## msg
2022-01-11 12:27:57 +00:00
( ==# ) :: ByteString -> ChatMsgEvent -> Expectation
2022-03-25 22:23:51 +04:00
s ==# msg = s ==## ChatMessage Nothing msg
2022-01-11 12:27:57 +00:00
( #== ) :: ByteString -> ChatMsgEvent -> Expectation
2022-03-25 22:23:51 +04:00
s #== msg = s ##== ChatMessage Nothing msg
2022-01-11 12:27:57 +00:00
( #==# ) :: ByteString -> ChatMsgEvent -> Expectation
s #==# msg = do
s #== msg
s ==# msg
testProfile :: Profile
2022-04-04 19:51:49 +01:00
testProfile = Profile { displayName = " alice " , fullName = " Alice " , image = Just ( ImageData " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII= " ) }
2022-01-11 12:27:57 +00:00
testGroupProfile :: GroupProfile
2022-03-10 15:45:40 +04:00
testGroupProfile = GroupProfile { displayName = " team " , fullName = " Team " , image = Nothing }
2022-01-11 12:27:57 +00:00
decodeChatMessageTest :: Spec
decodeChatMessageTest = describe " Chat message encoding/decoding " $ do
2022-03-13 19:34:03 +00:00
it " x.msg.new " $ " { \ " event \ " : \ " x.msg.new \ " , \ " params \ " :{ \ " content \ " :{ \ " text \ " : \ " hello \ " , \ " type \ " : \ " text \ " }}} " #==# XMsgNew ( MCSimple $ MCText " hello " )
2022-04-04 19:51:49 +01:00
it " x.msg.new " $
" { \ " event \ " : \ " x.msg.new \ " , \ " params \ " :{ \ " content \ " :{ \ " text \ " : \ " https://simplex.chat \ " , \ " type \ " : \ " link \ " , \ " preview \ " :{ \ " description \ " : \ " SimpleX Chat \ " , \ " image \ " : \ " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgA \ " , \ " title \ " : \ " SimpleX Chat \ " , \ " uri \ " : \ " https://simplex.chat \ " }}}} "
#==# XMsgNew ( MCSimple $ MCLink " https://simplex.chat " $ LinkPreview { uri = " https://simplex.chat " , title = " SimpleX Chat " , description = " SimpleX Chat " , image = ImageData " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgA " } )
2022-03-13 19:34:03 +00:00
it " x.msg.new " $ " { \ " msgId \ " : \ " AQIDBA== \ " , \ " event \ " : \ " x.msg.new \ " , \ " params \ " :{ \ " content \ " :{ \ " text \ " : \ " hello \ " , \ " type \ " : \ " text \ " }}} " ##==## ( ChatMessage ( Just $ SharedMsgId " \ 1 \ 2 \ 3 \ 4 " ) ( XMsgNew . MCSimple $ MCText " hello " ) )
it " x.msg.new " $
2022-03-16 13:20:47 +00:00
" { \ " msgId \ " : \ " AQIDBA== \ " , \ " event \ " : \ " x.msg.new \ " , \ " params \ " :{ \ " content \ " :{ \ " text \ " : \ " hello to you too \ " , \ " type \ " : \ " text \ " }, \ " quote \ " :{ \ " content \ " :{ \ " text \ " : \ " hello there! \ " , \ " type \ " : \ " text \ " }, \ " msgRef \ " :{ \ " msgId \ " : \ " BQYHCA== \ " , \ " sent \ " :true, \ " sentAt \ " : \ " 1970-01-01T00:00:01.000000001Z \ " }}}} "
2022-03-25 22:23:51 +04:00
##==## ChatMessage
( Just $ SharedMsgId " \ 1 \ 2 \ 3 \ 4 " )
( XMsgNew $
MCQuote
( QuotedMsg
( MsgRef ( Just $ SharedMsgId " \ 5 \ 6 \ 7 \ 8 " ) ( systemToUTCTime $ MkSystemTime 1 1 ) True Nothing )
$ MCText " hello there! "
)
( MCText " hello to you too " )
)
2022-03-13 19:34:03 +00:00
it " x.msg.new " $
" { \ " msgId \ " : \ " AQIDBA== \ " , \ " event \ " : \ " x.msg.new \ " , \ " params \ " :{ \ " content \ " :{ \ " text \ " : \ " hello \ " , \ " type \ " : \ " text \ " }, \ " forward \ " :true}} "
2022-03-25 22:23:51 +04:00
##==## ChatMessage ( Just $ SharedMsgId " \ 1 \ 2 \ 3 \ 4 " ) ( XMsgNew . MCForward $ MCText " hello " )
2022-01-11 12:27:57 +00:00
it " x.file " $
" { \ " event \ " : \ " x.file \ " , \ " params \ " :{ \ " file \ " :{ \ " fileConnReq \ " : \ " https://simplex.chat/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23MCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%3D&e2e=v%3D1%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D \ " , \ " fileSize \ " :12345, \ " fileName \ " : \ " photo.jpg \ " }}} "
2022-03-25 22:23:51 +04:00
#==# XFile FileInvitation { fileName = " photo.jpg " , fileSize = 12345 , fileConnReq = ACR SCMInvitation testConnReq }
2022-01-11 12:27:57 +00:00
it " x.file.acpt " $ " { \ " event \ " : \ " x.file.acpt \ " , \ " params \ " :{ \ " fileName \ " : \ " photo.jpg \ " }} " #==# XFileAcpt " photo.jpg "
2022-03-10 15:45:40 +04:00
it " x.info " $ " { \ " event \ " : \ " x.info \ " , \ " params \ " :{ \ " profile \ " :{ \ " fullName \ " : \ " Alice \ " , \ " displayName \ " : \ " alice \ " , \ " image \ " : \ " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII= \ " }}} " #==# XInfo testProfile
it " x.info " $ " { \ " event \ " : \ " x.info \ " , \ " params \ " :{ \ " profile \ " :{ \ " fullName \ " : \ " \ " , \ " displayName \ " : \ " alice \ " }}} " #==# XInfo Profile { displayName = " alice " , fullName = " " , image = Nothing }
2022-02-13 13:19:24 +04:00
it " x.contact with xContactId " $
2022-03-10 15:45:40 +04:00
" { \ " event \ " : \ " x.contact \ " , \ " params \ " :{ \ " contactReqId \ " : \ " AQIDBA== \ " , \ " profile \ " :{ \ " fullName \ " : \ " Alice \ " , \ " displayName \ " : \ " alice \ " , \ " image \ " : \ " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII= \ " }}} "
2022-02-13 13:19:24 +04:00
#==# XContact testProfile ( Just $ XContactId " \ 1 \ 2 \ 3 \ 4 " )
it " x.contact without XContactId " $
2022-03-10 15:45:40 +04:00
" { \ " event \ " : \ " x.contact \ " , \ " params \ " :{ \ " profile \ " :{ \ " fullName \ " : \ " Alice \ " , \ " displayName \ " : \ " alice \ " , \ " image \ " : \ " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII= \ " }}} "
2022-01-11 12:27:57 +00:00
#==# XContact testProfile Nothing
it " x.contact with content null " $
2022-03-10 15:45:40 +04:00
" { \ " event \ " : \ " x.contact \ " , \ " params \ " :{ \ " content \ " :null, \ " profile \ " :{ \ " fullName \ " : \ " Alice \ " , \ " displayName \ " : \ " alice \ " , \ " image \ " : \ " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII= \ " }}} "
2022-01-11 12:27:57 +00:00
==# XContact testProfile Nothing
2022-02-13 13:19:24 +04:00
it " x.contact with content (ignored) " $
2022-03-10 15:45:40 +04:00
" { \ " event \ " : \ " x.contact \ " , \ " params \ " :{ \ " content \ " :{ \ " text \ " : \ " hello \ " , \ " type \ " : \ " text \ " }, \ " profile \ " :{ \ " fullName \ " : \ " Alice \ " , \ " displayName \ " : \ " alice \ " , \ " image \ " : \ " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII= \ " }}} "
2022-02-13 13:19:24 +04:00
==# XContact testProfile Nothing
2022-01-11 12:27:57 +00:00
it " x.grp.inv " $
" { \ " event \ " : \ " x.grp.inv \ " , \ " params \ " :{ \ " groupInvitation \ " :{ \ " connRequest \ " : \ " https://simplex.chat/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23MCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%3D&e2e=v%3D1%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D \ " , \ " invitedMember \ " :{ \ " memberRole \ " : \ " member \ " , \ " memberId \ " : \ " BQYHCA== \ " }, \ " groupProfile \ " :{ \ " fullName \ " : \ " Team \ " , \ " displayName \ " : \ " team \ " }, \ " fromMember \ " :{ \ " memberRole \ " : \ " admin \ " , \ " memberId \ " : \ " AQIDBA== \ " }}}} "
#==# XGrpInv GroupInvitation { fromMember = MemberIdRole ( MemberId " \ 1 \ 2 \ 3 \ 4 " ) GRAdmin , invitedMember = MemberIdRole ( MemberId " \ 5 \ 6 \ 7 \ 8 " ) GRMember , connRequest = testConnReq , groupProfile = testGroupProfile }
it " x.grp.acpt " $ " { \ " event \ " : \ " x.grp.acpt \ " , \ " params \ " :{ \ " memberId \ " : \ " AQIDBA== \ " }} " #==# XGrpAcpt ( MemberId " \ 1 \ 2 \ 3 \ 4 " )
it " x.grp.acpt " $ " { \ " event \ " : \ " x.grp.acpt \ " , \ " params \ " :{ \ " memberId \ " : \ " AQIDBA== \ " }} " #==# XGrpAcpt ( MemberId " \ 1 \ 2 \ 3 \ 4 " )
it " x.grp.mem.new " $
2022-03-10 15:45:40 +04:00
" { \ " event \ " : \ " x.grp.mem.new \ " , \ " params \ " :{ \ " memberInfo \ " :{ \ " memberRole \ " : \ " admin \ " , \ " memberId \ " : \ " AQIDBA== \ " , \ " profile \ " :{ \ " fullName \ " : \ " Alice \ " , \ " displayName \ " : \ " alice \ " , \ " image \ " : \ " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII= \ " }}}} "
2022-01-11 12:27:57 +00:00
#==# XGrpMemNew MemberInfo { memberId = MemberId " \ 1 \ 2 \ 3 \ 4 " , memberRole = GRAdmin , profile = testProfile }
it " x.grp.mem.intro " $
2022-03-10 15:45:40 +04:00
" { \ " event \ " : \ " x.grp.mem.intro \ " , \ " params \ " :{ \ " memberInfo \ " :{ \ " memberRole \ " : \ " admin \ " , \ " memberId \ " : \ " AQIDBA== \ " , \ " profile \ " :{ \ " fullName \ " : \ " Alice \ " , \ " displayName \ " : \ " alice \ " , \ " image \ " : \ " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII= \ " }}}} "
2022-01-11 12:27:57 +00:00
#==# XGrpMemIntro MemberInfo { memberId = MemberId " \ 1 \ 2 \ 3 \ 4 " , memberRole = GRAdmin , profile = testProfile }
it " x.grp.mem.inv " $
" { \ " event \ " : \ " x.grp.mem.inv \ " , \ " params \ " :{ \ " memberId \ " : \ " AQIDBA== \ " , \ " memberIntro \ " :{ \ " directConnReq \ " : \ " https://simplex.chat/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23MCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%3D&e2e=v%3D1%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D \ " , \ " groupConnReq \ " : \ " https://simplex.chat/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23MCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%3D&e2e=v%3D1%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D \ " }}} "
#==# XGrpMemInv ( MemberId " \ 1 \ 2 \ 3 \ 4 " ) IntroInvitation { groupConnReq = testConnReq , directConnReq = testConnReq }
it " x.grp.mem.fwd " $
2022-03-10 15:45:40 +04:00
" { \ " event \ " : \ " x.grp.mem.fwd \ " , \ " params \ " :{ \ " memberIntro \ " :{ \ " directConnReq \ " : \ " https://simplex.chat/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23MCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%3D&e2e=v%3D1%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D \ " , \ " groupConnReq \ " : \ " https://simplex.chat/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23MCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%3D&e2e=v%3D1%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D \ " }, \ " memberInfo \ " :{ \ " memberRole \ " : \ " admin \ " , \ " memberId \ " : \ " AQIDBA== \ " , \ " profile \ " :{ \ " fullName \ " : \ " Alice \ " , \ " displayName \ " : \ " alice \ " , \ " image \ " : \ " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII= \ " }}}} "
2022-01-11 12:27:57 +00:00
#==# XGrpMemFwd MemberInfo { memberId = MemberId " \ 1 \ 2 \ 3 \ 4 " , memberRole = GRAdmin , profile = testProfile } IntroInvitation { groupConnReq = testConnReq , directConnReq = testConnReq }
it " x.grp.mem.info " $
2022-03-10 15:45:40 +04:00
" { \ " event \ " : \ " x.grp.mem.info \ " , \ " params \ " :{ \ " memberId \ " : \ " AQIDBA== \ " , \ " profile \ " :{ \ " fullName \ " : \ " Alice \ " , \ " displayName \ " : \ " alice \ " , \ " image \ " : \ " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII= \ " }}} "
2022-01-17 12:24:55 +00:00
#==# XGrpMemInfo ( MemberId " \ 1 \ 2 \ 3 \ 4 " ) testProfile
2022-01-11 12:27:57 +00:00
it " x.grp.mem.con " $ " { \ " event \ " : \ " x.grp.mem.con \ " , \ " params \ " :{ \ " memberId \ " : \ " AQIDBA== \ " }} " #==# XGrpMemCon ( MemberId " \ 1 \ 2 \ 3 \ 4 " )
it " x.grp.mem.con.all " $ " { \ " event \ " : \ " x.grp.mem.con.all \ " , \ " params \ " :{ \ " memberId \ " : \ " AQIDBA== \ " }} " #==# XGrpMemConAll ( MemberId " \ 1 \ 2 \ 3 \ 4 " )
it " x.grp.mem.del " $ " { \ " event \ " : \ " x.grp.mem.del \ " , \ " params \ " :{ \ " memberId \ " : \ " AQIDBA== \ " }} " #==# XGrpMemDel ( MemberId " \ 1 \ 2 \ 3 \ 4 " )
it " x.grp.leave " $ " { \ " event \ " : \ " x.grp.leave \ " , \ " params \ " :{}} " ==# XGrpLeave
it " x.grp.del " $ " { \ " event \ " : \ " x.grp.del \ " , \ " params \ " :{}} " ==# XGrpDel
it " x.info.probe " $ " { \ " event \ " : \ " x.info.probe \ " , \ " params \ " :{ \ " probe \ " : \ " AQIDBA== \ " }} " #==# XInfoProbe ( Probe " \ 1 \ 2 \ 3 \ 4 " )
it " x.info.probe.check " $ " { \ " event \ " : \ " x.info.probe.check \ " , \ " params \ " :{ \ " probeHash \ " : \ " AQIDBA== \ " }} " #==# XInfoProbeCheck ( ProbeHash " \ 1 \ 2 \ 3 \ 4 " )
it " x.info.probe.ok " $ " { \ " event \ " : \ " x.info.probe.ok \ " , \ " params \ " :{ \ " probe \ " : \ " AQIDBA== \ " }} " #==# XInfoProbeOk ( Probe " \ 1 \ 2 \ 3 \ 4 " )
it " x.ok " $ " { \ " event \ " : \ " x.ok \ " , \ " params \ " :{}} " ==# XOk