diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index a3c353a489..fd013f8339 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -252,12 +252,6 @@ func apiSetFilesFolder(filesFolder: String) throws { throw r } -func setXFTPConfig(_ cfg: XFTPFileConfig?) throws { - let r = chatSendCmdSync(.apiSetXFTPConfig(config: cfg)) - if case .cmdOk = r { return } - throw r -} - func apiSetEncryptLocalFiles(_ enable: Bool) throws { let r = chatSendCmdSync(.apiSetEncryptLocalFiles(enable: enable)) if case .cmdOk = r { return } @@ -1249,7 +1243,6 @@ func initializeChat(start: Bool, confirmStart: Bool = false, dbKey: String? = ni } try apiSetTempFolder(tempFolder: getTempFilesDirectory().path) try apiSetFilesFolder(filesFolder: getAppFilesDirectory().path) - try setXFTPConfig(getXFTPCfg()) try apiSetEncryptLocalFiles(privacyEncryptLocalFilesGroupDefault.get()) m.chatInitialized = true m.currentUser = try apiGetActiveUser() diff --git a/apps/ios/Shared/Views/UserSettings/DeveloperView.swift b/apps/ios/Shared/Views/UserSettings/DeveloperView.swift index e99c6e3301..3bbfbfe33e 100644 --- a/apps/ios/Shared/Views/UserSettings/DeveloperView.swift +++ b/apps/ios/Shared/Views/UserSettings/DeveloperView.swift @@ -42,25 +42,6 @@ struct DeveloperView: View { } footer: { (developerTools ? Text("Show:") : Text("Hide:")) + Text(" ") + Text("Database IDs and Transport isolation option.") } - -// Section { -// settingsRow("arrow.up.doc") { -// Toggle("Send videos and files via XFTP", isOn: $xftpSendEnabled) -// .onChange(of: xftpSendEnabled) { _ in -// do { -// try setXFTPConfig(getXFTPCfg()) -// } catch { -// logger.error("setXFTPConfig: cannot set XFTP config \(responseError(error))") -// } -// } -// } -// } header: { -// Text("Experimental") -// } footer: { -// if xftpSendEnabled { -// Text("v4.6.1+ is required to receive via XFTP.") -// } -// } } } } diff --git a/apps/ios/SimpleX NSE/NotificationService.swift b/apps/ios/SimpleX NSE/NotificationService.swift index 61c439fb33..67536d7b78 100644 --- a/apps/ios/SimpleX NSE/NotificationService.swift +++ b/apps/ios/SimpleX NSE/NotificationService.swift @@ -453,7 +453,6 @@ var receiverStarted = false let startLock = DispatchSemaphore(value: 1) let suspendLock = DispatchSemaphore(value: 1) var networkConfig: NetCfg = getNetCfg() -let xftpConfig: XFTPFileConfig? = getXFTPCfg() // startChat uses semaphore startLock to ensure that only one didReceive thread can start chat controller // Subsequent calls to didReceive will be waiting on semaphore and won't start chat again, as it will be .active @@ -499,7 +498,6 @@ func doStartChat() -> DBMigrationResult? { try setNetworkConfig(networkConfig) try apiSetTempFolder(tempFolder: getTempFilesDirectory().path) try apiSetFilesFolder(filesFolder: getAppFilesDirectory().path) - try setXFTPConfig(xftpConfig) try apiSetEncryptLocalFiles(privacyEncryptLocalFilesGroupDefault.get()) // prevent suspension while starting chat suspendLock.wait() @@ -733,12 +731,6 @@ func apiSetFilesFolder(filesFolder: String) throws { throw r } -func setXFTPConfig(_ cfg: XFTPFileConfig?) throws { - let r = sendSimpleXCmd(.apiSetXFTPConfig(config: cfg)) - if case .cmdOk = r { return } - throw r -} - func apiSetEncryptLocalFiles(_ enable: Bool) throws { let r = sendSimpleXCmd(.apiSetEncryptLocalFiles(enable: enable)) if case .cmdOk = r { return } diff --git a/apps/ios/SimpleXChat/APITypes.swift b/apps/ios/SimpleXChat/APITypes.swift index ae091f8415..9c5aa0da62 100644 --- a/apps/ios/SimpleXChat/APITypes.swift +++ b/apps/ios/SimpleXChat/APITypes.swift @@ -31,7 +31,6 @@ public enum ChatCommand { case apiSuspendChat(timeoutMicroseconds: Int) case setTempFolder(tempFolder: String) case setFilesFolder(filesFolder: String) - case apiSetXFTPConfig(config: XFTPFileConfig?) case apiSetEncryptLocalFiles(enable: Bool) case apiExportArchive(config: ArchiveConfig) case apiImportArchive(config: ArchiveConfig) @@ -162,11 +161,6 @@ public enum ChatCommand { case let .apiSuspendChat(timeoutMicroseconds): return "/_app suspend \(timeoutMicroseconds)" case let .setTempFolder(tempFolder): return "/_temp_folder \(tempFolder)" case let .setFilesFolder(filesFolder): return "/_files_folder \(filesFolder)" - case let .apiSetXFTPConfig(cfg): if let cfg = cfg { - return "/_xftp on \(encodeJSON(cfg))" - } else { - return "/_xftp off" - } case let .apiSetEncryptLocalFiles(enable): return "/_files_encrypt \(onOff(enable))" case let .apiExportArchive(cfg): return "/_db export \(encodeJSON(cfg))" case let .apiImportArchive(cfg): return "/_db import \(encodeJSON(cfg))" @@ -311,7 +305,6 @@ public enum ChatCommand { case .apiSuspendChat: return "apiSuspendChat" case .setTempFolder: return "setTempFolder" case .setFilesFolder: return "setFilesFolder" - case .apiSetXFTPConfig: return "apiSetXFTPConfig" case .apiSetEncryptLocalFiles: return "apiSetEncryptLocalFiles" case .apiExportArchive: return "apiExportArchive" case .apiImportArchive: return "apiImportArchive" @@ -1005,10 +998,6 @@ struct ComposedMessage: Encodable { var msgContent: MsgContent } -public struct XFTPFileConfig: Encodable { - var minFileSize: Int64 -} - public struct ArchiveConfig: Encodable { var archivePath: String var disableCompression: Bool? diff --git a/apps/ios/SimpleXChat/AppGroup.swift b/apps/ios/SimpleXChat/AppGroup.swift index f79c294e0c..ceb7d9d7db 100644 --- a/apps/ios/SimpleXChat/AppGroup.swift +++ b/apps/ios/SimpleXChat/AppGroup.swift @@ -265,10 +265,6 @@ public class Default { } } -public func getXFTPCfg() -> XFTPFileConfig { - return XFTPFileConfig(minFileSize: 0) -} - public func getNetCfg() -> NetCfg { let onionHosts = networkUseOnionHostsGroupDefault.get() let (hostMode, requiredHostMode) = onionHosts.hostMode diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt index c061d340f2..d6cea330b1 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt @@ -631,12 +631,6 @@ object ChatController { throw Error("failed to set remote hosts folder: ${r.responseType} ${r.details}") } - suspend fun apiSetXFTPConfig(cfg: XFTPFileConfig?) { - val r = sendCmd(null, CC.ApiSetXFTPConfig(cfg)) - if (r is CR.CmdOk) return - throw Error("apiSetXFTPConfig bad response: ${r.responseType} ${r.details}") - } - suspend fun apiSetEncryptLocalFiles(enable: Boolean) = sendCommandOkResp(null, CC.ApiSetEncryptLocalFiles(enable)) suspend fun apiExportArchive(config: ArchiveConfig) { @@ -2173,10 +2167,6 @@ object ChatController { } } - fun getXFTPCfg(): XFTPFileConfig { - return XFTPFileConfig(minFileSize = 0) - } - fun getNetCfg(): NetCfg { val useSocksProxy = appPrefs.networkUseSocksProxy.get() val proxyHostPort = appPrefs.networkProxyHostPort.get() @@ -2285,7 +2275,6 @@ sealed class CC { class SetTempFolder(val tempFolder: String): CC() class SetFilesFolder(val filesFolder: String): CC() class SetRemoteHostsFolder(val remoteHostsFolder: String): CC() - class ApiSetXFTPConfig(val config: XFTPFileConfig?): CC() class ApiSetEncryptLocalFiles(val enable: Boolean): CC() class ApiExportArchive(val config: ArchiveConfig): CC() class ApiImportArchive(val config: ArchiveConfig): CC() @@ -2415,7 +2404,6 @@ sealed class CC { is SetTempFolder -> "/_temp_folder $tempFolder" is SetFilesFolder -> "/_files_folder $filesFolder" is SetRemoteHostsFolder -> "/remote_hosts_folder $remoteHostsFolder" - is ApiSetXFTPConfig -> if (config != null) "/_xftp on ${json.encodeToString(config)}" else "/_xftp off" is ApiSetEncryptLocalFiles -> "/_files_encrypt ${onOff(enable)}" is ApiExportArchive -> "/_db export ${json.encodeToString(config)}" is ApiImportArchive -> "/_db import ${json.encodeToString(config)}" @@ -2550,7 +2538,6 @@ sealed class CC { is SetTempFolder -> "setTempFolder" is SetFilesFolder -> "setFilesFolder" is SetRemoteHostsFolder -> "setRemoteHostsFolder" - is ApiSetXFTPConfig -> "apiSetXFTPConfig" is ApiSetEncryptLocalFiles -> "apiSetEncryptLocalFiles" is ApiExportArchive -> "apiExportArchive" is ApiImportArchive -> "apiImportArchive" @@ -2716,9 +2703,6 @@ sealed class ChatPagination { @Serializable class ComposedMessage(val fileSource: CryptoFile?, val quotedItemId: Long?, val msgContent: MsgContent) -@Serializable -class XFTPFileConfig(val minFileSize: Long) - @Serializable class ArchiveConfig(val archivePath: String, val disableCompression: Boolean? = null, val parentTempDirectory: String? = null) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt index 63fcb90bbe..7a7c2d7f24 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt @@ -91,7 +91,6 @@ suspend fun initChatController(useKey: String? = null, confirmMigrations: Migrat if (appPlatform.isDesktop) { controller.apiSetRemoteHostsFolder(remoteHostsDir.absolutePath) } - controller.apiSetXFTPConfig(controller.getXFTPCfg()) controller.apiSetEncryptLocalFiles(controller.appPrefs.privacyEncryptLocalFiles.get()) // If we migrated successfully means previous re-encryption process on database level finished successfully too if (appPreferences.encryptionStartedAt.get() != null) appPreferences.encryptionStartedAt.set(null) diff --git a/packages/simplex-chat-client/typescript/src/command.ts b/packages/simplex-chat-client/typescript/src/command.ts index b49a3605b6..bd17a55926 100644 --- a/packages/simplex-chat-client/typescript/src/command.ts +++ b/packages/simplex-chat-client/typescript/src/command.ts @@ -12,7 +12,6 @@ export type ChatCommand = | APIStopChat | SetTempFolder | SetFilesFolder - | APISetXFTPConfig | SetIncognito | APIExportArchive | APIImportArchive @@ -112,7 +111,6 @@ type ChatCommandTag = | "apiStopChat" | "setTempFolder" | "setFilesFolder" - | "apiSetXFTPConfig" | "setIncognito" | "apiExportArchive" | "apiImportArchive" @@ -242,15 +240,6 @@ export interface SetFilesFolder extends IChatCommand { filePath: string } -export interface APISetXFTPConfig extends IChatCommand { - type: "apiSetXFTPConfig" - config?: XFTPFileConfig -} - -export interface XFTPFileConfig { - minFileSize: number -} - export interface SetIncognito extends IChatCommand { type: "setIncognito" incognito: boolean @@ -707,8 +696,6 @@ export function cmdString(cmd: ChatCommand): string { return `/_temp_folder ${cmd.tempFolder}` case "setFilesFolder": return `/_files_folder ${cmd.filePath}` - case "apiSetXFTPConfig": - return `/_xftp ${onOff(cmd.config)}${maybeJSON(cmd.config)}` case "setIncognito": return `/incognito ${onOff(cmd.incognito)}` case "apiExportArchive": diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index dcd392629c..9a0aaff0dc 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -81,7 +81,7 @@ import Simplex.Chat.Types.Util import Simplex.Chat.Util (encryptFile, shuffle) import Simplex.FileTransfer.Client.Main (maxFileSize) import Simplex.FileTransfer.Client.Presets (defaultXFTPServers) -import Simplex.FileTransfer.Description (ValidFileDescription, gb, kb, mb) +import Simplex.FileTransfer.Description (ValidFileDescription) import Simplex.FileTransfer.Protocol (FileParty (..), FilePartyI) import Simplex.Messaging.Agent as Agent import Simplex.Messaging.Agent.Client (AgentStatsKey (..), SubInfo (..), agentClientStore, getAgentWorkersDetails, getAgentWorkersSummary, temporaryAgentError) @@ -142,8 +142,6 @@ defaultChatConfig = xftpDescrPartSize = 14000, inlineFiles = defaultInlineFilesConfig, autoAcceptFileSize = 0, - xftpFileConfig = Just defaultXFTPFileConfig, - tempDir = Nothing, showReactions = False, showReceipts = False, logLevel = CLLImportant, @@ -201,7 +199,7 @@ newChatController :: ChatDatabase -> Maybe User -> ChatConfig -> ChatOpts -> Boo newChatController ChatDatabase {chatStore, agentStore} user - cfg@ChatConfig {agentConfig = aCfg, defaultServers, inlineFiles, tempDir, deviceNameForRemote} + cfg@ChatConfig {agentConfig = aCfg, defaultServers, inlineFiles, deviceNameForRemote} ChatOpts {coreOptions = CoreChatOpts {smpServers, xftpServers, networkConfig, logLevel, logConnections, logServerHosts, logFile, tbqSize, highlyAvailable}, deviceName, optFilesFolder, showReactions, allowInstantFiles, autoAcceptFileSize} backgroundMode = do let inlineFiles' = if allowInstantFiles || autoAcceptFileSize > 0 then inlineFiles else inlineFiles {sendChunks = 0, receiveInstant = False} @@ -236,8 +234,7 @@ newChatController chatActivated <- newTVarIO True showLiveItems <- newTVarIO False encryptLocalFiles <- newTVarIO False - userXFTPFileConfig <- newTVarIO $ xftpFileConfig cfg - tempDirectory <- newTVarIO tempDir + tempDirectory <- newTVarIO Nothing contactMergeEnabled <- newTVarIO True pure ChatController @@ -272,7 +269,6 @@ newChatController chatActivated, showLiveItems, encryptLocalFiles, - userXFTPFileConfig, tempDirectory, logFilePath = logFile, contactMergeEnabled @@ -582,9 +578,6 @@ processChatCommand' vr = \case createDirectoryIfMissing True rf chatWriteVar remoteHostsFolder $ Just rf ok_ - APISetXFTPConfig cfg -> do - asks userXFTPFileConfig >>= atomically . (`writeTVar` cfg) - ok_ APISetEncryptLocalFiles on -> chatWriteVar encryptLocalFiles on >> ok_ SetContactMergeEnabled onOff -> do asks contactMergeEnabled >>= atomically . (`writeTVar` onOff) @@ -645,7 +638,7 @@ processChatCommand' vr = \case memStatuses -> pure $ Just $ map (uncurry MemberDeliveryStatus) memStatuses _ -> pure Nothing pure $ CRChatItemInfo user aci ChatItemInfo {itemVersions, memberDeliveryStatuses} - APISendMessage (ChatRef cType chatId) live itemTTL (ComposedMessage file_ quotedItemId_ mc) -> withUser $ \user@User {userId} -> withChatLock "sendMessage" $ case cType of + APISendMessage (ChatRef cType chatId) live itemTTL (ComposedMessage file_ quotedItemId_ mc) -> withUser $ \user -> withChatLock "sendMessage" $ case cType of CTDirect -> do ct@Contact {contactId, contactUsed} <- withStore $ \db -> getContact db user chatId assertDirectAllowed user MDSnd ct XMsgNew_ @@ -653,45 +646,19 @@ processChatCommand' vr = \case if isVoice mc && not (featureAllowed SCFVoice forUser ct) then pure $ chatCmdError (Just user) ("feature not allowed " <> T.unpack (chatFeatureNameText CFVoice)) else do - (fInv_, ciFile_, ft_) <- unzipMaybe3 <$> setupSndFileTransfer ct + (fInv_, ciFile_) <- L.unzip <$> setupSndFileTransfer ct timed_ <- sndContactCITimed live ct itemTTL (msgContainer, quotedItem_) <- prepareMsg fInv_ timed_ - (msg@SndMessage {sharedMsgId}, _) <- sendDirectContactMessage ct (XMsgNew msgContainer) + (msg, _) <- sendDirectContactMessage ct (XMsgNew msgContainer) ci <- saveSndChatItem' user (CDDirectSnd ct) msg (CISndMsgContent mc) ciFile_ quotedItem_ timed_ live - case ft_ of - Just ft@FileTransferMeta {fileInline = Just IFMSent} -> - sendDirectFileInline ct ft sharedMsgId - _ -> pure () forM_ (timed_ >>= timedDeleteAt') $ startProximateTimedItemThread user (ChatRef CTDirect contactId, chatItemId' ci) pure $ CRNewChatItem user (AChatItem SCTDirect SMDSnd (DirectChat ct) ci) where - setupSndFileTransfer :: Contact -> m (Maybe (FileInvitation, CIFile 'MDSnd, FileTransferMeta)) + setupSndFileTransfer :: Contact -> m (Maybe (FileInvitation, CIFile 'MDSnd)) setupSndFileTransfer ct = forM file_ $ \file -> do - (fileSize, fileMode) <- checkSndFile mc file 1 - case fileMode of - SendFileSMP fileInline -> smpSndFileTransfer file fileSize fileInline - SendFileXFTP -> xftpSndFileTransfer user file fileSize 1 $ CGContact ct - where - smpSndFileTransfer :: CryptoFile -> Integer -> Maybe InlineFileMode -> m (FileInvitation, CIFile 'MDSnd, FileTransferMeta) - smpSndFileTransfer (CryptoFile _ (Just _)) _ _ = throwChatError $ CEFileInternal "locally encrypted files can't be sent via SMP" -- can only happen if XFTP is disabled - smpSndFileTransfer (CryptoFile file Nothing) fileSize fileInline = do - subMode <- chatReadVar subscriptionMode - (agentConnId_, fileConnReq) <- - if isJust fileInline - then pure (Nothing, Nothing) - else bimap Just Just <$> withAgent (\a -> createConnection a (aUserId user) True SCMInvitation Nothing subMode) - let fileName = takeFileName file - fileInvitation = FileInvitation {fileName, fileSize, fileDigest = Nothing, fileConnReq, fileInline, fileDescr = Nothing} - chSize <- asks $ fileChunkSize . config - withStore $ \db -> do - ft@FileTransferMeta {fileId} <- liftIO $ createSndDirectFileTransfer db userId ct file fileInvitation agentConnId_ chSize subMode - fileStatus <- case fileInline of - Just IFMSent -> createSndDirectInlineFT db ct ft $> CIFSSndTransfer 0 1 - _ -> pure CIFSSndStored - let fileSource = Just $ CF.plain file - ciFile = CIFile {fileId, fileName, fileSize, fileSource, fileStatus, fileProtocol = FPSMP} - pure (fileInvitation, ciFile, ft) + fileSize <- checkSndFile file + xftpSndFileTransfer user file fileSize 1 $ CGContact ct prepareMsg :: Maybe FileInvitation -> Maybe CITimed -> m (MsgContainer, Maybe (CIQuote 'CTDirect)) prepareMsg fInv_ timed_ = case quotedItemId_ of Nothing -> pure (MCSimple (ExtMsgContent mc fInv_ (ttl' <$> timed_) (justTrue live)), Nothing) @@ -718,53 +685,27 @@ processChatCommand' vr = \case | isVoice mc && not (groupFeatureAllowed SGFVoice gInfo) = notAllowedError GFVoice | not (isVoice mc) && isJust file_ && not (groupFeatureAllowed SGFFiles gInfo) = notAllowedError GFFiles | otherwise = do - (fInv_, ciFile_, ft_) <- unzipMaybe3 <$> setupSndFileTransfer g (length $ filter memberCurrent ms) + (fInv_, ciFile_) <- L.unzip <$> setupSndFileTransfer g (length $ filter memberCurrent ms) timed_ <- sndGroupCITimed live gInfo itemTTL (msgContainer, quotedItem_) <- prepareGroupMsg user gInfo mc quotedItemId_ fInv_ timed_ live - (msg@SndMessage {sharedMsgId}, sentToMembers) <- sendGroupMessage user gInfo ms (XMsgNew msgContainer) + (msg, sentToMembers) <- sendGroupMessage user gInfo ms (XMsgNew msgContainer) ci <- saveSndChatItem' user (CDGroupSnd gInfo) msg (CISndMsgContent mc) ciFile_ quotedItem_ timed_ live withStore' $ \db -> forM_ sentToMembers $ \GroupMember {groupMemberId} -> createGroupSndStatus db (chatItemId' ci) groupMemberId CISSndNew - mapM_ (sendGroupFileInline ms sharedMsgId) ft_ forM_ (timed_ >>= timedDeleteAt') $ startProximateTimedItemThread user (ChatRef CTGroup groupId, chatItemId' ci) pure $ CRNewChatItem user (AChatItem SCTGroup SMDSnd (GroupChat gInfo) ci) notAllowedError f = pure $ chatCmdError (Just user) ("feature not allowed " <> T.unpack (groupFeatureNameText f)) - setupSndFileTransfer :: Group -> Int -> m (Maybe (FileInvitation, CIFile 'MDSnd, FileTransferMeta)) - setupSndFileTransfer g@(Group gInfo _) n = forM file_ $ \file -> do - (fileSize, fileMode) <- checkSndFile mc file $ fromIntegral n - case fileMode of - SendFileSMP fileInline -> smpSndFileTransfer file fileSize fileInline - SendFileXFTP -> xftpSndFileTransfer user file fileSize n $ CGGroup g - where - smpSndFileTransfer :: CryptoFile -> Integer -> Maybe InlineFileMode -> m (FileInvitation, CIFile 'MDSnd, FileTransferMeta) - smpSndFileTransfer (CryptoFile _ (Just _)) _ _ = throwChatError $ CEFileInternal "locally encrypted files can't be sent via SMP" -- can only happen if XFTP is disabled - smpSndFileTransfer (CryptoFile file Nothing) fileSize fileInline = do - let fileName = takeFileName file - fileInvitation = FileInvitation {fileName, fileSize, fileDigest = Nothing, fileConnReq = Nothing, fileInline, fileDescr = Nothing} - fileStatus = if fileInline == Just IFMSent then CIFSSndTransfer 0 1 else CIFSSndStored - chSize <- asks $ fileChunkSize . config - withStore' $ \db -> do - ft@FileTransferMeta {fileId} <- createSndGroupFileTransfer db userId gInfo file fileInvitation chSize - let fileSource = Just $ CF.plain file - ciFile = CIFile {fileId, fileName, fileSize, fileSource, fileStatus, fileProtocol = FPSMP} - pure (fileInvitation, ciFile, ft) - sendGroupFileInline :: [GroupMember] -> SharedMsgId -> FileTransferMeta -> m () - sendGroupFileInline ms sharedMsgId ft@FileTransferMeta {fileInline} = - when (fileInline == Just IFMSent) . forM_ ms $ \m -> - processMember m `catchChatError` (toView . CRChatError (Just user)) - where - processMember m@GroupMember {activeConn = Just conn@Connection {connStatus}} = - when (connStatus == ConnReady || connStatus == ConnSndReady) $ do - void . withStore' $ \db -> createSndGroupInlineFT db m conn ft - sendMemberFileInline m conn ft sharedMsgId - processMember _ = pure () + setupSndFileTransfer :: Group -> Int -> m (Maybe (FileInvitation, CIFile 'MDSnd)) + setupSndFileTransfer g n = forM file_ $ \file -> do + fileSize <- checkSndFile file + xftpSndFileTransfer user file fileSize n $ CGGroup g CTLocal -> pure $ chatCmdError (Just user) "not supported" CTContactRequest -> pure $ chatCmdError (Just user) "not supported" CTContactConnection -> pure $ chatCmdError (Just user) "not supported" where - xftpSndFileTransfer :: User -> CryptoFile -> Integer -> Int -> ContactOrGroup -> m (FileInvitation, CIFile 'MDSnd, FileTransferMeta) + xftpSndFileTransfer :: User -> CryptoFile -> Integer -> Int -> ContactOrGroup -> m (FileInvitation, CIFile 'MDSnd) xftpSndFileTransfer user file@(CryptoFile filePath cfArgs) fileSize n contactOrGroup = do let fileName = takeFileName filePath fileDescr = FileDescr {fileDescrText = "", fileDescrPartNo = 0, fileDescrComplete = False} @@ -788,10 +729,7 @@ processChatCommand' vr = \case withStore' $ \db -> createSndFTDescrXFTP db user (Just m) conn ft fileDescr saveMemberFD _ = pure () - pure (fInv, ciFile, ft) - unzipMaybe3 :: Maybe (a, b, c) -> (Maybe a, Maybe b, Maybe c) - unzipMaybe3 (Just (a, b, c)) = (Just a, Just b, Just c) - unzipMaybe3 _ = (Nothing, Nothing, Nothing) + pure (fInv, ciFile) APICreateChatItem folderId (ComposedMessage file_ quotedItemId_ mc) -> withUser $ \user -> do forM_ quotedItemId_ $ \_ -> throwError $ ChatError $ CECommandError "not supported" nf <- withStore $ \db -> getNoteFolder db user folderId @@ -2202,27 +2140,13 @@ processChatCommand' vr = \case contactMember Contact {contactId} = find $ \GroupMember {memberContactId = cId, memberStatus = s} -> cId == Just contactId && s /= GSMemRemoved && s /= GSMemLeft - checkSndFile :: MsgContent -> CryptoFile -> Integer -> m (Integer, SendFileMode) - checkSndFile mc (CryptoFile f cfArgs) n = do + checkSndFile :: CryptoFile -> m Integer + checkSndFile (CryptoFile f cfArgs) = do fsFilePath <- toFSFilePath f unlessM (doesFileExist fsFilePath) . throwChatError $ CEFileNotFound f - ChatConfig {fileChunkSize, inlineFiles} <- asks config - xftpCfg <- readTVarIO =<< asks userXFTPFileConfig fileSize <- liftIO $ CF.getFileContentsSize $ CryptoFile fsFilePath cfArgs when (fromInteger fileSize > maxFileSize) $ throwChatError $ CEFileSize f - let chunks = -((-fileSize) `div` fileChunkSize) - fileInline = inlineFileMode mc inlineFiles chunks n - fileMode = case xftpCfg of - Just cfg - | isJust cfArgs -> SendFileXFTP - | fileInline == Just IFMSent || fileSize < minFileSize cfg || n <= 0 -> SendFileSMP fileInline - | otherwise -> SendFileXFTP - _ -> SendFileSMP fileInline - pure (fileSize, fileMode) - inlineFileMode mc InlineFilesConfig {offerChunks, sendChunks, totalSendChunks} chunks n - | chunks > offerChunks = Nothing - | chunks <= sendChunks && chunks * n <= totalSendChunks && isVoice mc = Just IFMSent - | otherwise = Just IFMOffer + pure fileSize updateProfile :: User -> Profile -> m ChatResponse updateProfile user p' = updateProfile_ user p' $ withStore $ \db -> updateUserProfile db user p' updateProfile_ :: User -> Profile -> m User -> m ChatResponse @@ -6495,8 +6419,6 @@ chatCommandP = "/_temp_folder " *> (SetTempFolder <$> filePath), ("/_files_folder " <|> "/files_folder ") *> (SetFilesFolder <$> filePath), "/remote_hosts_folder " *> (SetRemoteHostsFolder <$> filePath), - "/_xftp " *> (APISetXFTPConfig <$> ("on " *> (Just <$> jsonP) <|> ("off" $> Nothing))), - "/xftp " *> (APISetXFTPConfig <$> ("on" *> (Just <$> xftpCfgP) <|> ("off" $> Nothing))), "/_files_encrypt " *> (APISetEncryptLocalFiles <$> onOffP), "/contact_merge " *> (SetContactMergeEnabled <$> onOffP), "/_db export " *> (APIExportArchive <$> jsonP), @@ -6868,14 +6790,6 @@ chatCommandP = logErrors <- " log=" *> onOffP <|> pure False let tcpTimeout = 1000000 * fromMaybe (maybe 5 (const 10) socksProxy) t_ pure $ fullNetworkConfig socksProxy tcpTimeout logErrors - xftpCfgP = XFTPFileConfig <$> (" size=" *> fileSizeP <|> pure 0) - fileSizeP = - A.choice - [ gb <$> A.decimal <* "gb", - mb <$> A.decimal <* "mb", - kb <$> A.decimal <* "kb", - A.decimal - ] dbKeyP = nonEmptyKey <$?> strP nonEmptyKey k@(DBEncryptionKey s) = if BA.null s then Left "empty key" else Right k dbEncryptionConfig currentKey newKey = DBEncryptionConfig {currentKey, newKey, keepKey = Just False} diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index d3c8698f94..36dbae8e47 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -128,8 +128,6 @@ data ChatConfig = ChatConfig xftpDescrPartSize :: Int, inlineFiles :: InlineFilesConfig, autoAcceptFileSize :: Integer, - xftpFileConfig :: Maybe XFTPFileConfig, -- Nothing - XFTP is disabled - tempDir :: Maybe FilePath, showReactions :: Bool, showReceipts :: Bool, subscriptionEvents :: Bool, @@ -204,7 +202,6 @@ data ChatController = ChatController timedItemThreads :: TMap (ChatRef, ChatItemId) (TVar (Maybe (Weak ThreadId))), showLiveItems :: TVar Bool, encryptLocalFiles :: TVar Bool, - userXFTPFileConfig :: TVar (Maybe XFTPFileConfig), tempDirectory :: TVar (Maybe FilePath), logFilePath :: Maybe FilePath, contactMergeEnabled :: TVar Bool @@ -242,7 +239,6 @@ data ChatCommand | SetTempFolder FilePath | SetFilesFolder FilePath | SetRemoteHostsFolder FilePath - | APISetXFTPConfig (Maybe XFTPFileConfig) | APISetEncryptLocalFiles Bool | SetContactMergeEnabled Bool | APIExportArchive ArchiveConfig @@ -473,7 +469,6 @@ allowRemoteCommand = \case SetTempFolder _ -> False SetFilesFolder _ -> False SetRemoteHostsFolder _ -> False - APISetXFTPConfig _ -> False APISetEncryptLocalFiles _ -> False APIExportArchive _ -> False APIImportArchive _ -> False @@ -934,14 +929,6 @@ instance FromJSON ComposedMessage where parseJSON invalid = JT.prependFailure "bad ComposedMessage, " (JT.typeMismatch "Object" invalid) -data XFTPFileConfig = XFTPFileConfig - { minFileSize :: Integer - } - deriving (Show) - -defaultXFTPFileConfig :: XFTPFileConfig -defaultXFTPFileConfig = XFTPFileConfig {minFileSize = 0} - data NtfMsgInfo = NtfMsgInfo {msgId :: Text, msgTs :: UTCTime} deriving (Show) @@ -1001,11 +988,6 @@ data CoreVersionInfo = CoreVersionInfo } deriving (Show) -data SendFileMode - = SendFileSMP (Maybe InlineFileMode) - | SendFileXFTP - deriving (Show) - data SlowSQLQuery = SlowSQLQuery { query :: Text, queryStats :: SlowQueryStats @@ -1409,6 +1391,4 @@ $(JQ.deriveFromJSON defaultJSON ''ArchiveConfig) $(JQ.deriveFromJSON defaultJSON ''DBEncryptionConfig) -$(JQ.deriveJSON defaultJSON ''XFTPFileConfig) - $(JQ.deriveToJSON defaultJSON ''ComposedMessage) diff --git a/src/Simplex/Chat/Store/Files.hs b/src/Simplex/Chat/Store/Files.hs index bc5cec3332..d2351b4005 100644 --- a/src/Simplex/Chat/Store/Files.hs +++ b/src/Simplex/Chat/Store/Files.hs @@ -14,7 +14,6 @@ module Simplex.Chat.Store.Files ( getLiveSndFileTransfers, getLiveRcvFileTransfers, getPendingSndChunks, - createSndDirectFileTransfer, createSndDirectFTConnection, createSndGroupFileTransfer, createSndGroupFileTransferConnection, @@ -169,23 +168,6 @@ getPendingSndChunks db fileId connId = |] (fileId, connId) -createSndDirectFileTransfer :: DB.Connection -> UserId -> Contact -> FilePath -> FileInvitation -> Maybe ConnId -> Integer -> SubscriptionMode -> IO FileTransferMeta -createSndDirectFileTransfer db userId Contact {contactId} filePath FileInvitation {fileName, fileSize, fileInline} acId_ chunkSize subMode = do - currentTs <- getCurrentTime - DB.execute - db - "INSERT INTO files (user_id, contact_id, file_name, file_path, file_size, chunk_size, file_inline, ci_file_status, protocol, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?)" - ((userId, contactId, fileName, filePath, fileSize, chunkSize) :. (fileInline, CIFSSndStored, FPSMP, currentTs, currentTs)) - fileId <- insertedRowId db - forM_ acId_ $ \acId -> do - Connection {connId} <- createSndFileConnection_ db userId fileId acId subMode - let fileStatus = FSNew - DB.execute - db - "INSERT INTO snd_files (file_id, file_status, file_inline, connection_id, created_at, updated_at) VALUES (?,?,?,?,?,?)" - (fileId, fileStatus, fileInline, connId, currentTs, currentTs) - pure FileTransferMeta {fileId, xftpSndFile = Nothing, fileName, filePath, fileSize, fileInline, chunkSize, cancelled = False} - createSndDirectFTConnection :: DB.Connection -> User -> Int64 -> (CommandId, ConnId) -> SubscriptionMode -> IO () createSndDirectFTConnection db user@User {userId} fileId (cmdId, acId) subMode = do currentTs <- getCurrentTime diff --git a/tests/ChatClient.hs b/tests/ChatClient.hs index f7982c5fb4..0240648603 100644 --- a/tests/ChatClient.hs +++ b/tests/ChatClient.hs @@ -15,6 +15,7 @@ import Control.Concurrent.STM import Control.Exception (bracket, bracket_) import Control.Monad import Control.Monad.Except +import Control.Monad.Reader import Data.ByteArray (ScrubbedBytes) import Data.Functor (($>)) import Data.List (dropWhileEnd, find) @@ -22,7 +23,7 @@ import Data.Maybe (isNothing) import qualified Data.Text as T import Network.Socket import Simplex.Chat -import Simplex.Chat.Controller (ChatConfig (..), ChatController (..), ChatDatabase (..), ChatLogLevel (..)) +import Simplex.Chat.Controller (ChatCommand (..), ChatConfig (..), ChatController (..), ChatDatabase (..), ChatLogLevel (..)) import Simplex.Chat.Core import Simplex.Chat.Options import Simplex.Chat.Store @@ -129,8 +130,7 @@ testCfg = { agentConfig = testAgentCfg, showReceipts = False, testView = True, - tbqSize = 16, - xftpFileConfig = Nothing + tbqSize = 16 } testAgentCfgVPrev :: AgentConfig @@ -209,6 +209,7 @@ startTestChat_ db cfg opts user = do t <- withVirtualTerminal termSettings pure ct <- newChatTerminal t opts cc <- newChatController db (Just user) cfg opts False + void $ execChatCommand' (SetTempFolder "tests/tmp/tmp") `runReaderT` cc chatAsync <- async . runSimplexChat opts user cc $ \_u cc' -> runChatTerminal ct cc' opts atomically . unless (maintenance opts) $ readTVar (agentAsync cc) >>= \a -> when (isNothing a) retry termQ <- newTQueueIO diff --git a/tests/ChatTests/Direct.hs b/tests/ChatTests/Direct.hs index 8e7f8536ee..d17a94dbdf 100644 --- a/tests/ChatTests/Direct.hs +++ b/tests/ChatTests/Direct.hs @@ -1067,7 +1067,7 @@ testChatWorking alice bob = do alice <# "bob> hello too" testMaintenanceModeWithFiles :: HasCallStack => FilePath -> IO () -testMaintenanceModeWithFiles tmp = do +testMaintenanceModeWithFiles tmp = withXFTPServer $ do withNewTestChat tmp "bob" bobProfile $ \bob -> do withNewTestChatOpts tmp testOpts {maintenance = True} "alice" aliceProfile $ \alice -> do alice ##> "/_start" @@ -1075,12 +1075,26 @@ testMaintenanceModeWithFiles tmp = do alice ##> "/_files_folder ./tests/tmp/alice_files" alice <## "ok" connectUsers alice bob - startFileTransferWithDest' bob alice "test.jpg" "136.5 KiB / 139737 bytes" Nothing - bob <## "completed sending file 1 (test.jpg) to alice" + + bob #> "/f @alice ./tests/fixtures/test.jpg" + bob <## "use /fc 1 to cancel sending" + alice <# "bob> sends file test.jpg (136.5 KiB / 139737 bytes)" + alice <## "use /fr 1 [/ | ] to receive it" + bob <## "completed uploading file 1 (test.jpg) for alice" + + alice ##> "/fr 1" + alice + <### [ "saving file 1 from bob to test.jpg", + "started receiving file 1 (test.jpg) from bob" + ] alice <## "completed receiving file 1 (test.jpg) from bob" + src <- B.readFile "./tests/fixtures/test.jpg" - B.readFile "./tests/tmp/alice_files/test.jpg" `shouldReturn` src + dest <- B.readFile "./tests/tmp/alice_files/test.jpg" + dest `shouldBe` src + threadDelay 500000 + alice ##> "/_stop" alice <## "chat stopped" alice ##> "/_db export {\"archivePath\": \"./tests/tmp/alice-chat.zip\"}" diff --git a/tests/ChatTests/Files.hs b/tests/ChatTests/Files.hs index a6b0f56ba3..1b34f909f1 100644 --- a/tests/ChatTests/Files.hs +++ b/tests/ChatTests/Files.hs @@ -13,7 +13,7 @@ import qualified Data.Aeson as J import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Lazy.Char8 as LB import Simplex.Chat (roundedFDCount) -import Simplex.Chat.Controller (ChatConfig (..), InlineFilesConfig (..), XFTPFileConfig (..), defaultInlineFilesConfig) +import Simplex.Chat.Controller (ChatConfig (..)) import Simplex.Chat.Mobile.File import Simplex.Chat.Options (ChatOpts (..)) import Simplex.FileTransfer.Server.Env (XFTPServerConfig (..)) @@ -25,42 +25,16 @@ import Test.Hspec hiding (it) chatFileTests :: SpecWith FilePath chatFileTests = do - describe "sending and receiving files" $ do - describe "send and receive file" $ fileTestMatrix2 runTestFileTransfer - describe "send file, receive and locally encrypt file" $ fileTestMatrix2 runTestFileTransferEncrypted - it "send and receive file inline (without accepting)" testInlineFileTransfer - it "send inline file, receive (without accepting) and locally encrypt" testInlineFileTransferEncrypted - xit'' "accept inline file transfer, sender cancels during transfer" testAcceptInlineFileSndCancelDuringTransfer - it "send and receive small file inline (default config)" testSmallInlineFileTransfer - it "small file sent without acceptance is ignored in terminal by default" testSmallInlineFileIgnored - it "receive file inline with inline=on option" testReceiveInline - describe "send and receive a small file" $ fileTestMatrix2 runTestSmallFileTransfer - describe "sender cancelled file transfer before transfer" $ fileTestMatrix2 runTestFileSndCancelBeforeTransfer - it "sender cancelled file transfer during transfer" testFileSndCancelDuringTransfer - it "recipient cancelled file transfer" testFileRcvCancel - describe "send and receive file to group" $ fileTestMatrix3 runTestGroupFileTransfer - it "send and receive file inline to group (without accepting)" testInlineGroupFileTransfer - it "send and receive small file inline to group (default config)" testSmallInlineGroupFileTransfer - it "small file sent without acceptance is ignored in terminal by default" testSmallInlineGroupFileIgnored - describe "sender cancelled group file transfer before transfer" $ fileTestMatrix3 runTestGroupFileSndCancelBeforeTransfer describe "messages with files" $ do - describe "send and receive message with file" $ fileTestMatrix2 runTestMessageWithFile + it "send and receive message with file" runTestMessageWithFile it "send and receive image" testSendImage - it "sender marking chat item deleted during file transfer cancels file" testSenderMarkItemDeletedTransfer + it "sender marking chat item deleted cancels file" testSenderMarkItemDeleted it "files folder: send and receive image" testFilesFoldersSendImage - it "files folder: sender deleted file during transfer" testFilesFoldersImageSndDelete - it "files folder: recipient deleted file during transfer" testFilesFoldersImageRcvDelete + it "files folder: sender deleted file" testFilesFoldersImageSndDelete -- TODO add test deleting during upload + it "files folder: recipient deleted file" testFilesFoldersImageRcvDelete -- TODO add test deleting during download it "send and receive image with text and quote" testSendImageWithTextAndQuote it "send and receive image to group" testGroupSendImage it "send and receive image with text and quote to group" testGroupSendImageWithTextAndQuote - describe "async sending and receiving files" $ do - -- fails on CI - xit'' "send and receive file, sender restarts" testAsyncFileTransferSenderRestarts - xit'' "send and receive file, receiver restarts" testAsyncFileTransferReceiverRestarts - xdescribe "send and receive file, fully asynchronous" $ do - it "v2" testAsyncFileTransfer - it "v1" testAsyncFileTransferV1 - xit "send and receive file to group, fully asynchronous" testAsyncGroupFileTransfer describe "file transfer over XFTP" $ do it "round file description count" $ const testXFTPRoundFDCount it "send and receive file" testXFTPFileTransfer @@ -69,7 +43,6 @@ chatFileTests = do it "send and receive file in group" testXFTPGroupFileTransfer it "delete uploaded file" testXFTPDeleteUploadedFile it "delete uploaded file in group" testXFTPDeleteUploadedFileGroup - it "with changed XFTP config: send and receive file" testXFTPWithChangedConfig it "with relative paths: send and receive file" testXFTPWithRelativePaths xit' "continue receiving file after restart" testXFTPContinueRcv xit' "receive file marked to receive on chat start" testXFTPMarkToReceive @@ -78,481 +51,10 @@ chatFileTests = do it "should accept file automatically with CLI option" testAutoAcceptFile it "should prohibit file transfers in groups based on preference" testProhibitFiles -runTestFileTransfer :: HasCallStack => TestCC -> TestCC -> IO () -runTestFileTransfer alice bob = do +runTestMessageWithFile :: HasCallStack => FilePath -> IO () +runTestMessageWithFile = testChat2 aliceProfile bobProfile $ \alice bob -> withXFTPServer $ do connectUsers alice bob - startFileTransfer' alice bob "test.pdf" "266.0 KiB / 272376 bytes" - concurrentlyN_ - [ do - bob #> "@alice receiving here..." - bob <## "completed receiving file 1 (test.pdf) from alice", - alice - <### [ WithTime "bob> receiving here...", - "completed sending file 1 (test.pdf) to bob" - ] - ] - src <- B.readFile "./tests/fixtures/test.pdf" - dest <- B.readFile "./tests/tmp/test.pdf" - dest `shouldBe` src -runTestFileTransferEncrypted :: HasCallStack => TestCC -> TestCC -> IO () -runTestFileTransferEncrypted alice bob = do - connectUsers alice bob - alice #> "/f @bob ./tests/fixtures/test.pdf" - alice <## "use /fc 1 to cancel sending" - bob <# "alice> sends file test.pdf (266.0 KiB / 272376 bytes)" - bob <## "use /fr 1 [/ | ] to receive it" - bob ##> "/fr 1 encrypt=on ./tests/tmp" - bob <## "saving file 1 from alice to ./tests/tmp/test.pdf" - concurrently_ - (bob <## "started receiving file 1 (test.pdf) from alice") - (alice <## "started sending file 1 (test.pdf) to bob") - - concurrentlyN_ - [ do - bob #> "@alice receiving here..." - -- uncomment this and below to test encryption error in encryptFile - -- bob <## "cannot write file ./tests/tmp/test.pdf: test error, received file not encrypted" - bob <## "completed receiving file 1 (test.pdf) from alice", - alice - <### [ WithTime "bob> receiving here...", - "completed sending file 1 (test.pdf) to bob" - ] - ] - Just (CFArgs key nonce) <- J.decode . LB.pack <$> getTermLine bob - src <- B.readFile "./tests/fixtures/test.pdf" - -- dest <- B.readFile "./tests/tmp/test.pdf" - -- dest `shouldBe` src - Right dest <- chatReadFile "./tests/tmp/test.pdf" (strEncode key) (strEncode nonce) - LB.toStrict dest `shouldBe` src - -testInlineFileTransfer :: HasCallStack => FilePath -> IO () -testInlineFileTransfer = - testChatCfg2 cfg aliceProfile bobProfile $ \alice bob -> do - connectUsers alice bob - bob ##> "/_files_folder ./tests/tmp/" - bob <## "ok" - alice ##> "/_send @2 json {\"msgContent\":{\"type\":\"voice\", \"duration\":10, \"text\":\"\"}, \"filePath\":\"./tests/fixtures/test.jpg\"}" - alice <# "@bob voice message (00:10)" - alice <# "/f @bob ./tests/fixtures/test.jpg" - -- below is not shown in "sent" mode - -- alice <## "use /fc 1 to cancel sending" - bob <# "alice> voice message (00:10)" - bob <# "alice> sends file test.jpg (136.5 KiB / 139737 bytes)" - -- below is not shown in "sent" mode - -- bob <## "use /fr 1 [/ | ] to receive it" - bob <## "started receiving file 1 (test.jpg) from alice" - concurrently_ - (alice <## "completed sending file 1 (test.jpg) to bob") - (bob <## "completed receiving file 1 (test.jpg) from alice") - src <- B.readFile "./tests/fixtures/test.jpg" - dest <- B.readFile "./tests/tmp/test.jpg" - dest `shouldBe` src - where - cfg = testCfg {inlineFiles = defaultInlineFilesConfig {offerChunks = 100, sendChunks = 100, receiveChunks = 100}} - -testInlineFileTransferEncrypted :: HasCallStack => FilePath -> IO () -testInlineFileTransferEncrypted = - testChatCfg2 cfg aliceProfile bobProfile $ \alice bob -> do - connectUsers alice bob - bob ##> "/_files_folder ./tests/tmp/" - bob <## "ok" - bob ##> "/_files_encrypt on" - bob <## "ok" - alice ##> "/_send @2 json {\"msgContent\":{\"type\":\"voice\", \"duration\":10, \"text\":\"\"}, \"filePath\":\"./tests/fixtures/test.jpg\"}" - alice <# "@bob voice message (00:10)" - alice <# "/f @bob ./tests/fixtures/test.jpg" - -- below is not shown in "sent" mode - -- alice <## "use /fc 1 to cancel sending" - bob <# "alice> voice message (00:10)" - bob <# "alice> sends file test.jpg (136.5 KiB / 139737 bytes)" - -- below is not shown in "sent" mode - -- bob <## "use /fr 1 [/ | ] to receive it" - bob <## "started receiving file 1 (test.jpg) from alice" - concurrently_ - (alice <## "completed sending file 1 (test.jpg) to bob") - (bob <## "completed receiving file 1 (test.jpg) from alice") - Just (CFArgs key nonce) <- J.decode . LB.pack <$> getTermLine bob - src <- B.readFile "./tests/fixtures/test.jpg" - Right dest <- chatReadFile "./tests/tmp/test.jpg" (strEncode key) (strEncode nonce) - LB.toStrict dest `shouldBe` src - where - cfg = testCfg {inlineFiles = defaultInlineFilesConfig {offerChunks = 100, sendChunks = 100, receiveChunks = 100}} - -testAcceptInlineFileSndCancelDuringTransfer :: HasCallStack => FilePath -> IO () -testAcceptInlineFileSndCancelDuringTransfer = - testChatCfg2 cfg aliceProfile bobProfile $ \alice bob -> do - connectUsers alice bob - bob ##> "/_files_folder ./tests/tmp/" - bob <## "ok" - alice #> "/f @bob ./tests/fixtures/test_1MB.pdf" - alice <## "use /fc 1 to cancel sending" - bob <# "alice> sends file test_1MB.pdf (1017.7 KiB / 1042157 bytes)" - bob <## "use /fr 1 [/ | ] to receive it" - bob ##> "/fr 1 inline=on" - bob <## "saving file 1 from alice to test_1MB.pdf" - alice <## "started sending file 1 (test_1MB.pdf) to bob" - bob <## "started receiving file 1 (test_1MB.pdf) from alice" - alice ##> "/fc 1" -- test that inline file cancel doesn't delete contact connection - concurrentlyN_ - [ do - alice <##. "cancelled sending file 1 (test_1MB.pdf)" - alice <## "completed sending file 1 (test_1MB.pdf) to bob", - bob <## "completed receiving file 1 (test_1MB.pdf) from alice" - ] - alice #> "@bob hi" - bob <# "alice> hi" - bob #> "@alice hey" - alice <# "bob> hey" - where - cfg = testCfg {inlineFiles = defaultInlineFilesConfig {offerChunks = 100, receiveChunks = 50}} - -testSmallInlineFileTransfer :: HasCallStack => FilePath -> IO () -testSmallInlineFileTransfer = - testChat2 aliceProfile bobProfile $ \alice bob -> do - connectUsers alice bob - bob ##> "/_files_folder ./tests/tmp/" - bob <## "ok" - alice ##> "/_send @2 json {\"msgContent\":{\"type\":\"voice\", \"duration\":10, \"text\":\"\"}, \"filePath\":\"./tests/fixtures/logo.jpg\"}" - alice <# "@bob voice message (00:10)" - alice <# "/f @bob ./tests/fixtures/logo.jpg" - -- below is not shown in "sent" mode - -- alice <## "use /fc 1 to cancel sending" - bob <# "alice> voice message (00:10)" - bob <# "alice> sends file logo.jpg (31.3 KiB / 32080 bytes)" - -- below is not shown in "sent" mode - -- bob <## "use /fr 1 [/ | ] to receive it" - bob <## "started receiving file 1 (logo.jpg) from alice" - concurrently_ - (alice <## "completed sending file 1 (logo.jpg) to bob") - (bob <## "completed receiving file 1 (logo.jpg) from alice") - src <- B.readFile "./tests/fixtures/logo.jpg" - dest <- B.readFile "./tests/tmp/logo.jpg" - dest `shouldBe` src - -testSmallInlineFileIgnored :: HasCallStack => FilePath -> IO () -testSmallInlineFileIgnored tmp = do - withNewTestChat tmp "alice" aliceProfile $ \alice -> - withNewTestChatOpts tmp testOpts {allowInstantFiles = False} "bob" bobProfile $ \bob -> do - connectUsers alice bob - bob ##> "/_files_folder ./tests/tmp/" - bob <## "ok" - alice ##> "/_send @2 json {\"msgContent\":{\"type\":\"voice\", \"duration\":10, \"text\":\"\"}, \"filePath\":\"./tests/fixtures/logo.jpg\"}" - alice <# "@bob voice message (00:10)" - alice <# "/f @bob ./tests/fixtures/logo.jpg" - -- below is not shown in "sent" mode - -- alice <## "use /fc 1 to cancel sending" - bob <# "alice> voice message (00:10)" - bob <# "alice> sends file logo.jpg (31.3 KiB / 32080 bytes)" - bob <## "use /fr 1 [/ | ] to receive it" - bob <## "A small file sent without acceptance - you can enable receiving such files with -f option." - -- below is not shown in "sent" mode - -- bob <## "use /fr 1 [/ | ] to receive it" - alice <## "completed sending file 1 (logo.jpg) to bob" - bob ##> "/fr 1" - bob <## "file is already being received: logo.jpg" - -testReceiveInline :: HasCallStack => FilePath -> IO () -testReceiveInline = - testChatCfg2 cfg aliceProfile bobProfile $ \alice bob -> do - connectUsers alice bob - alice #> "/f @bob ./tests/fixtures/test.jpg" - alice <## "use /fc 1 to cancel sending" - bob <# "alice> sends file test.jpg (136.5 KiB / 139737 bytes)" - bob <## "use /fr 1 [/ | ] to receive it" - bob ##> "/fr 1 inline=on ./tests/tmp" - bob <## "saving file 1 from alice to ./tests/tmp/test.jpg" - alice <## "started sending file 1 (test.jpg) to bob" - alice <## "completed sending file 1 (test.jpg) to bob" - bob <## "started receiving file 1 (test.jpg) from alice" - bob <## "completed receiving file 1 (test.jpg) from alice" - src <- B.readFile "./tests/fixtures/test.jpg" - dest <- B.readFile "./tests/tmp/test.jpg" - dest `shouldBe` src - where - cfg = testCfg {inlineFiles = defaultInlineFilesConfig {offerChunks = 10, receiveChunks = 5}} - -runTestSmallFileTransfer :: HasCallStack => TestCC -> TestCC -> IO () -runTestSmallFileTransfer alice bob = do - connectUsers alice bob - alice #> "/f @bob ./tests/fixtures/test.txt" - alice <## "use /fc 1 to cancel sending" - bob <# "alice> sends file test.txt (11 bytes / 11 bytes)" - bob <## "use /fr 1 [/ | ] to receive it" - bob ##> "/fr 1 ./tests/tmp" - bob <## "saving file 1 from alice to ./tests/tmp/test.txt" - concurrentlyN_ - [ do - bob <## "started receiving file 1 (test.txt) from alice" - bob <## "completed receiving file 1 (test.txt) from alice", - do - alice <## "started sending file 1 (test.txt) to bob" - alice <## "completed sending file 1 (test.txt) to bob" - ] - src <- B.readFile "./tests/fixtures/test.txt" - dest <- B.readFile "./tests/tmp/test.txt" - dest `shouldBe` src - -runTestFileSndCancelBeforeTransfer :: HasCallStack => TestCC -> TestCC -> IO () -runTestFileSndCancelBeforeTransfer alice bob = do - connectUsers alice bob - alice #> "/f @bob ./tests/fixtures/test.txt" - alice <## "use /fc 1 to cancel sending" - bob <# "alice> sends file test.txt (11 bytes / 11 bytes)" - bob <## "use /fr 1 [/ | ] to receive it" - alice ##> "/fc 1" - concurrentlyN_ - [ alice <##. "cancelled sending file 1 (test.txt)", - bob <## "alice cancelled sending file 1 (test.txt)" - ] - alice ##> "/fs 1" - alice - <##.. [ "sending file 1 (test.txt): no file transfers", - "sending file 1 (test.txt) cancelled: bob" - ] - alice <## "file transfer cancelled" - bob ##> "/fs 1" - bob <## "receiving file 1 (test.txt) cancelled" - bob ##> "/fr 1 ./tests/tmp" - bob <## "file cancelled: test.txt" - -testFileSndCancelDuringTransfer :: HasCallStack => FilePath -> IO () -testFileSndCancelDuringTransfer = - testChat2 aliceProfile bobProfile $ - \alice bob -> do - connectUsers alice bob - startFileTransfer' alice bob "test_1MB.pdf" "1017.7 KiB / 1042157 bytes" - alice ##> "/fc 1" - concurrentlyN_ - [ do - alice <## "cancelled sending file 1 (test_1MB.pdf) to bob" - alice ##> "/fs 1" - alice <## "sending file 1 (test_1MB.pdf) cancelled: bob" - alice <## "file transfer cancelled", - do - bob <## "alice cancelled sending file 1 (test_1MB.pdf)" - bob ##> "/fs 1" - bob <## "receiving file 1 (test_1MB.pdf) cancelled, received part path: ./tests/tmp/test_1MB.pdf" - ] - checkPartialTransfer "test_1MB.pdf" - -testFileRcvCancel :: HasCallStack => FilePath -> IO () -testFileRcvCancel = - testChat2 aliceProfile bobProfile $ - \alice bob -> do - connectUsers alice bob - startFileTransfer alice bob - bob ##> "/fs 1" - getTermLine bob >>= (`shouldStartWith` "receiving file 1 (test.jpg) progress") - waitFileExists "./tests/tmp/test.jpg" - bob ##> "/fc 1" - concurrentlyN_ - [ do - bob <## "cancelled receiving file 1 (test.jpg) from alice" - bob ##> "/fs 1" - bob <## "receiving file 1 (test.jpg) cancelled, received part path: ./tests/tmp/test.jpg", - do - alice <## "bob cancelled receiving file 1 (test.jpg)" - alice ##> "/fs 1" - alice <## "sending file 1 (test.jpg) cancelled: bob" - alice <## "file transfer cancelled" - ] - checkPartialTransfer "test.jpg" - -runTestGroupFileTransfer :: HasCallStack => TestCC -> TestCC -> TestCC -> IO () -runTestGroupFileTransfer alice bob cath = do - createGroup3 "team" alice bob cath - alice #> "/f #team ./tests/fixtures/test.jpg" - alice <## "use /fc 1 to cancel sending" - concurrentlyN_ - [ do - bob <# "#team alice> sends file test.jpg (136.5 KiB / 139737 bytes)" - bob <## "use /fr 1 [/ | ] to receive it", - do - cath <# "#team alice> sends file test.jpg (136.5 KiB / 139737 bytes)" - cath <## "use /fr 1 [/ | ] to receive it" - ] - alice ##> "/fs 1" - getTermLine alice >>= (`shouldStartWith` "sending file 1 (test.jpg): no file transfers") - bob ##> "/fr 1 ./tests/tmp/" - bob <## "saving file 1 from alice to ./tests/tmp/test.jpg" - concurrentlyN_ - [ do - alice <## "started sending file 1 (test.jpg) to bob" - alice <## "completed sending file 1 (test.jpg) to bob" - alice ##> "/fs 1" - alice <## "sending file 1 (test.jpg) complete: bob", - do - bob <## "started receiving file 1 (test.jpg) from alice" - bob <## "completed receiving file 1 (test.jpg) from alice" - ] - cath ##> "/fr 1 ./tests/tmp/" - cath <## "saving file 1 from alice to ./tests/tmp/test_1.jpg" - concurrentlyN_ - [ do - alice <## "started sending file 1 (test.jpg) to cath" - alice <## "completed sending file 1 (test.jpg) to cath" - alice ##> "/fs 1" - getTermLine alice >>= (`shouldStartWith` "sending file 1 (test.jpg) complete"), - do - cath <## "started receiving file 1 (test.jpg) from alice" - cath <## "completed receiving file 1 (test.jpg) from alice" - ] - src <- B.readFile "./tests/fixtures/test.jpg" - dest1 <- B.readFile "./tests/tmp/test.jpg" - dest2 <- B.readFile "./tests/tmp/test_1.jpg" - dest1 `shouldBe` src - dest2 `shouldBe` src - -testInlineGroupFileTransfer :: HasCallStack => FilePath -> IO () -testInlineGroupFileTransfer = - testChatCfg3 cfg aliceProfile bobProfile cathProfile $ - \alice bob cath -> do - createGroup3 "team" alice bob cath - bob ##> "/_files_folder ./tests/tmp/bob/" - bob <## "ok" - cath ##> "/_files_folder ./tests/tmp/cath/" - cath <## "ok" - alice ##> "/_send #1 json {\"msgContent\":{\"type\":\"voice\", \"duration\":10, \"text\":\"\"}, \"filePath\":\"./tests/fixtures/logo.jpg\"}" - alice <# "#team voice message (00:10)" - alice <# "/f #team ./tests/fixtures/logo.jpg" - -- below is not shown in "sent" mode - -- alice <## "use /fc 1 to cancel sending" - concurrentlyN_ - [ do - alice - <### [ "completed sending file 1 (logo.jpg) to bob", - "completed sending file 1 (logo.jpg) to cath" - ] - alice ##> "/fs 1" - alice <##. "sending file 1 (logo.jpg) complete", - do - bob <# "#team alice> voice message (00:10)" - bob <# "#team alice> sends file logo.jpg (31.3 KiB / 32080 bytes)" - bob <## "started receiving file 1 (logo.jpg) from alice" - bob <## "completed receiving file 1 (logo.jpg) from alice", - do - cath <# "#team alice> voice message (00:10)" - cath <# "#team alice> sends file logo.jpg (31.3 KiB / 32080 bytes)" - cath <## "started receiving file 1 (logo.jpg) from alice" - cath <## "completed receiving file 1 (logo.jpg) from alice" - ] - src <- B.readFile "./tests/fixtures/logo.jpg" - dest1 <- B.readFile "./tests/tmp/bob/logo.jpg" - dest2 <- B.readFile "./tests/tmp/cath/logo.jpg" - dest1 `shouldBe` src - dest2 `shouldBe` src - where - cfg = testCfg {inlineFiles = defaultInlineFilesConfig {offerChunks = 100, sendChunks = 100, totalSendChunks = 100, receiveChunks = 100}} - -testSmallInlineGroupFileTransfer :: HasCallStack => FilePath -> IO () -testSmallInlineGroupFileTransfer = - testChatCfg3 testCfg aliceProfile bobProfile cathProfile $ - \alice bob cath -> do - createGroup3 "team" alice bob cath - bob ##> "/_files_folder ./tests/tmp/bob/" - bob <## "ok" - cath ##> "/_files_folder ./tests/tmp/cath/" - cath <## "ok" - alice ##> "/_send #1 json {\"msgContent\":{\"type\":\"voice\", \"duration\":10, \"text\":\"\"}, \"filePath\":\"./tests/fixtures/logo.jpg\"}" - alice <# "#team voice message (00:10)" - alice <# "/f #team ./tests/fixtures/logo.jpg" - -- below is not shown in "sent" mode - -- alice <## "use /fc 1 to cancel sending" - concurrentlyN_ - [ do - alice - <### [ "completed sending file 1 (logo.jpg) to bob", - "completed sending file 1 (logo.jpg) to cath" - ] - alice ##> "/fs 1" - alice <##. "sending file 1 (logo.jpg) complete", - do - bob <# "#team alice> voice message (00:10)" - bob <# "#team alice> sends file logo.jpg (31.3 KiB / 32080 bytes)" - bob <## "started receiving file 1 (logo.jpg) from alice" - bob <## "completed receiving file 1 (logo.jpg) from alice", - do - cath <# "#team alice> voice message (00:10)" - cath <# "#team alice> sends file logo.jpg (31.3 KiB / 32080 bytes)" - cath <## "started receiving file 1 (logo.jpg) from alice" - cath <## "completed receiving file 1 (logo.jpg) from alice" - ] - src <- B.readFile "./tests/fixtures/logo.jpg" - dest1 <- B.readFile "./tests/tmp/bob/logo.jpg" - dest2 <- B.readFile "./tests/tmp/cath/logo.jpg" - dest1 `shouldBe` src - dest2 `shouldBe` src - -testSmallInlineGroupFileIgnored :: HasCallStack => FilePath -> IO () -testSmallInlineGroupFileIgnored tmp = do - withNewTestChat tmp "alice" aliceProfile $ \alice -> - withNewTestChatOpts tmp testOpts {allowInstantFiles = False} "bob" bobProfile $ \bob -> do - withNewTestChatOpts tmp testOpts {allowInstantFiles = False} "cath" cathProfile $ \cath -> do - createGroup3 "team" alice bob cath - bob ##> "/_files_folder ./tests/tmp/bob/" - bob <## "ok" - cath ##> "/_files_folder ./tests/tmp/cath/" - cath <## "ok" - alice ##> "/_send #1 json {\"msgContent\":{\"type\":\"voice\", \"duration\":10, \"text\":\"\"}, \"filePath\":\"./tests/fixtures/logo.jpg\"}" - alice <# "#team voice message (00:10)" - alice <# "/f #team ./tests/fixtures/logo.jpg" - -- below is not shown in "sent" mode - -- alice <## "use /fc 1 to cancel sending" - concurrentlyN_ - [ do - alice - <### [ "completed sending file 1 (logo.jpg) to bob", - "completed sending file 1 (logo.jpg) to cath" - ] - alice ##> "/fs 1" - alice <##. "sending file 1 (logo.jpg) complete", - do - bob <# "#team alice> voice message (00:10)" - bob <# "#team alice> sends file logo.jpg (31.3 KiB / 32080 bytes)" - bob <## "use /fr 1 [/ | ] to receive it" - bob <## "A small file sent without acceptance - you can enable receiving such files with -f option." - bob ##> "/fr 1" - bob <## "file is already being received: logo.jpg", - do - cath <# "#team alice> voice message (00:10)" - cath <# "#team alice> sends file logo.jpg (31.3 KiB / 32080 bytes)" - cath <## "use /fr 1 [/ | ] to receive it" - cath <## "A small file sent without acceptance - you can enable receiving such files with -f option." - cath ##> "/fr 1" - cath <## "file is already being received: logo.jpg" - ] - -runTestGroupFileSndCancelBeforeTransfer :: HasCallStack => TestCC -> TestCC -> TestCC -> IO () -runTestGroupFileSndCancelBeforeTransfer alice bob cath = do - createGroup3 "team" alice bob cath - alice #> "/f #team ./tests/fixtures/test.txt" - alice <## "use /fc 1 to cancel sending" - concurrentlyN_ - [ do - bob <# "#team alice> sends file test.txt (11 bytes / 11 bytes)" - bob <## "use /fr 1 [/ | ] to receive it", - do - cath <# "#team alice> sends file test.txt (11 bytes / 11 bytes)" - cath <## "use /fr 1 [/ | ] to receive it" - ] - alice ##> "/fc 1" - concurrentlyN_ - [ alice <## "cancelled sending file 1 (test.txt)", - bob <## "alice cancelled sending file 1 (test.txt)", - cath <## "alice cancelled sending file 1 (test.txt)" - ] - alice ##> "/fs 1" - alice <## "sending file 1 (test.txt): no file transfers" - alice <## "file transfer cancelled" - bob ##> "/fs 1" - bob <## "receiving file 1 (test.txt) cancelled" - bob ##> "/fr 1 ./tests/tmp" - bob <## "file cancelled: test.txt" - -runTestMessageWithFile :: HasCallStack => TestCC -> TestCC -> IO () -runTestMessageWithFile alice bob = do - connectUsers alice bob alice ##> "/_send @2 json {\"filePath\": \"./tests/fixtures/test.jpg\", \"msgContent\": {\"type\": \"text\", \"text\": \"hi, sending a file\"}}" alice <# "@bob hi, sending a file" alice <# "/f @bob ./tests/fixtures/test.jpg" @@ -560,14 +62,15 @@ runTestMessageWithFile alice bob = do bob <# "alice> hi, sending a file" bob <# "alice> sends file test.jpg (136.5 KiB / 139737 bytes)" bob <## "use /fr 1 [/ | ] to receive it" + alice <## "completed uploading file 1 (test.jpg) for bob" + bob ##> "/fr 1 ./tests/tmp" - bob <## "saving file 1 from alice to ./tests/tmp/test.jpg" - concurrently_ - (bob <## "started receiving file 1 (test.jpg) from alice") - (alice <## "started sending file 1 (test.jpg) to bob") - concurrently_ - (bob <## "completed receiving file 1 (test.jpg) from alice") - (alice <## "completed sending file 1 (test.jpg) to bob") + bob + <### [ "saving file 1 from alice to ./tests/tmp/test.jpg", + "started receiving file 1 (test.jpg) from alice" + ] + bob <## "completed receiving file 1 (test.jpg) from alice" + src <- B.readFile "./tests/fixtures/test.jpg" dest <- B.readFile "./tests/tmp/test.jpg" dest `shouldBe` src @@ -577,21 +80,22 @@ runTestMessageWithFile alice bob = do testSendImage :: HasCallStack => FilePath -> IO () testSendImage = testChat2 aliceProfile bobProfile $ - \alice bob -> do + \alice bob -> withXFTPServer $ do connectUsers alice bob alice ##> "/_send @2 json {\"filePath\": \"./tests/fixtures/test.jpg\", \"msgContent\": {\"text\":\"\",\"type\":\"image\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\"}}" alice <# "/f @bob ./tests/fixtures/test.jpg" alice <## "use /fc 1 to cancel sending" bob <# "alice> sends file test.jpg (136.5 KiB / 139737 bytes)" bob <## "use /fr 1 [/ | ] to receive it" + alice <## "completed uploading file 1 (test.jpg) for bob" + bob ##> "/fr 1 ./tests/tmp" - bob <## "saving file 1 from alice to ./tests/tmp/test.jpg" - concurrently_ - (bob <## "started receiving file 1 (test.jpg) from alice") - (alice <## "started sending file 1 (test.jpg) to bob") - concurrently_ - (bob <## "completed receiving file 1 (test.jpg) from alice") - (alice <## "completed sending file 1 (test.jpg) to bob") + bob + <### [ "saving file 1 from alice to ./tests/tmp/test.jpg", + "started receiving file 1 (test.jpg) from alice" + ] + bob <## "completed receiving file 1 (test.jpg) from alice" + src <- B.readFile "./tests/fixtures/test.jpg" dest <- B.readFile "./tests/tmp/test.jpg" dest `shouldBe` src @@ -604,10 +108,10 @@ testSendImage = fileExists <- doesFileExist "./tests/tmp/test.jpg" fileExists `shouldBe` True -testSenderMarkItemDeletedTransfer :: HasCallStack => FilePath -> IO () -testSenderMarkItemDeletedTransfer = +testSenderMarkItemDeleted :: HasCallStack => FilePath -> IO () +testSenderMarkItemDeleted = testChat2 aliceProfile bobProfile $ - \alice bob -> do + \alice bob -> withXFTPServer $ do connectUsers alice bob alice ##> "/_send @2 json {\"filePath\": \"./tests/fixtures/test_1MB.pdf\", \"msgContent\": {\"type\": \"text\", \"text\": \"hi, sending a file\"}}" alice <# "@bob hi, sending a file" @@ -616,28 +120,21 @@ testSenderMarkItemDeletedTransfer = bob <# "alice> hi, sending a file" bob <# "alice> sends file test_1MB.pdf (1017.7 KiB / 1042157 bytes)" bob <## "use /fr 1 [/ | ] to receive it" - bob ##> "/fr 1 ./tests/tmp" - bob <## "saving file 1 from alice to ./tests/tmp/test_1MB.pdf" - concurrently_ - (bob <## "started receiving file 1 (test_1MB.pdf) from alice") - (alice <## "started sending file 1 (test_1MB.pdf) to bob") + alice <## "completed uploading file 1 (test_1MB.pdf) for bob" alice #$> ("/_delete item @2 " <> itemId 1 <> " broadcast", id, "message marked deleted") - - alice ##> "/fs 1" - alice <## "sending file 1 (test_1MB.pdf) cancelled: bob" - alice <## "file transfer cancelled" - bob <# "alice> [marked deleted] hi, sending a file" - bob ##> "/fs 1" - bob <## "receiving file 1 (test_1MB.pdf) cancelled, received part path: ./tests/tmp/test_1MB.pdf" - checkPartialTransfer "test_1MB.pdf" + bob ##> "/fr 1 ./tests/tmp" + bob <## "file cancelled: test_1MB.pdf" + + bob ##> "/fs 1" + bob <## "receiving file 1 (test_1MB.pdf) cancelled" testFilesFoldersSendImage :: HasCallStack => FilePath -> IO () testFilesFoldersSendImage = testChat2 aliceProfile bobProfile $ - \alice bob -> do + \alice bob -> withXFTPServer $ do connectUsers alice bob alice #$> ("/_files_folder ./tests/fixtures", id, "ok") bob #$> ("/_files_folder ./tests/tmp/app_files", id, "ok") @@ -646,14 +143,15 @@ testFilesFoldersSendImage = alice <## "use /fc 1 to cancel sending" bob <# "alice> sends file test.jpg (136.5 KiB / 139737 bytes)" bob <## "use /fr 1 [/ | ] to receive it" + alice <## "completed uploading file 1 (test.jpg) for bob" + bob ##> "/fr 1" - bob <## "saving file 1 from alice to test.jpg" - concurrently_ - (bob <## "started receiving file 1 (test.jpg) from alice") - (alice <## "started sending file 1 (test.jpg) to bob") - concurrently_ - (bob <## "completed receiving file 1 (test.jpg) from alice") - (alice <## "completed sending file 1 (test.jpg) to bob") + bob + <### [ "saving file 1 from alice to test.jpg", + "started receiving file 1 (test.jpg) from alice" + ] + bob <## "completed receiving file 1 (test.jpg) from alice" + src <- B.readFile "./tests/fixtures/test.jpg" dest <- B.readFile "./tests/tmp/app_files/test.jpg" dest `shouldBe` src @@ -668,7 +166,7 @@ testFilesFoldersSendImage = testFilesFoldersImageSndDelete :: HasCallStack => FilePath -> IO () testFilesFoldersImageSndDelete = testChat2 aliceProfile bobProfile $ - \alice bob -> do + \alice bob -> withXFTPServer $ do connectUsers alice bob alice #$> ("/_files_folder ./tests/tmp/alice_app_files", id, "ok") copyFile "./tests/fixtures/test_1MB.pdf" "./tests/tmp/alice_app_files/test_1MB.pdf" @@ -678,19 +176,22 @@ testFilesFoldersImageSndDelete = alice <## "use /fc 1 to cancel sending" bob <# "alice> sends file test_1MB.pdf (1017.7 KiB / 1042157 bytes)" bob <## "use /fr 1 [/ | ] to receive it" + alice <## "completed uploading file 1 (test_1MB.pdf) for bob" + bob ##> "/fr 1" - bob <## "saving file 1 from alice to test_1MB.pdf" - concurrently_ - (bob <## "started receiving file 1 (test_1MB.pdf) from alice") - (alice <## "started sending file 1 (test_1MB.pdf) to bob") - -- deleting contact should cancel and remove file + bob + <### [ "saving file 1 from alice to test_1MB.pdf", + "started receiving file 1 (test_1MB.pdf) from alice" + ] + bob <## "completed receiving file 1 (test_1MB.pdf) from alice" + + -- deleting contact should remove file checkActionDeletesFile "./tests/tmp/alice_app_files/test_1MB.pdf" $ do alice ##> "/d bob" alice <## "bob: contact is deleted" bob <## "alice (Alice) deleted contact with you" bob ##> "/fs 1" - bob <##. "receiving file 1 (test_1MB.pdf) progress" - -- deleting contact should remove cancelled file + bob <##. "receiving file 1 (test_1MB.pdf) complete" checkActionDeletesFile "./tests/tmp/bob_app_files/test_1MB.pdf" $ do bob ##> "/d alice" bob <## "alice: contact is deleted" @@ -698,7 +199,7 @@ testFilesFoldersImageSndDelete = testFilesFoldersImageRcvDelete :: HasCallStack => FilePath -> IO () testFilesFoldersImageRcvDelete = testChat2 aliceProfile bobProfile $ - \alice bob -> do + \alice bob -> withXFTPServer $ do connectUsers alice bob alice #$> ("/_files_folder ./tests/fixtures", id, "ok") bob #$> ("/_files_folder ./tests/tmp/app_files", id, "ok") @@ -707,28 +208,25 @@ testFilesFoldersImageRcvDelete = alice <## "use /fc 1 to cancel sending" bob <# "alice> sends file test.jpg (136.5 KiB / 139737 bytes)" bob <## "use /fr 1 [/ | ] to receive it" + alice <## "completed uploading file 1 (test.jpg) for bob" + bob ##> "/fr 1" - bob <## "saving file 1 from alice to test.jpg" - concurrently_ - (bob <## "started receiving file 1 (test.jpg) from alice") - (alice <## "started sending file 1 (test.jpg) to bob") - -- deleting contact should cancel and remove file - waitFileExists "./tests/tmp/app_files/test.jpg" + bob + <### [ "saving file 1 from alice to test.jpg", + "started receiving file 1 (test.jpg) from alice" + ] + bob <## "completed receiving file 1 (test.jpg) from alice" + + -- deleting contact should remove file checkActionDeletesFile "./tests/tmp/app_files/test.jpg" $ do bob ##> "/d alice" bob <## "alice: contact is deleted" - alice - <### [ "bob (Bob) deleted contact with you", - "bob cancelled receiving file 1 (test.jpg)" - ] - alice ##> "/fs 1" - alice <## "sending file 1 (test.jpg) cancelled: bob" - alice <## "file transfer cancelled" + alice <## "bob (Bob) deleted contact with you" testSendImageWithTextAndQuote :: HasCallStack => FilePath -> IO () testSendImageWithTextAndQuote = testChat2 aliceProfile bobProfile $ - \alice bob -> do + \alice bob -> withXFTPServer $ do connectUsers alice bob bob #> "@alice hi alice" alice <# "bob> hi alice" @@ -741,20 +239,22 @@ testSendImageWithTextAndQuote = bob <## " hey bob" bob <# "alice> sends file test.jpg (136.5 KiB / 139737 bytes)" bob <## "use /fr 1 [/ | ] to receive it" + alice <## "completed uploading file 1 (test.jpg) for bob" + bob ##> "/fr 1 ./tests/tmp" - bob <## "saving file 1 from alice to ./tests/tmp/test.jpg" - concurrently_ - (bob <## "started receiving file 1 (test.jpg) from alice") - (alice <## "started sending file 1 (test.jpg) to bob") - concurrently_ - (bob <## "completed receiving file 1 (test.jpg) from alice") - (alice <## "completed sending file 1 (test.jpg) to bob") + bob + <### [ "saving file 1 from alice to ./tests/tmp/test.jpg", + "started receiving file 1 (test.jpg) from alice" + ] + bob <## "completed receiving file 1 (test.jpg) from alice" + src <- B.readFile "./tests/fixtures/test.jpg" B.readFile "./tests/tmp/test.jpg" `shouldReturn` src alice #$> ("/_get chat @2 count=100", chat'', chatFeatures'' <> [((0, "hi alice"), Nothing, Nothing), ((1, "hey bob"), Just (0, "hi alice"), Just "./tests/fixtures/test.jpg")]) alice @@@ [("@bob", "hey bob")] bob #$> ("/_get chat @2 count=100", chat'', chatFeatures'' <> [((1, "hi alice"), Nothing, Nothing), ((0, "hey bob"), Just (1, "hi alice"), Just "./tests/tmp/test.jpg")]) bob @@@ [("@alice", "hey bob")] + -- quoting (file + text) with file uses quoted text bob ##> ("/_send @2 json {\"filePath\": \"./tests/fixtures/test.pdf\", \"quotedItemId\": " <> itemId 2 <> ", \"msgContent\": {\"text\":\"\",\"type\":\"file\"}}") bob <# "@alice > hey bob" @@ -765,16 +265,18 @@ testSendImageWithTextAndQuote = alice <## " test.pdf" alice <# "bob> sends file test.pdf (266.0 KiB / 272376 bytes)" alice <## "use /fr 2 [/ | ] to receive it" + bob <## "completed uploading file 2 (test.pdf) for alice" + alice ##> "/fr 2 ./tests/tmp" - alice <## "saving file 2 from bob to ./tests/tmp/test.pdf" - concurrently_ - (alice <## "started receiving file 2 (test.pdf) from bob") - (bob <## "started sending file 2 (test.pdf) to alice") - concurrently_ - (alice <## "completed receiving file 2 (test.pdf) from bob") - (bob <## "completed sending file 2 (test.pdf) to alice") + alice + <### [ "saving file 2 from bob to ./tests/tmp/test.pdf", + "started receiving file 2 (test.pdf) from bob" + ] + alice <## "completed receiving file 2 (test.pdf) from bob" + txtSrc <- B.readFile "./tests/fixtures/test.pdf" B.readFile "./tests/tmp/test.pdf" `shouldReturn` txtSrc + -- quoting (file without text) with file uses file name alice ##> ("/_send @2 json {\"filePath\": \"./tests/fixtures/test.jpg\", \"quotedItemId\": " <> itemId 3 <> ", \"msgContent\": {\"text\":\"\",\"type\":\"image\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\"}}") alice <# "@bob > test.pdf" @@ -785,20 +287,21 @@ testSendImageWithTextAndQuote = bob <## " test.jpg" bob <# "alice> sends file test.jpg (136.5 KiB / 139737 bytes)" bob <## "use /fr 3 [/ | ] to receive it" + alice <## "completed uploading file 3 (test.jpg) for bob" + bob ##> "/fr 3 ./tests/tmp" - bob <## "saving file 3 from alice to ./tests/tmp/test_1.jpg" - concurrently_ - (bob <## "started receiving file 3 (test.jpg) from alice") - (alice <## "started sending file 3 (test.jpg) to bob") - concurrently_ - (bob <## "completed receiving file 3 (test.jpg) from alice") - (alice <## "completed sending file 3 (test.jpg) to bob") + bob + <### [ "saving file 3 from alice to ./tests/tmp/test_1.jpg", + "started receiving file 3 (test.jpg) from alice" + ] + bob <## "completed receiving file 3 (test.jpg) from alice" + B.readFile "./tests/tmp/test_1.jpg" `shouldReturn` src testGroupSendImage :: HasCallStack => FilePath -> IO () testGroupSendImage = testChat3 aliceProfile bobProfile cathProfile $ - \alice bob cath -> do + \alice bob cath -> withXFTPServer $ do createGroup3 "team" alice bob cath threadDelay 1000000 alice ##> "/_send #1 json {\"filePath\": \"./tests/fixtures/test.jpg\", \"msgContent\": {\"text\":\"\",\"type\":\"image\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\"}}" @@ -812,26 +315,22 @@ testGroupSendImage = cath <# "#team alice> sends file test.jpg (136.5 KiB / 139737 bytes)" cath <## "use /fr 1 [/ | ] to receive it" ] - bob ##> "/fr 1 ./tests/tmp/" - bob <## "saving file 1 from alice to ./tests/tmp/test.jpg" - concurrentlyN_ - [ do - alice <## "started sending file 1 (test.jpg) to bob" - alice <## "completed sending file 1 (test.jpg) to bob", - do - bob <## "started receiving file 1 (test.jpg) from alice" - bob <## "completed receiving file 1 (test.jpg) from alice" - ] - cath ##> "/fr 1 ./tests/tmp/" - cath <## "saving file 1 from alice to ./tests/tmp/test_1.jpg" - concurrentlyN_ - [ do - alice <## "started sending file 1 (test.jpg) to cath" - alice <## "completed sending file 1 (test.jpg) to cath", - do - cath <## "started receiving file 1 (test.jpg) from alice" - cath <## "completed receiving file 1 (test.jpg) from alice" - ] + alice <## "completed uploading file 1 (test.jpg) for #team" + + bob ##> "/fr 1 ./tests/tmp" + bob + <### [ "saving file 1 from alice to ./tests/tmp/test.jpg", + "started receiving file 1 (test.jpg) from alice" + ] + bob <## "completed receiving file 1 (test.jpg) from alice" + + cath ##> "/fr 1 ./tests/tmp" + cath + <### [ "saving file 1 from alice to ./tests/tmp/test_1.jpg", + "started receiving file 1 (test.jpg) from alice" + ] + cath <## "completed receiving file 1 (test.jpg) from alice" + src <- B.readFile "./tests/fixtures/test.jpg" dest <- B.readFile "./tests/tmp/test.jpg" dest `shouldBe` src @@ -844,7 +343,7 @@ testGroupSendImage = testGroupSendImageWithTextAndQuote :: HasCallStack => FilePath -> IO () testGroupSendImageWithTextAndQuote = testChat3 aliceProfile bobProfile cathProfile $ - \alice bob cath -> do + \alice bob cath -> withXFTPServer $ do createGroup3 "team" alice bob cath threadDelay 1000000 bob #> "#team hi team" @@ -870,26 +369,22 @@ testGroupSendImageWithTextAndQuote = cath <# "#team alice> sends file test.jpg (136.5 KiB / 139737 bytes)" cath <## "use /fr 1 [/ | ] to receive it" ] - bob ##> "/fr 1 ./tests/tmp/" - bob <## "saving file 1 from alice to ./tests/tmp/test.jpg" - concurrentlyN_ - [ do - alice <## "started sending file 1 (test.jpg) to bob" - alice <## "completed sending file 1 (test.jpg) to bob", - do - bob <## "started receiving file 1 (test.jpg) from alice" - bob <## "completed receiving file 1 (test.jpg) from alice" - ] - cath ##> "/fr 1 ./tests/tmp/" - cath <## "saving file 1 from alice to ./tests/tmp/test_1.jpg" - concurrentlyN_ - [ do - alice <## "started sending file 1 (test.jpg) to cath" - alice <## "completed sending file 1 (test.jpg) to cath", - do - cath <## "started receiving file 1 (test.jpg) from alice" - cath <## "completed receiving file 1 (test.jpg) from alice" - ] + alice <## "completed uploading file 1 (test.jpg) for #team" + + bob ##> "/fr 1 ./tests/tmp" + bob + <### [ "saving file 1 from alice to ./tests/tmp/test.jpg", + "started receiving file 1 (test.jpg) from alice" + ] + bob <## "completed receiving file 1 (test.jpg) from alice" + + cath ##> "/fr 1 ./tests/tmp" + cath + <### [ "saving file 1 from alice to ./tests/tmp/test_1.jpg", + "started receiving file 1 (test.jpg) from alice" + ] + cath <## "completed receiving file 1 (test.jpg) from alice" + src <- B.readFile "./tests/fixtures/test.jpg" dest <- B.readFile "./tests/tmp/test.jpg" dest `shouldBe` src @@ -902,142 +397,6 @@ testGroupSendImageWithTextAndQuote = cath #$> ("/_get chat #1 count=2", chat'', [((0, "hi team"), Nothing, Nothing), ((0, "hey bob"), Just (0, "hi team"), Just "./tests/tmp/test_1.jpg")]) cath @@@ [("#team", "hey bob"), ("@alice", "received invitation to join group team as admin")] -testAsyncFileTransferSenderRestarts :: HasCallStack => FilePath -> IO () -testAsyncFileTransferSenderRestarts tmp = do - withNewTestChat tmp "bob" bobProfile $ \bob -> do - withNewTestChat tmp "alice" aliceProfile $ \alice -> do - connectUsers alice bob - startFileTransfer' alice bob "test_1MB.pdf" "1017.7 KiB / 1042157 bytes" - threadDelay 100000 - withTestChatContactConnected tmp "alice" $ \alice -> do - alice <## "completed sending file 1 (test_1MB.pdf) to bob" - bob <## "completed receiving file 1 (test_1MB.pdf) from alice" - src <- B.readFile "./tests/fixtures/test_1MB.pdf" - dest <- B.readFile "./tests/tmp/test_1MB.pdf" - dest `shouldBe` src - -testAsyncFileTransferReceiverRestarts :: HasCallStack => FilePath -> IO () -testAsyncFileTransferReceiverRestarts tmp = do - withNewTestChat tmp "alice" aliceProfile $ \alice -> do - withNewTestChat tmp "bob" bobProfile $ \bob -> do - connectUsers alice bob - startFileTransfer' alice bob "test_1MB.pdf" "1017.7 KiB / 1042157 bytes" - threadDelay 100000 - withTestChatContactConnected tmp "bob" $ \bob -> do - alice <## "completed sending file 1 (test_1MB.pdf) to bob" - bob <## "completed receiving file 1 (test_1MB.pdf) from alice" - src <- B.readFile "./tests/fixtures/test_1MB.pdf" - dest <- B.readFile "./tests/tmp/test_1MB.pdf" - dest `shouldBe` src - -testAsyncFileTransfer :: HasCallStack => FilePath -> IO () -testAsyncFileTransfer tmp = do - withNewTestChat tmp "alice" aliceProfile $ \alice -> - withNewTestChat tmp "bob" bobProfile $ \bob -> - connectUsers alice bob - withTestChatContactConnected tmp "alice" $ \alice -> do - alice ##> "/_send @2 json {\"filePath\": \"./tests/fixtures/test.jpg\", \"msgContent\": {\"type\":\"text\", \"text\": \"hi, sending a file\"}}" - alice <# "@bob hi, sending a file" - alice <# "/f @bob ./tests/fixtures/test.jpg" - alice <## "use /fc 1 to cancel sending" - withTestChatContactConnected tmp "bob" $ \bob -> do - bob <# "alice> hi, sending a file" - bob <# "alice> sends file test.jpg (136.5 KiB / 139737 bytes)" - bob <## "use /fr 1 [/ | ] to receive it" - bob ##> "/fr 1 ./tests/tmp" - bob <## "saving file 1 from alice to ./tests/tmp/test.jpg" - -- withTestChatContactConnected' tmp "alice" -- TODO not needed in v2 - -- withTestChatContactConnected' tmp "bob" -- TODO not needed in v2 - withTestChatContactConnected' tmp "alice" - withTestChatContactConnected' tmp "bob" - withTestChatContactConnected tmp "alice" $ \alice -> do - alice <## "started sending file 1 (test.jpg) to bob" - alice <## "completed sending file 1 (test.jpg) to bob" - withTestChatContactConnected tmp "bob" $ \bob -> do - bob <## "started receiving file 1 (test.jpg) from alice" - bob <## "completed receiving file 1 (test.jpg) from alice" - src <- B.readFile "./tests/fixtures/test.jpg" - dest <- B.readFile "./tests/tmp/test.jpg" - dest `shouldBe` src - -testAsyncFileTransferV1 :: HasCallStack => FilePath -> IO () -testAsyncFileTransferV1 tmp = do - withNewTestChatV1 tmp "alice" aliceProfile $ \alice -> - withNewTestChatV1 tmp "bob" bobProfile $ \bob -> - connectUsers alice bob - withTestChatContactConnectedV1 tmp "alice" $ \alice -> do - alice ##> "/_send @2 json {\"filePath\": \"./tests/fixtures/test.jpg\", \"msgContent\": {\"type\":\"text\", \"text\": \"hi, sending a file\"}}" - alice <# "@bob hi, sending a file" - alice <# "/f @bob ./tests/fixtures/test.jpg" - alice <## "use /fc 1 to cancel sending" - withTestChatContactConnectedV1 tmp "bob" $ \bob -> do - bob <# "alice> hi, sending a file" - bob <# "alice> sends file test.jpg (136.5 KiB / 139737 bytes)" - bob <## "use /fr 1 [/ | ] to receive it" - bob ##> "/fr 1 ./tests/tmp" - bob <## "saving file 1 from alice to ./tests/tmp/test.jpg" - withTestChatContactConnectedV1' tmp "alice" -- TODO not needed in v2 - withTestChatContactConnectedV1' tmp "bob" -- TODO not needed in v2 - withTestChatContactConnectedV1' tmp "alice" - withTestChatContactConnectedV1' tmp "bob" - withTestChatContactConnectedV1 tmp "alice" $ \alice -> do - alice <## "started sending file 1 (test.jpg) to bob" - alice <## "completed sending file 1 (test.jpg) to bob" - withTestChatContactConnectedV1 tmp "bob" $ \bob -> do - bob <## "started receiving file 1 (test.jpg) from alice" - bob <## "completed receiving file 1 (test.jpg) from alice" - src <- B.readFile "./tests/fixtures/test.jpg" - dest <- B.readFile "./tests/tmp/test.jpg" - dest `shouldBe` src - -testAsyncGroupFileTransfer :: HasCallStack => FilePath -> IO () -testAsyncGroupFileTransfer tmp = do - withNewTestChat tmp "alice" aliceProfile $ \alice -> - withNewTestChat tmp "bob" bobProfile $ \bob -> - withNewTestChat tmp "cath" cathProfile $ \cath -> - createGroup3 "team" alice bob cath - withTestChatGroup3Connected tmp "alice" $ \alice -> do - alice ##> "/_send #1 json {\"filePath\": \"./tests/fixtures/test.jpg\", \"msgContent\": {\"text\":\"\",\"type\":\"text\"}}" - alice <# "/f #team ./tests/fixtures/test.jpg" - alice <## "use /fc 1 to cancel sending" - withTestChatGroup3Connected tmp "bob" $ \bob -> do - bob <# "#team alice> sends file test.jpg (136.5 KiB / 139737 bytes)" - bob <## "use /fr 1 [/ | ] to receive it" - bob ##> "/fr 1 ./tests/tmp/" - bob <## "saving file 1 from alice to ./tests/tmp/test.jpg" - withTestChatGroup3Connected tmp "cath" $ \cath -> do - cath <# "#team alice> sends file test.jpg (136.5 KiB / 139737 bytes)" - cath <## "use /fr 1 [/ | ] to receive it" - cath ##> "/fr 1 ./tests/tmp/" - cath <## "saving file 1 from alice to ./tests/tmp/test_1.jpg" - withTestChatGroup3Connected' tmp "alice" - withTestChatGroup3Connected' tmp "bob" - withTestChatGroup3Connected' tmp "cath" - -- withTestChatGroup3Connected' tmp "alice" -- TODO not needed in v2 - -- withTestChatGroup3Connected' tmp "bob" -- TODO not needed in v2 - -- withTestChatGroup3Connected' tmp "cath" -- TODO not needed in v2 - withTestChatGroup3Connected' tmp "alice" - withTestChatGroup3Connected tmp "bob" $ \bob -> do - bob <## "started receiving file 1 (test.jpg) from alice" - withTestChatGroup3Connected tmp "cath" $ \cath -> do - cath <## "started receiving file 1 (test.jpg) from alice" - withTestChatGroup3Connected tmp "alice" $ \alice -> do - alice - <### [ "started sending file 1 (test.jpg) to bob", - "completed sending file 1 (test.jpg) to bob", - "started sending file 1 (test.jpg) to cath", - "completed sending file 1 (test.jpg) to cath" - ] - withTestChatGroup3Connected tmp "bob" $ \bob -> do - bob <## "completed receiving file 1 (test.jpg) from alice" - withTestChatGroup3Connected tmp "cath" $ \cath -> do - cath <## "completed receiving file 1 (test.jpg) from alice" - src <- B.readFile "./tests/fixtures/test.jpg" - dest <- B.readFile "./tests/tmp/test.jpg" - dest `shouldBe` src - dest2 <- B.readFile "./tests/tmp/test_1.jpg" - dest2 `shouldBe` src - testXFTPRoundFDCount :: Expectation testXFTPRoundFDCount = do roundedFDCount (-100) `shouldBe` 4 @@ -1053,13 +412,12 @@ testXFTPRoundFDCount = do testXFTPFileTransfer :: HasCallStack => FilePath -> IO () testXFTPFileTransfer = - testChatCfg2 cfg aliceProfile bobProfile $ \alice bob -> do + testChat2 aliceProfile bobProfile $ \alice bob -> do withXFTPServer $ do connectUsers alice bob alice #> "/f @bob ./tests/fixtures/test.pdf" alice <## "use /fc 1 to cancel sending" - -- alice <## "started sending file 1 (test.pdf) to bob" -- TODO "started uploading" ? bob <# "alice> sends file test.pdf (266.0 KiB / 272376 bytes)" bob <## "use /fr 1 [/ | ] to receive it" bob ##> "/fr 1 ./tests/tmp" @@ -1080,12 +438,10 @@ testXFTPFileTransfer = src <- B.readFile "./tests/fixtures/test.pdf" dest <- B.readFile "./tests/tmp/test.pdf" dest `shouldBe` src - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} testXFTPFileTransferEncrypted :: HasCallStack => FilePath -> IO () testXFTPFileTransferEncrypted = - testChatCfg2 cfg aliceProfile bobProfile $ \alice bob -> do + testChat2 aliceProfile bobProfile $ \alice bob -> do src <- B.readFile "./tests/fixtures/test.pdf" srcLen <- getFileSize "./tests/fixtures/test.pdf" let srcPath = "./tests/tmp/alice/test.pdf" @@ -1109,12 +465,10 @@ testXFTPFileTransferEncrypted = Right dest <- chatReadFile "./tests/tmp/bob/test.pdf" (strEncode key) (strEncode nonce) LB.length dest `shouldBe` fromIntegral srcLen LB.toStrict dest `shouldBe` src - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} testXFTPAcceptAfterUpload :: HasCallStack => FilePath -> IO () testXFTPAcceptAfterUpload = - testChatCfg2 cfg aliceProfile bobProfile $ \alice bob -> do + testChat2 aliceProfile bobProfile $ \alice bob -> do withXFTPServer $ do connectUsers alice bob @@ -1122,7 +476,6 @@ testXFTPAcceptAfterUpload = alice <## "use /fc 1 to cancel sending" bob <# "alice> sends file test.pdf (266.0 KiB / 272376 bytes)" bob <## "use /fr 1 [/ | ] to receive it" - -- alice <## "started sending file 1 (test.pdf) to bob" -- TODO "started uploading" ? alice <## "completed uploading file 1 (test.pdf) for bob" threadDelay 100000 @@ -1137,12 +490,10 @@ testXFTPAcceptAfterUpload = src <- B.readFile "./tests/fixtures/test.pdf" dest <- B.readFile "./tests/tmp/test.pdf" dest `shouldBe` src - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} testXFTPGroupFileTransfer :: HasCallStack => FilePath -> IO () testXFTPGroupFileTransfer = - testChatCfg3 cfg aliceProfile bobProfile cathProfile $ \alice bob cath -> do + testChat3 aliceProfile bobProfile cathProfile $ \alice bob cath -> do withXFTPServer $ do createGroup3 "team" alice bob cath @@ -1156,7 +507,6 @@ testXFTPGroupFileTransfer = cath <# "#team alice> sends file test.pdf (266.0 KiB / 272376 bytes)" cath <## "use /fr 1 [/ | ] to receive it" ] - -- alice <## "started sending file 1 (test.pdf) to #team" -- TODO "started uploading" ? alice <## "completed uploading file 1 (test.pdf) for #team" bob ##> "/fr 1 ./tests/tmp" @@ -1178,12 +528,10 @@ testXFTPGroupFileTransfer = dest2 <- B.readFile "./tests/tmp/test_1.pdf" dest1 `shouldBe` src dest2 `shouldBe` src - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} testXFTPDeleteUploadedFile :: HasCallStack => FilePath -> IO () testXFTPDeleteUploadedFile = - testChatCfg2 cfg aliceProfile bobProfile $ \alice bob -> do + testChat2 aliceProfile bobProfile $ \alice bob -> do withXFTPServer $ do connectUsers alice bob @@ -1191,7 +539,6 @@ testXFTPDeleteUploadedFile = alice <## "use /fc 1 to cancel sending" bob <# "alice> sends file test.pdf (266.0 KiB / 272376 bytes)" bob <## "use /fr 1 [/ | ] to receive it" - -- alice <## "started sending file 1 (test.pdf) to bob" -- TODO "started uploading" ? alice <## "completed uploading file 1 (test.pdf) for bob" alice ##> "/fc 1" @@ -1202,12 +549,10 @@ testXFTPDeleteUploadedFile = bob ##> "/fr 1 ./tests/tmp" bob <## "file cancelled: test.pdf" - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} testXFTPDeleteUploadedFileGroup :: HasCallStack => FilePath -> IO () testXFTPDeleteUploadedFileGroup = - testChatCfg3 cfg aliceProfile bobProfile cathProfile $ \alice bob cath -> do + testChat3 aliceProfile bobProfile cathProfile $ \alice bob cath -> do withXFTPServer $ do createGroup3 "team" alice bob cath @@ -1221,7 +566,6 @@ testXFTPDeleteUploadedFileGroup = cath <# "#team alice> sends file test.pdf (266.0 KiB / 272376 bytes)" cath <## "use /fr 1 [/ | ] to receive it" ] - -- alice <## "started sending file 1 (test.pdf) to #team" -- TODO "started uploading" ? alice <## "completed uploading file 1 (test.pdf) for #team" bob ##> "/fr 1 ./tests/tmp" @@ -1257,45 +601,10 @@ testXFTPDeleteUploadedFileGroup = cath ##> "/fr 1 ./tests/tmp" cath <## "file cancelled: test.pdf" - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} - -testXFTPWithChangedConfig :: HasCallStack => FilePath -> IO () -testXFTPWithChangedConfig = - testChatCfg2 cfg aliceProfile bobProfile $ \alice bob -> do - withXFTPServer $ do - alice #$> ("/_xftp off", id, "ok") - alice #$> ("/_xftp on {\"minFileSize\":1024}", id, "ok") - - bob #$> ("/xftp off", id, "ok") - bob #$> ("/xftp on size=1kb", id, "ok") - - connectUsers alice bob - - alice #> "/f @bob ./tests/fixtures/test.pdf" - alice <## "use /fc 1 to cancel sending" - -- alice <## "started sending file 1 (test.pdf) to bob" -- TODO "started uploading" ? - bob <# "alice> sends file test.pdf (266.0 KiB / 272376 bytes)" - bob <## "use /fr 1 [/ | ] to receive it" - bob ##> "/fr 1 ./tests/tmp" - concurrentlyN_ - [ alice <## "completed uploading file 1 (test.pdf) for bob", - bob - <### [ "saving file 1 from alice to ./tests/tmp/test.pdf", - "started receiving file 1 (test.pdf) from alice" - ] - ] - bob <## "completed receiving file 1 (test.pdf) from alice" - - src <- B.readFile "./tests/fixtures/test.pdf" - dest <- B.readFile "./tests/tmp/test.pdf" - dest `shouldBe` src - where - cfg = testCfg {tempDir = Just "./tests/tmp"} testXFTPWithRelativePaths :: HasCallStack => FilePath -> IO () testXFTPWithRelativePaths = - testChatCfg2 cfg aliceProfile bobProfile $ \alice bob -> do + testChat2 aliceProfile bobProfile $ \alice bob -> do withXFTPServer $ do -- agent is passed xftp work directory only on chat start, -- so for test we work around by stopping and starting chat @@ -1317,7 +626,6 @@ testXFTPWithRelativePaths = alice #> "/f @bob test.pdf" alice <## "use /fc 1 to cancel sending" - -- alice <## "started sending file 1 (test.pdf) to bob" -- TODO "started uploading" ? bob <# "alice> sends file test.pdf (266.0 KiB / 272376 bytes)" bob <## "use /fr 1 [/ | ] to receive it" bob ##> "/fr 1" @@ -1333,25 +641,22 @@ testXFTPWithRelativePaths = src <- B.readFile "./tests/fixtures/test.pdf" dest <- B.readFile "./tests/tmp/bob_files/test.pdf" dest `shouldBe` src - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}} testXFTPContinueRcv :: HasCallStack => FilePath -> IO () testXFTPContinueRcv tmp = do withXFTPServer $ do - withNewTestChatCfg tmp cfg "alice" aliceProfile $ \alice -> do - withNewTestChatCfg tmp cfg "bob" bobProfile $ \bob -> do + withNewTestChat tmp "alice" aliceProfile $ \alice -> do + withNewTestChat tmp "bob" bobProfile $ \bob -> do connectUsers alice bob alice #> "/f @bob ./tests/fixtures/test.pdf" alice <## "use /fc 1 to cancel sending" bob <# "alice> sends file test.pdf (266.0 KiB / 272376 bytes)" bob <## "use /fr 1 [/ | ] to receive it" - -- alice <## "started sending file 1 (test.pdf) to bob" -- TODO "started uploading" ? alice <## "completed uploading file 1 (test.pdf) for bob" -- server is down - file is not received - withTestChatCfg tmp cfg "bob" $ \bob -> do + withTestChat tmp "bob" $ \bob -> do bob <## "1 contacts connected (use /cs for the list)" bob ##> "/fr 1 ./tests/tmp" bob @@ -1366,18 +671,16 @@ testXFTPContinueRcv tmp = do withXFTPServer $ do -- server is up - file reception is continued - withTestChatCfg tmp cfg "bob" $ \bob -> do + withTestChat tmp "bob" $ \bob -> do bob <## "1 contacts connected (use /cs for the list)" bob <## "completed receiving file 1 (test.pdf) from alice" src <- B.readFile "./tests/fixtures/test.pdf" dest <- B.readFile "./tests/tmp/test.pdf" dest `shouldBe` src - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} testXFTPMarkToReceive :: HasCallStack => FilePath -> IO () testXFTPMarkToReceive = do - testChatCfg2 cfg aliceProfile bobProfile $ \alice bob -> do + testChat2 aliceProfile bobProfile $ \alice bob -> do withXFTPServer $ do connectUsers alice bob @@ -1385,7 +688,6 @@ testXFTPMarkToReceive = do alice <## "use /fc 1 to cancel sending" bob <# "alice> sends file test.pdf (266.0 KiB / 272376 bytes)" bob <## "use /fr 1 [/ | ] to receive it" - -- alice <## "started sending file 1 (test.pdf) to bob" -- TODO "started uploading" ? alice <## "completed uploading file 1 (test.pdf) for bob" bob #$> ("/_set_file_to_receive 1", id, "ok") @@ -1412,26 +714,23 @@ testXFTPMarkToReceive = do src <- B.readFile "./tests/fixtures/test.pdf" dest <- B.readFile "./tests/tmp/bob_files/test.pdf" dest `shouldBe` src - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}} testXFTPRcvError :: HasCallStack => FilePath -> IO () testXFTPRcvError tmp = do withXFTPServer $ do - withNewTestChatCfg tmp cfg "alice" aliceProfile $ \alice -> do - withNewTestChatCfg tmp cfg "bob" bobProfile $ \bob -> do + withNewTestChat tmp "alice" aliceProfile $ \alice -> do + withNewTestChat tmp "bob" bobProfile $ \bob -> do connectUsers alice bob alice #> "/f @bob ./tests/fixtures/test.pdf" alice <## "use /fc 1 to cancel sending" bob <# "alice> sends file test.pdf (266.0 KiB / 272376 bytes)" bob <## "use /fr 1 [/ | ] to receive it" - -- alice <## "started sending file 1 (test.pdf) to bob" -- TODO "started uploading" ? alice <## "completed uploading file 1 (test.pdf) for bob" -- server is up w/t store log - file reception should fail withXFTPServer' xftpServerConfig {storeLogFile = Nothing} $ do - withTestChatCfg tmp cfg "bob" $ \bob -> do + withTestChat tmp "bob" $ \bob -> do bob <## "1 contacts connected (use /cs for the list)" bob ##> "/fr 1 ./tests/tmp" bob @@ -1443,8 +742,6 @@ testXFTPRcvError tmp = do bob ##> "/fs 1" bob <## "receiving file 1 (test.pdf) error" - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} testXFTPCancelRcvRepeat :: HasCallStack => FilePath -> IO () testXFTPCancelRcvRepeat = @@ -1456,7 +753,6 @@ testXFTPCancelRcvRepeat = alice #> "/f @bob ./tests/tmp/testfile" alice <## "use /fc 1 to cancel sending" - -- alice <## "started sending file 1 (testfile) to bob" -- TODO "started uploading" ? bob <# "alice> sends file testfile (17.0 MiB / 17825792 bytes)" bob <## "use /fr 1 [/ | ] to receive it" bob ##> "/fr 1 ./tests/tmp" @@ -1493,11 +789,11 @@ testXFTPCancelRcvRepeat = dest <- B.readFile "./tests/tmp/testfile_1" dest `shouldBe` src where - cfg = testCfg {xftpDescrPartSize = 200, xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} + cfg = testCfg {xftpDescrPartSize = 200} testAutoAcceptFile :: HasCallStack => FilePath -> IO () testAutoAcceptFile = - testChatCfgOpts2 cfg opts aliceProfile bobProfile $ \alice bob -> withXFTPServer $ do + testChatOpts2 opts aliceProfile bobProfile $ \alice bob -> withXFTPServer $ do connectUsers alice bob bob ##> "/_files_folder ./tests/tmp/bob_files" bob <## "ok" @@ -1518,12 +814,11 @@ testAutoAcceptFile = -- no auto accept for large files (bob FilePath -> IO () testProhibitFiles = - testChatCfg3 cfg aliceProfile bobProfile cathProfile $ \alice bob cath -> withXFTPServer $ do + testChat3 aliceProfile bobProfile cathProfile $ \alice bob cath -> withXFTPServer $ do createGroup3 "team" alice bob cath alice ##> "/set files #team off" alice <## "updated group preferences:" @@ -1542,22 +837,6 @@ testProhibitFiles = alice <## "bad chat command: feature not allowed Files and media" (bob TestCC -> TestCC -> IO () -startFileTransfer alice bob = - startFileTransfer' alice bob "test.jpg" "136.5 KiB / 139737 bytes" - -startFileTransfer' :: HasCallStack => TestCC -> TestCC -> String -> String -> IO () -startFileTransfer' cc1 cc2 fName fSize = startFileTransferWithDest' cc1 cc2 fName fSize $ Just "./tests/tmp" - -checkPartialTransfer :: HasCallStack => String -> IO () -checkPartialTransfer fileName = do - src <- B.readFile $ "./tests/fixtures/" <> fileName - dest <- B.readFile $ "./tests/tmp/" <> fileName - B.unpack src `shouldStartWith` B.unpack dest - B.length src > B.length dest `shouldBe` True waitFileExists :: HasCallStack => FilePath -> IO () waitFileExists f = unlessM (doesFileExist f) $ waitFileExists f diff --git a/tests/ChatTests/Groups.hs b/tests/ChatTests/Groups.hs index 51a5b352a7..3057fa7b70 100644 --- a/tests/ChatTests/Groups.hs +++ b/tests/ChatTests/Groups.hs @@ -11,7 +11,7 @@ import Control.Monad (void, when) import qualified Data.ByteString as B import Data.List (isInfixOf) import qualified Data.Text as T -import Simplex.Chat.Controller (ChatConfig (..), XFTPFileConfig (..)) +import Simplex.Chat.Controller (ChatConfig (..)) import Simplex.Chat.Protocol (supportedChatVRange) import Simplex.Chat.Store (agentStoreFile, chatStoreFile) import Simplex.Chat.Types (GroupMemberRole (..)) @@ -4321,7 +4321,7 @@ testGroupMsgForwardDeletion = testGroupMsgForwardFile :: HasCallStack => FilePath -> IO () testGroupMsgForwardFile = - testChatCfg3 cfg aliceProfile bobProfile cathProfile $ + testChat3 aliceProfile bobProfile cathProfile $ \alice bob cath -> withXFTPServer $ do setupGroupForwarding3 "team" alice bob cath @@ -4343,8 +4343,6 @@ testGroupMsgForwardFile = src <- B.readFile "./tests/fixtures/test.jpg" dest <- B.readFile "./tests/tmp/test.jpg" dest `shouldBe` src - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} testGroupMsgForwardChangeRole :: HasCallStack => FilePath -> IO () testGroupMsgForwardChangeRole = @@ -4577,7 +4575,7 @@ testGroupHistoryPreferenceOff = testGroupHistoryHostFile :: HasCallStack => FilePath -> IO () testGroupHistoryHostFile = - testChatCfg3 cfg aliceProfile bobProfile cathProfile $ + testChat3 aliceProfile bobProfile cathProfile $ \alice bob cath -> withXFTPServer $ do createGroup2 "team" alice bob @@ -4613,12 +4611,10 @@ testGroupHistoryHostFile = src <- B.readFile "./tests/fixtures/test.jpg" dest <- B.readFile "./tests/tmp/test.jpg" dest `shouldBe` src - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} testGroupHistoryMemberFile :: HasCallStack => FilePath -> IO () testGroupHistoryMemberFile = - testChatCfg3 cfg aliceProfile bobProfile cathProfile $ + testChat3 aliceProfile bobProfile cathProfile $ \alice bob cath -> withXFTPServer $ do createGroup2 "team" alice bob @@ -4654,8 +4650,6 @@ testGroupHistoryMemberFile = src <- B.readFile "./tests/fixtures/test.jpg" dest <- B.readFile "./tests/tmp/test.jpg" dest `shouldBe` src - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} testGroupHistoryLargeFile :: HasCallStack => FilePath -> IO () testGroupHistoryLargeFile = @@ -4713,11 +4707,11 @@ testGroupHistoryLargeFile = destCath <- B.readFile "./tests/tmp/testfile_2" destCath `shouldBe` src where - cfg = testCfg {xftpDescrPartSize = 200, xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} + cfg = testCfg {xftpDescrPartSize = 200} testGroupHistoryMultipleFiles :: HasCallStack => FilePath -> IO () testGroupHistoryMultipleFiles = - testChatCfg3 cfg aliceProfile bobProfile cathProfile $ + testChat3 aliceProfile bobProfile cathProfile $ \alice bob cath -> withXFTPServer $ do xftpCLI ["rand", "./tests/tmp/testfile_bob", "2mb"] `shouldReturn` ["File created: " <> "./tests/tmp/testfile_bob"] xftpCLI ["rand", "./tests/tmp/testfile_alice", "1mb"] `shouldReturn` ["File created: " <> "./tests/tmp/testfile_alice"] @@ -4794,12 +4788,10 @@ testGroupHistoryMultipleFiles = `shouldContain` [ ((0, "hi alice"), Just "./tests/tmp/testfile_bob_1"), ((0, "hey bob"), Just "./tests/tmp/testfile_alice_1") ] - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} testGroupHistoryFileCancel :: HasCallStack => FilePath -> IO () testGroupHistoryFileCancel = - testChatCfg3 cfg aliceProfile bobProfile cathProfile $ + testChat3 aliceProfile bobProfile cathProfile $ \alice bob cath -> withXFTPServer $ do xftpCLI ["rand", "./tests/tmp/testfile_bob", "2mb"] `shouldReturn` ["File created: " <> "./tests/tmp/testfile_bob"] xftpCLI ["rand", "./tests/tmp/testfile_alice", "1mb"] `shouldReturn` ["File created: " <> "./tests/tmp/testfile_alice"] @@ -4851,12 +4843,10 @@ testGroupHistoryFileCancel = bob <## "#team: alice added cath (Catherine) to the group (connecting...)" bob <## "#team: new member cath is connected" ] - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} testGroupHistoryFileCancelNoText :: HasCallStack => FilePath -> IO () testGroupHistoryFileCancelNoText = - testChatCfg3 cfg aliceProfile bobProfile cathProfile $ + testChat3 aliceProfile bobProfile cathProfile $ \alice bob cath -> withXFTPServer $ do xftpCLI ["rand", "./tests/tmp/testfile_bob", "2mb"] `shouldReturn` ["File created: " <> "./tests/tmp/testfile_bob"] xftpCLI ["rand", "./tests/tmp/testfile_alice", "1mb"] `shouldReturn` ["File created: " <> "./tests/tmp/testfile_alice"] @@ -4912,8 +4902,6 @@ testGroupHistoryFileCancelNoText = bob <## "#team: alice added cath (Catherine) to the group (connecting...)" bob <## "#team: new member cath is connected" ] - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"} testGroupHistoryQuotes :: HasCallStack => FilePath -> IO () testGroupHistoryQuotes = diff --git a/tests/ChatTests/Local.hs b/tests/ChatTests/Local.hs index 1d0c540d76..6ea41a2387 100644 --- a/tests/ChatTests/Local.hs +++ b/tests/ChatTests/Local.hs @@ -12,7 +12,6 @@ import Simplex.Chat.Controller (ChatConfig (..), InlineFilesConfig (..), default import System.Directory (copyFile, doesFileExist) import System.FilePath (()) import Test.Hspec hiding (it) -import UnliftIO.Async (concurrently_) chatLocalChatsTests :: SpecWith FilePath chatLocalChatsTests = do @@ -158,24 +157,24 @@ testFiles tmp = withNewTestChat tmp "alice" aliceProfile $ \alice -> do testOtherFiles :: FilePath -> IO () testOtherFiles = - testChatCfg2 cfg aliceProfile bobProfile $ \alice bob -> do + testChatCfg2 cfg aliceProfile bobProfile $ \alice bob -> withXFTPServer $ do connectUsers alice bob createCCNoteFolder bob bob ##> "/_files_folder ./tests/tmp/" bob <## "ok" - alice ##> "/_send @2 json {\"msgContent\":{\"type\":\"voice\", \"duration\":10, \"text\":\"\"}, \"filePath\":\"./tests/fixtures/test.jpg\"}" - alice <# "@bob voice message (00:10)" - alice <# "/f @bob ./tests/fixtures/test.jpg" - -- below is not shown in "sent" mode - -- alice <## "use /fc 1 to cancel sending" - bob <# "alice> voice message (00:10)" + + alice #> "/f @bob ./tests/fixtures/test.jpg" + alice <## "use /fc 1 to cancel sending" bob <# "alice> sends file test.jpg (136.5 KiB / 139737 bytes)" - -- below is not shown in "sent" mode - -- bob <## "use /fr 1 [/ | ] to receive it" - bob <## "started receiving file 1 (test.jpg) from alice" - concurrently_ - (alice <## "completed sending file 1 (test.jpg) to bob") - (bob <## "completed receiving file 1 (test.jpg) from alice") + bob <## "use /fr 1 [/ | ] to receive it" + alice <## "completed uploading file 1 (test.jpg) for bob" + + bob ##> "/fr 1" + bob + <### [ "saving file 1 from alice to test.jpg", + "started receiving file 1 (test.jpg) from alice" + ] + bob <## "completed receiving file 1 (test.jpg) from alice" bob /* "test" bob ##> "/tail *" diff --git a/tests/ChatTests/Profiles.hs b/tests/ChatTests/Profiles.hs index 80cdc34c76..30c78138ad 100644 --- a/tests/ChatTests/Profiles.hs +++ b/tests/ChatTests/Profiles.hs @@ -1493,7 +1493,7 @@ testSetConnectionAlias = testChat2 aliceProfile bobProfile $ testSetContactPrefs :: HasCallStack => FilePath -> IO () testSetContactPrefs = testChat2 aliceProfile bobProfile $ - \alice bob -> do + \alice bob -> withXFTPServer $ do alice #$> ("/_files_folder ./tests/tmp/alice", id, "ok") bob #$> ("/_files_folder ./tests/tmp/bob", id, "ok") createDirectoryIfMissing True "./tests/tmp/alice" @@ -1528,15 +1528,24 @@ testSetContactPrefs = testChat2 aliceProfile bobProfile $ bob #$> ("/_get chat @2 count=100", chat, startFeatures <> [(0, "Voice messages: enabled for you")]) alice ##> sendVoice alice <## voiceNotAllowed + + -- sending voice message allowed bob ##> sendVoice bob <# "@alice voice message (00:10)" bob <# "/f @alice test.txt" - bob <## "completed sending file 1 (test.txt) to alice" + bob <## "use /fc 1 to cancel sending" alice <# "bob> voice message (00:10)" alice <# "bob> sends file test.txt (11 bytes / 11 bytes)" - alice <## "started receiving file 1 (test.txt) from bob" + alice <## "use /fr 1 [/ | ] to receive it" + bob <## "completed uploading file 1 (test.txt) for alice" + alice ##> "/fr 1" + alice + <### [ "saving file 1 from bob to test_1.txt", + "started receiving file 1 (test.txt) from bob" + ] alice <## "completed receiving file 1 (test.txt) from bob" (bob "/_profile 1 {\"displayName\": \"alice\", \"fullName\": \"Alice\", \"preferences\": {\"voice\": {\"allow\": \"no\"}}}" alice ##> "/set voice no" alice <## "updated preferences:" diff --git a/tests/ChatTests/Utils.hs b/tests/ChatTests/Utils.hs index 433bf46036..9ce84be18e 100644 --- a/tests/ChatTests/Utils.hs +++ b/tests/ChatTests/Utils.hs @@ -19,7 +19,7 @@ import Data.Maybe (fromMaybe) import Data.String import qualified Data.Text as T import Database.SQLite.Simple (Only (..)) -import Simplex.Chat.Controller (ChatConfig (..), ChatController (..), InlineFilesConfig (..), defaultInlineFilesConfig) +import Simplex.Chat.Controller (ChatConfig (..), ChatController (..)) import Simplex.Chat.Protocol import Simplex.Chat.Store.NoteFolders (createNoteFolder) import Simplex.Chat.Store.Profiles (getUserContactProfiles) @@ -32,7 +32,6 @@ import Simplex.Messaging.Encoding.String import Simplex.Messaging.Version import System.Directory (doesFileExist) import System.Environment (lookupEnv, withArgs) -import System.FilePath (()) import System.IO.Silently (capture_) import System.Info (os) import Test.Hspec hiding (it) @@ -96,29 +95,6 @@ versionTestMatrix3 runTest = do it "curr to prev" $ runTestCfg3 testCfgVPrev testCfg testCfg runTest it "curr+prev to prev" $ runTestCfg3 testCfgVPrev testCfg testCfgVPrev runTest -inlineCfg :: Integer -> ChatConfig -inlineCfg n = testCfg {inlineFiles = defaultInlineFilesConfig {sendChunks = 0, offerChunks = n, receiveChunks = n}} - -fileTestMatrix2 :: (HasCallStack => TestCC -> TestCC -> IO ()) -> SpecWith FilePath -fileTestMatrix2 runTest = do - it "via connection" $ runTestCfg2 viaConn viaConn runTest - it "inline (accepting)" $ runTestCfg2 inline inline runTest - it "via connection (inline offered)" $ runTestCfg2 inline viaConn runTest - it "via connection (inline supported)" $ runTestCfg2 viaConn inline runTest - where - inline = inlineCfg 100 - viaConn = inlineCfg 0 - -fileTestMatrix3 :: (HasCallStack => TestCC -> TestCC -> TestCC -> IO ()) -> SpecWith FilePath -fileTestMatrix3 runTest = do - it "via connection" $ runTestCfg3 viaConn viaConn viaConn runTest - it "inline" $ runTestCfg3 inline inline inline runTest - it "via connection (inline offered)" $ runTestCfg3 inline viaConn viaConn runTest - it "via connection (inline supported)" $ runTestCfg3 viaConn inline inline runTest - where - inline = inlineCfg 100 - viaConn = inlineCfg 0 - runTestCfg2 :: ChatConfig -> ChatConfig -> (HasCallStack => TestCC -> TestCC -> IO ()) -> FilePath -> IO () runTestCfg2 aliceCfg bobCfg runTest tmp = withNewTestChatCfg tmp aliceCfg "alice" aliceProfile $ \alice -> @@ -595,20 +571,6 @@ checkActionDeletesFile file action = do fileExistsAfter <- doesFileExist file fileExistsAfter `shouldBe` False -startFileTransferWithDest' :: HasCallStack => TestCC -> TestCC -> String -> String -> Maybe String -> IO () -startFileTransferWithDest' cc1 cc2 fileName fileSize fileDest_ = do - name1 <- userName cc1 - name2 <- userName cc2 - cc1 #> ("/f @" <> name2 <> " ./tests/fixtures/" <> fileName) - cc1 <## "use /fc 1 to cancel sending" - cc2 <# (name1 <> "> sends file " <> fileName <> " (" <> fileSize <> ")") - cc2 <## "use /fr 1 [/ | ] to receive it" - cc2 ##> ("/fr 1" <> maybe "" (" " <>) fileDest_) - cc2 <## ("saving file 1 from " <> name1 <> " to " <> maybe id () fileDest_ fileName) - concurrently_ - (cc2 <## ("started receiving file 1 (" <> fileName <> ") from " <> name1)) - (cc1 <## ("started sending file 1 (" <> fileName <> ") to " <> name2)) - currentChatVRangeInfo :: String currentChatVRangeInfo = "peer chat protocol version range: " <> vRangeStr supportedChatVRange diff --git a/tests/RemoteTests.hs b/tests/RemoteTests.hs index 25c3514e4a..ac6fa7b23a 100644 --- a/tests/RemoteTests.hs +++ b/tests/RemoteTests.hs @@ -13,7 +13,7 @@ import qualified Data.ByteString as B import qualified Data.ByteString.Lazy.Char8 as LB import qualified Data.Map.Strict as M import Simplex.Chat.Archive (archiveFilesFolder) -import Simplex.Chat.Controller (ChatConfig (..), XFTPFileConfig (..), versionNumber) +import Simplex.Chat.Controller (versionNumber) import qualified Simplex.Chat.Controller as Controller import Simplex.Chat.Mobile.File import Simplex.Chat.Remote.Types @@ -194,7 +194,7 @@ remoteMessageTest = testChat3 aliceProfile aliceDesktopProfile bobProfile $ \mob remoteStoreFileTest :: HasCallStack => FilePath -> IO () remoteStoreFileTest = - testChatCfg3 cfg aliceProfile aliceDesktopProfile bobProfile $ \mobile desktop bob -> + testChat3 aliceProfile aliceDesktopProfile bobProfile $ \mobile desktop bob -> withXFTPServer $ do let mobileFiles = "./tests/tmp/mobile_files" mobile ##> ("/_files_folder " <> mobileFiles) @@ -317,15 +317,13 @@ remoteStoreFileTest = stopMobile mobile desktop where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp/tmp"} hostError cc err = do r <- getTermLine cc r `shouldStartWith` "remote host 1 error" r `shouldContain` err remoteCLIFileTest :: HasCallStack => FilePath -> IO () -remoteCLIFileTest = testChatCfg3 cfg aliceProfile aliceDesktopProfile bobProfile $ \mobile desktop bob -> withXFTPServer $ do - createDirectoryIfMissing True "./tests/tmp/tmp/" +remoteCLIFileTest = testChat3 aliceProfile aliceDesktopProfile bobProfile $ \mobile desktop bob -> withXFTPServer $ do let mobileFiles = "./tests/tmp/mobile_files" mobile ##> ("/_files_folder " <> mobileFiles) mobile <## "ok" @@ -392,8 +390,6 @@ remoteCLIFileTest = testChatCfg3 cfg aliceProfile aliceDesktopProfile bobProfile B.readFile (bobFiles "test.jpg") `shouldReturn` src' stopMobile mobile desktop - where - cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp/tmp"} switchRemoteHostTest :: FilePath -> IO () switchRemoteHostTest = testChat3 aliceProfile aliceDesktopProfile bobProfile $ \mobile desktop bob -> do