Files
simplexmq/tests/CoreTests/EncodingTests.hs
Evgeny af9ca59e51 smp server: optimize concurrency and memory usage, refactor (#1544)
* smp server: optimize concurrency and memory usage, refactor

* hide clients IntMap

* reduce STM contention

* comment

* version

* correct stats for subscriptions

* version

* comment

* remove subscribed clients from map

* version

* optimze, refactor

* version

* debug test

* enable all tests

* remove test logs

* retry failed tests with debug logging

* increase test timeout

* sync between tests
2025-05-23 12:52:18 +01:00

81 lines
3.9 KiB
Haskell

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module CoreTests.EncodingTests where
import Data.Bits (shiftR)
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as B
import Data.ByteString.Internal (w2c)
import Data.Int (Int64)
import Data.Time.Clock.System (SystemTime (..), getSystemTime, utcToSystemTime)
import Data.Time.ISO8601 (parseISO8601)
import Simplex.Messaging.Encoding
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Parsers (parseAll)
import Simplex.Messaging.Transport.Client (TransportHost (..))
import Test.Hspec hiding (fit, it)
import Test.Hspec.QuickCheck (modifyMaxSuccess)
import Test.QuickCheck
import Util
int64 :: Int64
int64 = 1234567890123456789
s64 :: ByteString
s64 = B.pack $ map (w2c . fromIntegral . (int64 `shiftR`)) [56, 48, 40, 32, 24, 16, 8, 0]
encodingTests :: Spec
encodingTests = modifyMaxSuccess (const 1000) $ do
describe "Encoding Int64" $ do
it "should encode and decode Int64 example" $ do
s64 `shouldBe` "\17\34\16\244\125\233\129\21"
smpEncode int64 `shouldBe` s64
parseAll smpP s64 `shouldBe` Right int64
it "parse(encode(Int64) should equal the same Int64" . property $
\i -> parseAll smpP (smpEncode i) == Right (i :: Int64)
describe "Encoding SystemTime" $ do
it "should encode and decode SystemTime" $ do
t <- getSystemTime
testSystemTime t
Just t' <- pure $ utcToSystemTime <$> parseISO8601 "2022-01-01T10:24:05.000Z"
systemSeconds t' `shouldBe` 1641032645
testSystemTime t'
it "parse(encode(SystemTime) should equal the same Int64" . property $
\i -> parseAll smpP (smpEncode i) == Right (i :: Int64)
describe "Encoding transport hosts" $ do
describe "domain name hosts" $ do
it "should encode / decode domain name" $ THDomainName "smp.simplex.im" #==# "smp.simplex.im"
it "should not allow whitespace or punctuation" $ do
shouldNotParse @TransportHost "smp,simplex.im" "endOfInput"
shouldNotParse @TransportHost "smp:simplex.im" "endOfInput"
shouldNotParse @TransportHost "smp#simplex.im" "endOfInput"
shouldNotParse @TransportHost "smp simplex.im" "endOfInput"
shouldNotParse @TransportHost "smp\nsimplex.im" "endOfInput"
describe "onion hosts" $ do
it "should encode / decode onion host" $ THOnionHost "beccx4yfxxbvyhqypaavemqurytl6hozr47wfc7uuecacjqdvwpw2xid.onion" #==# "beccx4yfxxbvyhqypaavemqurytl6hozr47wfc7uuecacjqdvwpw2xid.onion"
it "should only allow latin letters and digits" $ do
shouldNotParse @TransportHost "beccx4yfxxbvyhqypaavemqurytl 6hozr47wfc7uuecacjqdvwpw2xid.onion" "endOfInput"
shouldNotParse @TransportHost "beccx4yfxxbvyhqypaavemqurytl\n6hozr47wfc7uuecacjqdvwpw2xid.onion" "endOfInput"
shouldNotParse @TransportHost "bèccx4yfxxbvyhqypaavemqurytl6hozr47wfc7uuecacjqdvwpw2xid.onion" "Failed reading: empty"
describe "IP address hosts" $ do
it "should encode / decode IP address" $ THIPv4 (192, 168, 0, 1) #==# "192.168.0.1"
it "should be valid" $ do
THDomainName "192.168.1" #==# "192.168.1"
THDomainName "192.256.0.1" #==# "192.256.0.1"
THDomainName "192.168.0.-1" #==# "192.168.0.-1"
shouldNotParse @TransportHost "192.168.0.0.1" "endOfInput"
where
testSystemTime :: SystemTime -> Expectation
testSystemTime t = do
smpEncode t `shouldBe` smpEncode (systemSeconds t)
smpDecode (smpEncode t) `shouldBe` Right t {systemNanoseconds = 0}
(#==#) :: (StrEncoding s, Eq s, Show s) => s -> ByteString -> Expectation
(#==#) x s = do
strEncode x `shouldBe` s
strDecode s `shouldBe` Right x
shouldNotParse :: forall s. (StrEncoding s, Eq s, Show s) => ByteString -> String -> Expectation
shouldNotParse s err = strDecode s `shouldBe` (Left err :: Either String s)