patrol 1.1.0.0 → 1.2.0.0
raw patch · 12 files changed
+220/−168 lines, 12 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Patrol.Type.Headers: fromObject :: Object -> Headers
- Patrol.Type.Headers: instance Data.Aeson.Types.FromJSON.FromJSON Patrol.Type.Headers.Headers
- Patrol.Type.Headers: intoObject :: Headers -> Object
- Patrol.Type.Headers: newtype Headers
- Patrol.Type.Item: Item :: Headers -> ByteString -> Item
- Patrol.Type.Item: [headers] :: Item -> Headers
- Patrol.Type.Item: [payload] :: Item -> ByteString
- Patrol.Type.Item: fromEvent :: Event -> Item
+ Patrol.Type.BreadcrumbType: Debug :: BreadcrumbType
+ Patrol.Type.BreadcrumbType: Error :: BreadcrumbType
+ Patrol.Type.BreadcrumbType: Info :: BreadcrumbType
+ Patrol.Type.BreadcrumbType: Query :: BreadcrumbType
+ Patrol.Type.BreadcrumbType: Transaction :: BreadcrumbType
+ Patrol.Type.BreadcrumbType: UI :: BreadcrumbType
+ Patrol.Type.BreadcrumbType: User :: BreadcrumbType
+ Patrol.Type.Headers: [dsn] :: Headers -> Maybe Dsn
+ Patrol.Type.Headers: [eventId] :: Headers -> Maybe EventId
+ Patrol.Type.Headers: [sdk] :: Headers -> Maybe ClientSdkInfo
+ Patrol.Type.Headers: [sentAt] :: Headers -> Maybe UTCTime
+ Patrol.Type.Headers: data Headers
+ Patrol.Type.Item: Event :: Event -> Item
+ Patrol.Type.Item: Raw :: Item
+ Patrol.Type.Items: EnvelopeItems :: [Item] -> Items
+ Patrol.Type.Items: Raw :: ByteString -> Items
+ Patrol.Type.Items: data Items
+ Patrol.Type.Items: instance GHC.Classes.Eq Patrol.Type.Items.Items
+ Patrol.Type.Items: instance GHC.Internal.Show.Show Patrol.Type.Items.Items
+ Patrol.Type.Items: serialize :: Items -> Builder
- Patrol.Type.Envelope: Envelope :: Headers -> [Item] -> Envelope
+ Patrol.Type.Envelope: Envelope :: Headers -> Items -> Envelope
- Patrol.Type.Envelope: [items] :: Envelope -> [Item]
+ Patrol.Type.Envelope: [items] :: Envelope -> Items
- Patrol.Type.Headers: Headers :: Object -> Headers
+ Patrol.Type.Headers: Headers :: Maybe EventId -> Maybe Dsn -> Maybe ClientSdkInfo -> Maybe UTCTime -> Headers
Files
- patrol.cabal +3/−1
- source/library/Patrol/Type/BreadcrumbType.hs +32/−4
- source/library/Patrol/Type/Envelope.hs +10/−14
- source/library/Patrol/Type/Headers.hs +25/−13
- source/library/Patrol/Type/Item.hs +20/−24
- source/library/Patrol/Type/Items.hs +20/−0
- source/test-suite/Patrol/Type/BreadcrumbTypeSpec.hs +23/−2
- source/test-suite/Patrol/Type/EnvelopeSpec.hs +22/−38
- source/test-suite/Patrol/Type/HeadersSpec.hs +26/−15
- source/test-suite/Patrol/Type/ItemSpec.hs +8/−57
- source/test-suite/Patrol/Type/ItemsSpec.hs +29/−0
- source/test-suite/PatrolSpec.hs +2/−0
patrol.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: patrol-version: 1.1.0.0+version: 1.2.0.0 synopsis: Sentry SDK description: Patrol is a Sentry SDK. build-type: Simple@@ -99,6 +99,7 @@ Patrol.Type.GpuContext Patrol.Type.Headers Patrol.Type.Item+ Patrol.Type.Items Patrol.Type.Level Patrol.Type.LogEntry Patrol.Type.MachException@@ -178,6 +179,7 @@ Patrol.Type.GpuContextSpec Patrol.Type.HeadersSpec Patrol.Type.ItemSpec+ Patrol.Type.ItemsSpec Patrol.Type.LevelSpec Patrol.Type.LogEntrySpec Patrol.Type.MachExceptionSpec
source/library/Patrol/Type/BreadcrumbType.hs view
@@ -2,14 +2,42 @@ import qualified Data.Aeson as Aeson +-- | <https://develop.sentry.dev/sdk/data-model/event-payloads/breadcrumbs/#breadcrumb-types> data BreadcrumbType- = Default- | Http- | Navigation+ = -- | A generic breadcrumb, typically a log message or something user-generated.+ Default+ | -- | A generic debug event, typically a log message.+ Debug+ | -- | An error that occurred before the exception that generates an+ -- 'Patrol.Type.Event.Event'.+ Error+ | -- | A URL change in a web application, a UI transition on mobile or desktop,+ -- or some other event with similar semantics.+ Navigation+ | -- | An HTTP request transmitted from your application.+ Http+ | -- | Information that helps identify the root cause of the issue or for whom+ -- the error occurred.+ Info+ | -- | A query made to the application.+ Query+ | -- | A tracing event.+ Transaction+ | -- | A user interaction with the application's UI, synonymouos with 'User'.+ UI+ | -- | A user interaction with the application's UI, synonymous with 'UI'.+ User deriving (Eq, Show) instance Aeson.ToJSON BreadcrumbType where toJSON breadcrumbType = Aeson.toJSON $ case breadcrumbType of Default -> "default"- Http -> "http"+ Debug -> "debug"+ Error -> "error" Navigation -> "navigation"+ Http -> "http"+ Info -> "info"+ Query -> "query"+ Transaction -> "transaction"+ UI -> "ui"+ User -> "user"
source/library/Patrol/Type/Envelope.hs view
@@ -1,13 +1,9 @@ module Patrol.Type.Envelope where import qualified Control.Monad.Catch as Catch-import qualified Data.Aeson as Aeson-import qualified Data.Aeson.Key as Key-import qualified Data.Aeson.KeyMap as KeyMap import qualified Data.ByteString as ByteString import qualified Data.ByteString.Builder as Builder import qualified Data.ByteString.Lazy as LazyByteString-import qualified Data.Maybe as Maybe import qualified Data.Text as Text import qualified Data.Text.Encoding as Encoding import qualified Network.HTTP.Client as Client@@ -19,11 +15,12 @@ import qualified Patrol.Type.Event as Event import qualified Patrol.Type.Headers as Headers import qualified Patrol.Type.Item as Item+import qualified Patrol.Type.Items as Items -- | <https://develop.sentry.dev/sdk/data-model/envelopes/> data Envelope = Envelope { headers :: Headers.Headers,- items :: [Item.Item]+ items :: Items.Items } deriving (Eq, Show) @@ -31,14 +28,13 @@ fromEvent dsn event = Envelope { headers =- Headers.fromObject- . KeyMap.fromList- $ Maybe.catMaybes- [ Just (Key.fromString "dsn", Aeson.toJSON $ Dsn.intoUri dsn),- Just (Key.fromString "sdk", Aeson.toJSON ClientSdkInfo.patrol),- (,) (Key.fromString "sent_at") . Aeson.toJSON <$> Event.timestamp event- ],- items = [Item.fromEvent event]+ Headers.empty+ { Headers.eventId = Just $ Event.eventId event,+ Headers.dsn = Just dsn,+ Headers.sdk = Just ClientSdkInfo.patrol,+ Headers.sentAt = Event.timestamp event+ },+ items = Items.EnvelopeItems [Item.Event event] } intoRequest :: (Catch.MonadThrow m) => Dsn.Dsn -> Envelope -> m Client.Request@@ -77,4 +73,4 @@ serialize envelope = Headers.serialize (headers envelope) <> Builder.char7 '\n'- <> foldMap ((<> Builder.char7 '\n') . Item.serialize) (items envelope)+ <> Items.serialize (items envelope)
source/library/Patrol/Type/Headers.hs view
@@ -2,26 +2,38 @@ import qualified Data.Aeson as Aeson import qualified Data.ByteString.Builder as Builder+import qualified Data.Time as Time+import qualified Patrol.Extra.Aeson as Aeson+import qualified Patrol.Type.ClientSdkInfo as ClientSdkInfo+import qualified Patrol.Type.Dsn as Dsn+import qualified Patrol.Type.EventId as EventId -- | <https://develop.sentry.dev/sdk/data-model/envelopes/#headers>-newtype Headers- = Headers Aeson.Object+data Headers = Headers+ { eventId :: Maybe EventId.EventId,+ dsn :: Maybe Dsn.Dsn,+ sdk :: Maybe ClientSdkInfo.ClientSdkInfo,+ sentAt :: Maybe Time.UTCTime+ } deriving (Eq, Show) -instance Aeson.FromJSON Headers where- parseJSON = fmap fromObject . Aeson.parseJSON- instance Aeson.ToJSON Headers where- toJSON = Aeson.Object . intoObject--fromObject :: Aeson.Object -> Headers-fromObject = Headers--intoObject :: Headers -> Aeson.Object-intoObject (Headers object) = object+ toJSON headers =+ Aeson.intoObject+ [ Aeson.pair "event_id" $ eventId headers,+ Aeson.pair "dsn" . fmap Dsn.intoUri $ dsn headers,+ Aeson.pair "sdk" $ sdk headers,+ Aeson.pair "sent_at" $ sentAt headers+ ] empty :: Headers-empty = fromObject mempty+empty =+ Headers+ { eventId = Nothing,+ dsn = Nothing,+ sdk = Nothing,+ sentAt = Nothing+ } serialize :: Headers -> Builder.Builder serialize = Aeson.fromEncoding . Aeson.toEncoding
source/library/Patrol/Type/Item.hs view
@@ -1,37 +1,33 @@+{-# LANGUAGE OverloadedStrings #-}+ module Patrol.Type.Item where import qualified Data.Aeson as Aeson import qualified Data.Aeson.Key as Key-import qualified Data.Aeson.KeyMap as KeyMap import qualified Data.ByteString as ByteString import qualified Data.ByteString.Builder as Builder import qualified Data.ByteString.Lazy as LazyByteString import qualified Patrol.Type.Event as Event-import qualified Patrol.Type.Headers as Headers -- | <https://develop.sentry.dev/sdk/data-model/envelope-items/>-data Item = Item- { headers :: Headers.Headers,- payload :: ByteString.ByteString- }+data Item+ = -- | An 'Patrol.Type.Event.Event' item.+ --+ -- <https://develop.sentry.dev/sdk/envelopes/#event>+ Event Event.Event+ | -- | A sentinel item used to filter raw envelopes.+ Raw deriving (Eq, Show) -fromEvent :: Event.Event -> Item-fromEvent event =- let thePayload = LazyByteString.toStrict $ Aeson.encode event- in Item- { headers =- Headers.fromObject $- KeyMap.fromList- [ (Key.fromString "type", Aeson.toJSON "event"),- (Key.fromString "length", Aeson.toJSON $ ByteString.length thePayload),- (Key.fromString "event_id", Aeson.toJSON $ Event.eventId event)- ],- payload = thePayload- }- serialize :: Item -> Builder.Builder-serialize item =- Headers.serialize (headers item)- <> Builder.char7 '\n'- <> Builder.byteString (payload item)+serialize item = case item of+ Event event ->+ let payload = LazyByteString.toStrict $ Aeson.encode event+ headers = buildHeaders "event" (ByteString.length payload)+ in headers <> Builder.char7 '\n' <> Builder.byteString payload+ Raw -> mempty+ where+ buildHeaders :: Key.Key -> Int -> Builder.Builder+ buildHeaders type_ length_ =+ Aeson.fromEncoding $+ Aeson.pairs ("type" Aeson..= type_ <> "length" Aeson..= length_)
+ source/library/Patrol/Type/Items.hs view
@@ -0,0 +1,20 @@+module Patrol.Type.Items where++import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Builder as Builder+import qualified Patrol.Type.Item as Item++-- | The items contained in an 'Patrol.Type.Envelope.Envelope'.+--+-- This is typically a list of 'Patrol.Type.Item.Item', but can also be a+-- binary blob of 'ByteString.ByteString'.+data Items+ = EnvelopeItems [Item.Item]+ | Raw ByteString.ByteString+ deriving (Eq, Show)++serialize :: Items -> Builder.Builder+serialize items = case items of+ Raw buf -> Builder.byteString buf+ EnvelopeItems envelopeItems ->+ foldMap ((<> Builder.char7 '\n') . Item.serialize) envelopeItems
source/test-suite/Patrol/Type/BreadcrumbTypeSpec.hs view
@@ -13,8 +13,29 @@ Hspec.it "works for Default" $ do Aeson.toJSON BreadcrumbType.Default `Hspec.shouldBe` [Aeson.aesonQQ| "default" |] - Hspec.it "works for Http" $ do- Aeson.toJSON BreadcrumbType.Http `Hspec.shouldBe` [Aeson.aesonQQ| "http" |]+ Hspec.it "works for Debug" $ do+ Aeson.toJSON BreadcrumbType.Debug `Hspec.shouldBe` [Aeson.aesonQQ| "debug" |] + Hspec.it "works for Error" $ do+ Aeson.toJSON BreadcrumbType.Error `Hspec.shouldBe` [Aeson.aesonQQ| "error" |]+ Hspec.it "works for Navigation" $ do Aeson.toJSON BreadcrumbType.Navigation `Hspec.shouldBe` [Aeson.aesonQQ| "navigation" |]++ Hspec.it "works for Http" $ do+ Aeson.toJSON BreadcrumbType.Http `Hspec.shouldBe` [Aeson.aesonQQ| "http" |]++ Hspec.it "works for Info" $ do+ Aeson.toJSON BreadcrumbType.Info `Hspec.shouldBe` [Aeson.aesonQQ| "info" |]++ Hspec.it "works for Query" $ do+ Aeson.toJSON BreadcrumbType.Query `Hspec.shouldBe` [Aeson.aesonQQ| "query" |]++ Hspec.it "works for Transaction" $ do+ Aeson.toJSON BreadcrumbType.Transaction `Hspec.shouldBe` [Aeson.aesonQQ| "transaction" |]++ Hspec.it "works for UI" $ do+ Aeson.toJSON BreadcrumbType.UI `Hspec.shouldBe` [Aeson.aesonQQ| "ui" |]++ Hspec.it "works for User" $ do+ Aeson.toJSON BreadcrumbType.User `Hspec.shouldBe` [Aeson.aesonQQ| "user" |]
source/test-suite/Patrol/Type/EnvelopeSpec.hs view
@@ -2,21 +2,20 @@ module Patrol.Type.EnvelopeSpec where -import qualified Data.Aeson as Aeson-import qualified Data.Aeson.KeyMap as KeyMap import qualified Data.ByteString.Builder as Builder import qualified Data.ByteString.Lazy as LazyByteString import qualified Data.Text.Encoding as Text import qualified Network.HTTP.Client as Client import qualified Network.HTTP.Types as Http import qualified Patrol.Constant as Constant-import qualified Patrol.Extra.Aeson as Aeson+import qualified Patrol.Type.ClientSdkInfo as ClientSdkInfo import qualified Patrol.Type.Dsn as Dsn import qualified Patrol.Type.Envelope as Envelope import qualified Patrol.Type.Event as Event+import qualified Patrol.Type.EventId as EventId import qualified Patrol.Type.Headers as Headers import qualified Patrol.Type.Item as Item-import qualified Patrol.Version as Version+import qualified Patrol.Type.Items as Items import qualified Test.Hspec as Hspec spec :: Hspec.Spec@@ -28,65 +27,50 @@ Envelope.serialize Envelope.Envelope { Envelope.headers = Headers.empty,- Envelope.items = []+ Envelope.items = Items.EnvelopeItems [] } actual `Hspec.shouldBe` "{}\n" - Hspec.it "works with one item" $ do+ Hspec.it "works with 'Items.Raw'" $ do let actual = Builder.toLazyByteString $ Envelope.serialize Envelope.Envelope- { Envelope.headers = Headers.fromObject . KeyMap.singleton "a" $ Aeson.toJSON False,- Envelope.items =- [ Item.Item- { Item.headers = Headers.fromObject . KeyMap.singleton "b" $ Aeson.toJSON True,- Item.payload = "c"- }- ]+ { Envelope.headers = Headers.empty,+ Envelope.items = Items.Raw "" }- actual `Hspec.shouldBe` "{\"a\":false}\n{\"b\":true}\nc\n"+ actual `Hspec.shouldBe` "{}\n" - Hspec.it "works with two items" $ do+ Hspec.it "works with 'Items.EnvelopeItems'" $ do let actual = Builder.toLazyByteString $ Envelope.serialize Envelope.Envelope- { Envelope.headers = Headers.fromObject . KeyMap.singleton "a" $ Aeson.toJSON (1 :: Int),- Envelope.items =- [ Item.Item- { Item.headers = Headers.fromObject . KeyMap.singleton "b" $ Aeson.toJSON (2 :: Int),- Item.payload = "c"- },- Item.Item- { Item.headers = Headers.fromObject . KeyMap.singleton "d" $ Aeson.toJSON (3 :: Int),- Item.payload = "e"- }- ]+ { Envelope.headers = Headers.empty,+ Envelope.items = Items.EnvelopeItems [Item.Event Event.empty] }- actual `Hspec.shouldBe` "{\"a\":1}\n{\"b\":2}\nc\n{\"d\":3}\ne\n"+ actual `Hspec.shouldBe` "{}\n{\"type\":\"event\",\"length\":47}\n{\"event_id\":\"00000000000000000000000000000000\"}\n" Hspec.describe "fromEvent" $ do Hspec.it "sets the header" $ do dsn <- Dsn.fromText "http://key@sentry.test/1" let envelope = Envelope.fromEvent dsn Event.empty let expected =- Headers.fromObject $- KeyMap.fromList- [ ("dsn", "http://key@sentry.test/1"),- ( "sdk",- Aeson.object- [ Aeson.pair "name" ("patrol" :: String),- Aeson.pair "version" Version.version- ]- )- ]+ Headers.Headers+ { Headers.eventId = Just EventId.empty,+ Headers.dsn = Just dsn,+ Headers.sdk = Just ClientSdkInfo.patrol,+ Headers.sentAt = Event.timestamp Event.empty+ } Envelope.headers envelope `Hspec.shouldBe` expected Hspec.it "sets the items" $ do dsn <- Dsn.fromText "http://key@sentry.test/1" let envelope = Envelope.fromEvent dsn Event.empty- Envelope.items envelope `Hspec.shouldNotSatisfy` null+ case Envelope.items envelope of+ Items.EnvelopeItems items ->+ items `Hspec.shouldBe` [Item.Event Event.empty]+ other -> Hspec.expectationFailure $ "expected an envelope containing an event, got: " <> show other Hspec.describe "intoRequest" $ do Hspec.it "sets the method" $ do
source/test-suite/Patrol/Type/HeadersSpec.hs view
@@ -2,39 +2,50 @@ module Patrol.Type.HeadersSpec where -import qualified Data.Aeson as Aeson-import qualified Data.Aeson.KeyMap as KeyMap import qualified Data.ByteString.Builder as Builder+import qualified Data.Text as Text+import qualified Data.Time as Time+import qualified Data.UUID as Uuid+import qualified Patrol.Type.ClientSdkInfo as ClientSdkInfo+import qualified Patrol.Type.Dsn as Dsn+import qualified Patrol.Type.EventId as EventId import qualified Patrol.Type.Headers as Headers import qualified Test.Hspec as Hspec spec :: Hspec.Spec spec = Hspec.describe "Patrol.Type.Headers" $ do Hspec.describe "serialize" $ do- Hspec.it "works with an empty object" $ do+ Hspec.it "works with empty Headers" $ do let actual = Builder.toLazyByteString $ Headers.serialize Headers.empty actual `Hspec.shouldBe` "{}" - Hspec.it "works with a singleton object" $ do+ Hspec.it "works with an EventId" $ do let actual = Builder.toLazyByteString . Headers.serialize- . Headers.fromObject- $ KeyMap.singleton "k" Aeson.Null- actual `Hspec.shouldBe` "{\"k\":null}"+ $ Headers.empty {Headers.eventId = Just $ EventId.fromUuid Uuid.nil}+ actual `Hspec.shouldBe` "{\"event_id\":\"00000000000000000000000000000000\"}" - Hspec.it "works with a non-empty object" $ do+ Hspec.it "works with a DSN" $ do+ dsn <- Dsn.fromText (Text.pack "a://b@c/d") let actual = Builder.toLazyByteString . Headers.serialize- . Headers.fromObject- $ KeyMap.fromList [("a", Aeson.toJSON False), ("b", Aeson.toJSON True)]- actual `Hspec.shouldBe` "{\"a\":false,\"b\":true}"+ $ Headers.empty {Headers.dsn = Just dsn}+ actual `Hspec.shouldBe` "{\"dsn\":\"a://b@c/d\"}" - Hspec.it "escapes newlines" $ do+ Hspec.it "works with ClientSdkInfo" $ do+ let clientSdkInfo = ClientSdkInfo.empty {ClientSdkInfo.name = "patrol"} let actual = Builder.toLazyByteString . Headers.serialize- . Headers.fromObject- $ KeyMap.singleton "k" "\n"- actual `Hspec.shouldBe` "{\"k\":\"\\n\"}"+ $ Headers.empty {Headers.sdk = Just clientSdkInfo}+ actual `Hspec.shouldBe` "{\"sdk\":{\"name\":\"patrol\"}}"++ Hspec.it "works with a 'sentAt' timestamp" $ do+ let timestamp = Time.UTCTime (Time.fromGregorian 1970 1 1) 0+ let actual =+ Builder.toLazyByteString+ . Headers.serialize+ $ Headers.empty {Headers.sentAt = Just timestamp}+ actual `Hspec.shouldBe` "{\"sent_at\":\"1970-01-01T00:00:00Z\"}"
source/test-suite/Patrol/Type/ItemSpec.hs view
@@ -2,70 +2,21 @@ module Patrol.Type.ItemSpec where -import qualified Data.Aeson as Aeson-import qualified Data.Aeson.KeyMap as KeyMap import qualified Data.ByteString as ByteString import qualified Data.ByteString.Builder as Builder+import qualified Data.ByteString.Lazy as LazyByteString import qualified Patrol.Type.Event as Event-import qualified Patrol.Type.Headers as Headers import qualified Patrol.Type.Item as Item import qualified Test.Hspec as Hspec spec :: Hspec.Spec spec = Hspec.describe "Patrol.Type.Item" $ do Hspec.describe "serialize" $ do- Hspec.it "works with an empty payload" $ do- let actual =- Builder.toLazyByteString $- Item.serialize- Item.Item- { Item.headers = Headers.empty,- Item.payload = ""- }- actual `Hspec.shouldBe` "{}\n"-- Hspec.it "works with a non-empty payload" $ do- let actual =- Builder.toLazyByteString $- Item.serialize- Item.Item- { Item.headers = Headers.empty,- Item.payload = "x"- }- actual `Hspec.shouldBe` "{}\nx"-- Hspec.it "allows newlines in the payload" $ do- -- <https://develop.sentry.dev/sdk/data-model/envelopes/#items>- -- If no `length` is specified, the payload implicitly goes to the next- -- newline. For payloads containing newline characters, the `length` must- -- be specified.+ Hspec.it "works on Event" $ do let actual =- Builder.toLazyByteString $- Item.serialize- Item.Item- { Item.headers =- Headers.fromObject- . KeyMap.singleton "length"- $ Aeson.toJSON (3 :: Int),- Item.payload = "a\nb"- }- actual `Hspec.shouldBe` "{\"length\":3}\na\nb"-- Hspec.describe "fromEvent" $ do- Hspec.it "sets the headers" $ do- let event = Event.empty- let actual = Item.fromEvent event- let expected =- Headers.fromObject $- KeyMap.fromList- [ ("type", "event"),- ("length", Aeson.toJSON (47 :: Int)),- ("event_id", Aeson.toJSON $ Event.eventId event)- ]- Item.headers actual `Hspec.shouldBe` expected-- Hspec.it "sets the payload" $ do- let event = Event.empty- let actual = Item.fromEvent event- let expected = "{\"event_id\":\"00000000000000000000000000000000\"}" :: ByteString.ByteString- Item.payload actual `Hspec.shouldBe` expected+ LazyByteString.toStrict+ . Builder.toLazyByteString+ . Item.serialize+ $ Item.Event Event.empty+ let expected = "{\"type\":\"event\",\"length\":47}\n{\"event_id\":\"00000000000000000000000000000000\"}" :: ByteString.ByteString+ actual `Hspec.shouldBe` expected
+ source/test-suite/Patrol/Type/ItemsSpec.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE OverloadedStrings #-}++module Patrol.Type.ItemsSpec where++import qualified Data.ByteString.Builder as Builder+import qualified Data.ByteString.Lazy as LazyByteString+import qualified Patrol.Type.Event as Event+import qualified Patrol.Type.Item as Item+import qualified Patrol.Type.Items as Items+import qualified Test.Hspec as Hspec++spec :: Hspec.Spec+spec = Hspec.describe "Patrol.Type.Items" $ do+ Hspec.describe "serialize" $ do+ Hspec.it "works on a raw binary blob" $ do+ let actual =+ LazyByteString.toStrict+ . Builder.toLazyByteString+ . Items.serialize+ $ Items.Raw "test"+ actual `Hspec.shouldBe` "test"++ Hspec.it "works with a single Event" $ do+ let actual =+ LazyByteString.toStrict+ . Builder.toLazyByteString+ . Items.serialize+ $ Items.EnvelopeItems [Item.Event Event.empty]+ actual `Hspec.shouldBe` "{\"type\":\"event\",\"length\":47}\n{\"event_id\":\"00000000000000000000000000000000\"}\n"
source/test-suite/PatrolSpec.hs view
@@ -31,6 +31,7 @@ import qualified Patrol.Type.GpuContextSpec import qualified Patrol.Type.HeadersSpec import qualified Patrol.Type.ItemSpec+import qualified Patrol.Type.ItemsSpec import qualified Patrol.Type.LevelSpec import qualified Patrol.Type.LogEntrySpec import qualified Patrol.Type.MachExceptionSpec@@ -79,6 +80,7 @@ Patrol.Type.EnvelopeSpec.spec Patrol.Type.HeadersSpec.spec Patrol.Type.ItemSpec.spec+ Patrol.Type.ItemsSpec.spec Patrol.Type.ErrorTypeSpec.spec Patrol.Type.EventIdSpec.spec Patrol.Type.EventProcessingErrorSpec.spec