packages feed

ceilometer-common 0.2.2 → 0.2.3

raw patch · 5 files changed

+635/−7 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Ceilometer.Types: time :: Lens' (Timed value_atbj) Word64
+ Ceilometer.Types: time :: Lens' (Timed value_atc7) Word64

Files

ceilometer-common.cabal view
@@ -1,7 +1,10 @@ name:                ceilometer-common-version:             0.2.2-synopsis:            Common Haskell types and encoding for ceilometer-description:         Provides a set of common types for use with ceilometer related packages.+version:             0.2.3+synopsis:            Common Haskell types and encoding for OpenStack Ceilometer+description:         This package defines a library with two interfaces: one +                     for working with the data producers (e.g. the collector for +                     OpenStack Ceilometer) and one for the consumers (e.g. the +                     Borel metering and billing system). homepage:            https://github.com/anchor/ceilometer-common license:             BSD3 license-file:        LICENSE@@ -55,7 +58,9 @@   hs-source-dirs:      tests,lib    main-is:             Main.hs-+  other-modules:       Fold+                     , Prisms+                     , SampleData   build-depends:       base >=4.7 && < 5                      , QuickCheck >= 2.7                      , bimap >= 0.2
lib/Ceilometer/Client.hs view
@@ -26,7 +26,10 @@   , decodeFold_      -- * Re-exports-  , module C+  , module Ceilometer.Fold +  , module Ceilometer.Tags+  , module Ceilometer.Types+  , module Vaultaire.Types   ) where  import           Control.Applicative@@ -37,9 +40,9 @@ import           Pipes import qualified Pipes.Prelude       as P -import           Ceilometer.Fold     as C+import           Ceilometer.Fold     import           Ceilometer.Tags-import           Ceilometer.Types    as C+import           Ceilometer.Types   import           Vaultaire.Types  
+ tests/Fold.hs view
@@ -0,0 +1,112 @@+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}+module Fold where++import qualified Control.Foldl         as L+import qualified Data.Map              as M+import           Test.Hspec+import           Test.Hspec.QuickCheck+import           Test.QuickCheck++import           Ceilometer.Fold+import           Ceilometer.Types++import           SampleData++suite :: Spec+suite = do+  -- "Cumulative Pollster" resources+  describe "Folding points for CUMULATIVE resource: CPU" $ do+    it "ok for monotonically decreasing points"+      $ L.fold foldCPU cpuDecreasing `shouldBe` cumulativeDecreasingResult++    it "ok for monotonically increasing points"+      $ L.fold foldCPU cpuIncreasing `shouldBe` cumulativeIncreasingResult++    it "ok for non-monotonic points"+      $ L.fold foldCPU cpuAny `shouldBe` cumulativeAnyResult++  describe "Folding points for CUMULATIVE resource: NeutronRx" $ do+    it "ok for monotonically decreasing points"+      $ L.fold foldNeutronRx neutronRxDecreasing `shouldBe` cumulativeDecreasingResult++    it "ok for monotonically increasing points"+      $ L.fold foldNeutronRx neutronRxIncreasing `shouldBe` cumulativeIncreasingResult++    it "ok for non-monotonic points"+      $ L.fold foldNeutronRx neutronRxAny `shouldBe` cumulativeAnyResult++  describe "Folding points for CUMULATIVE resource: NeutronTx" $ do+    it "ok for monotonically decreasing points"+      $ L.fold foldNeutronTx neutronTxDecreasing `shouldBe` cumulativeDecreasingResult++    it "ok for monotonically increasing points"+      $ L.fold foldNeutronTx neutronTxIncreasing `shouldBe` cumulativeIncreasingResult++    it "ok for non-monotonic points"+      $ L.fold foldNeutronTx neutronTxAny `shouldBe` cumulativeAnyResult++  describe "Folding points for CUMULATIVE resource: DiskWrite" $ do+    it "ok for monotonically decreasing points"+      $ L.fold foldDiskWrite diskWriteDecreasing `shouldBe` cumulativeDecreasingResult++    it "ok for monotonically increasing points"+      $ L.fold foldDiskWrite diskWriteIncreasing `shouldBe` cumulativeIncreasingResult++    it "ok for non-monotonic points"+      $ L.fold foldDiskWrite diskWriteAny `shouldBe` cumulativeAnyResult++  describe "Folding points for CUMULATIVE resource: DiskRead" $ do+    it "ok for monotonically decreasing points"+      $ L.fold foldDiskRead diskReadDecreasing `shouldBe` cumulativeDecreasingResult++    it "ok for monotonically increasing points"+      $ L.fold foldDiskRead diskReadIncreasing `shouldBe` cumulativeIncreasingResult++    it "ok for non-monotonic points"+      $ L.fold foldDiskRead diskReadAny `shouldBe` cumulativeAnyResult++  -- "Gauge Event" resources+  describe "Folding points for EVENT resource: VOLUME" $+    it "ok for example payload"+      $ L.fold foldVolumeAll volumeTimedPDs `shouldBe` volumeTimedPDsResult++  describe "Folding points for EVENT resource: SSD" $+    it "ok for example payload"+      $ L.fold foldSSDAll ssdTimedPDs `shouldBe` ssdTimedPDsResult++  describe "Folding points for EVENT resource: IMAGE" $+    it "ok for example payload"+      $ L.fold foldImageAll imageTimedPDs `shouldBe` imageTimedPDsResult++  describe "Folding points for EVENT resource: SNAPSHOT" $+    it "ok for example payload"+      $ L.fold foldSnapshotAll snapshotTimedPDs `shouldBe` snapshotTimedPDsResult++  -- "Gauge Pollster" resources+  describe "Folding points for POLLSTER resource: INSTANCE FLAVOR" $+    it "ok for example payload"+      $ L.fold (foldInstanceFlavor $ const True) flavorTimedPDs `shouldBe` M.fromList flavorTimedPDsResult++  describe "Filtering instance statuses" $+      prop "is sane" propSafetyInstance++  describe "Folding points for POLLSTER resource: IMAGE POLLSTER" $+    it "ok for example payload"+      $ L.fold foldImagePollster imagePTimedPDs `shouldBe` imagePTimedPDsResult++{- This test no longer applies since we assume no more event after delete+  +  describe "Folding points on edge cases:" $+    prop "discards the rest after VOLUME DELETE" $ property $ do+      vs0 <- listOf volumeNonDelete+      vs1 <- listOf volumeNonDelete+      let bomb = PDVolume VolumeAvailable VolumeDelete Start 10+      let xs0  = zipWith Timed [testS..] $ vs0 ++ [bomb]+      let xs1  = zipWith Timed [testS..] $ vs0 ++ [bomb] ++ vs1+      return $ L.fold foldVolumeAll xs0 == L.fold foldVolumeAll xs1+-}++  where foldVolumeAll   = foldVolume   (testS, testE)+        foldSSDAll      = foldSSD      (testS, testE)+        foldImageAll    = foldImage    (testS, testE)+        foldSnapshotAll = foldSnapshot (testS, testE)
+ tests/Prisms.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE RankNTypes #-}+module Prisms where++import           Control.Lens            hiding (elements)+import           Control.Lens.Properties+import           Test.Hspec+import           Test.Hspec.QuickCheck+import           Test.QuickCheck++import           Ceilometer.Types+import           SampleData++suite :: Spec+suite = do+  -- Optics for raw payloads aren't required to be proper, since we are+  -- ignoring some bits of the serialised format (Word64), depending on+  -- the raw payload type.+  --+  -- They should still satisfy prism identity since that is concerned with+  -- the RHS of the prism only, but they don't need to satisfy the "suffcient"+  -- law.++  -- does what it says it does+  describe "CHECK: prism for RAW payload: " $ do+    prop "obey the identity prism law" $ prismIdentity prCompoundEvent+    prop "obey the identity prism law" $ prismIdentity prCompoundPollster++  describe "CHECK: prism for DECODED PAYLOAD FIELD: " $ do+    prop "ENDPOINT        - is a proper prism" $ isPrism pfEndpoint+    prop "VOLUME STATUS   - is a proper prism" $ isPrism pfVolumeStatus+    prop "VOLUME VERB     - is a proper prism" $ isPrism pfVolumeVerb+    prop "IMAGE STATUS    - is a proper prism" $ isPrism pfImageStatus+    prop "IMAGE VERB      - is a proper prism" $ isPrism pfImageVerb+    prop "SNAPSHOT STATUS - is a proper prism" $ isPrism pfSnapshotStatus+    prop "SNAPSHOT VERB   - is a proper prism" $ isPrism pfSnapshotVerb+    prop "IP STATUS       - is a proper prism" $ isPrism pfIPStatus+    prop "IP VERB         - is a proper prism" $ isPrism pfIPVerb++  describe "CHECK: prism for DECODED PAYLOAD: " $ do+    prop "VOLUME   - is a proper prism" $ isPrism pdVolume+    prop "SSD      - is a proper prism" $ isPrism pdSSD+    prop "CPU      - is a proper prism" $ isPrism pdCPU+    prop "VCPU     - is a proper prism" $ isPrism pdInstanceVCPU+    prop "RAM      - is a proper prism" $ isPrism pdInstanceRAM+    prop "DISK     - is a proper prism" $ isPrism pdInstanceDisk+    prop "FLAVOR   - is a proper prism" $ isPrism $ pdInstanceFlavor testFlavors+    prop "IMAGE    - is a proper prism" $ isPrism pdImage+    prop "SNAPSHOT - is a proper prism" $ isPrism pdSnapshot+    prop "IP       - is a proper prism" $ isPrism pdIP++  -- what it does is what we expect+  describe "REFINE: prism:" $ do+    it "parses/prints values correct to spec for: VOLUME" $+      shouldAllBe (preview pdVolume . view prCompoundEvent) volumePRs volumePDs++    it "parses/prints values correct to spec for: SSD" $+      shouldAllBe (preview pdSSD . view prCompoundEvent) ssdPRs ssdPDs++    it "parses/prints values correct to spec for: INSTANCE FLAVOR" $+      shouldAllBe (preview (pdInstanceFlavor testFlavors) . view prCompoundPollster) flavorPRs flavorPDs++    it "parses/prints values correct to spec for: IMAGE" $+      shouldAllBe (preview pdImage    . view prCompoundEvent) imagePRs imagePDs++    it "parses/prints values correct to spec for: SNAPSHOT" $+      shouldAllBe (preview pdSnapshot . view prCompoundEvent) snapshotPRs snapshotPDs++    it "parses/prints values correct to spec for: IP" $+      shouldAllBe (preview pdIP       . view prCompoundEvent) ipPRs ipPDs+  where shouldAllBe f xs ys = map f xs `shouldBe` map Just ys+++prismIdentity :: Eq b => Prism' a b -> b -> Property+prismIdentity l b = property $ preview l (review l b) == Just b
+ tests/SampleData.hs view
@@ -0,0 +1,434 @@+-- This module defines hard-coded sample data+-- for parsing/printing and folding.+--+{-# LANGUAGE FlexibleInstances    #-}+{-# LANGUAGE OverlappingInstances #-}+{-# LANGUAGE OverloadedStrings    #-}+{-# LANGUAGE TypeSynonymInstances #-}++{-# OPTIONS -fno-warn-orphans#-}+{-# OPTIONS -fno-warn-missing-signatures #-}++module SampleData where++import           Control.Applicative+import qualified Control.Foldl             as L+import           Control.Lens              hiding (elements)+import           Control.Monad+import qualified Data.Bimap                as BM+import           Data.Binary               (Word64)+import           Data.Bits+import           Data.List.Ordered+import           Data.Map                  (Map)+import qualified Data.Map                  as M+import           Data.Maybe+import           Data.Word+import           Test.QuickCheck+import           Test.QuickCheck.Function++import           Ceilometer.Fold+import           Ceilometer.Types+import           Ceilometer.Types.Image    (imageVerb)+import           Ceilometer.Types.Instance (siphashID)+import           Ceilometer.Types.IP       (ipVerb)+import           Ceilometer.Types.Snapshot (snapshotVerb)+import           Ceilometer.Types.Volume   (volumeVerb)+++-- Instances (DO NOT DEFNE NEW ONES IN TESTS) ----------------------------------++instance Function PFEndpoint       where function = functionShow+instance Function PFVolumeStatus   where function = functionShow+instance Function PFVolumeVerb     where function = functionShow+instance Function PFImageStatus    where function = functionShow+instance Function PFImageVerb      where function = functionShow+instance Function PFSnapshotStatus where function = functionShow+instance Function PFSnapshotVerb   where function = functionShow+instance Function PFIPStatus       where function = functionShow+instance Function PFIPVerb         where function = functionShow+instance Function PDCPU            where function = functionShow+instance Function PDVolume         where function = functionShow+instance Function PDSSD            where function = functionShow+instance Function PDImage          where function = functionShow+instance Function PDImagePollster  where function = functionShow+instance Function PDIP             where function = functionShow+instance Function PDSnapshot       where function = functionShow+instance Function PDInstanceVCPU   where function = functionShow+instance Function PDInstanceRAM    where function = functionShow+instance Function PDInstanceDisk   where function = functionShow+instance Function PDInstanceFlavor where function = functionShow++instance Arbitrary a => Arbitrary [Timed a] where+  arbitrary = do+    bigNumber <- choose (1, 10000)+    let ts = [1..bigNumber]+    vs <- replicateM (fromIntegral bigNumber) arbitrary+    return $ zipWith Timed ts vs++instance Arbitrary PRSimple        where+  arbitrary = PRSimple <$> arbitrary+instance Arbitrary PRCompoundEvent where+  arbitrary =   PRCompoundEvent+            <$> arbitrary+            <*> arbitrary+            <*> arbitrary+            <*> arbitrary+instance Arbitrary PRCompoundPollster where+  arbitrary =   PRCompoundPollster+            <$> arbitrary+            <*> arbitrary++instance Arbitrary PFEndpoint       where arbitrary = arbitraryBoundedEnum+instance Arbitrary PFVolumeVerb     where arbitrary = arbitraryBoundedEnum+instance Arbitrary PFVolumeStatus   where arbitrary = arbitraryBoundedEnum+instance Arbitrary PFInstanceStatus where arbitrary = arbitraryBoundedEnum+instance Arbitrary PFImageVerb      where arbitrary = arbitraryBoundedEnum+instance Arbitrary PFImageStatus    where arbitrary = arbitraryBoundedEnum+instance Arbitrary PFSnapshotVerb   where arbitrary = arbitraryBoundedEnum+instance Arbitrary PFSnapshotStatus where arbitrary = arbitraryBoundedEnum+instance Arbitrary PFIPVerb         where arbitrary = arbitraryBoundedEnum+instance Arbitrary PFIPStatus       where arbitrary = arbitraryBoundedEnum+instance Arbitrary PFIPAlloc        where arbitrary = arbitraryBoundedEnum+instance Arbitrary PFValueText      where arbitrary = elements $ BM.keys testFlavors++instance Arbitrary PDCPU            where arbitrary =   PDCPU <$> arbitrary+instance Arbitrary PDVolume         where arbitrary =   PDVolume+                                                  <$> arbitrary+                                                  <*> arbitrary+                                                  <*> arbitrary+                                                  <*> arbitrary+instance Arbitrary PDSSD            where arbitrary =   PDSSD+                                                  <$> arbitrary+                                                  <*> arbitrary+                                                  <*> arbitrary+                                                  <*> arbitrary+instance Arbitrary PDInstanceVCPU   where arbitrary =   PDInstanceVCPU+                                                  <$> arbitrary+                                                  <*> arbitrary+instance Arbitrary PDInstanceRAM    where arbitrary =   PDInstanceRAM+                                                  <$> arbitrary+                                                  <*> arbitrary+instance Arbitrary PDInstanceDisk   where arbitrary =   PDInstanceDisk+                                                  <$> arbitrary+                                                  <*> arbitrary+instance Arbitrary PDInstanceFlavor where arbitrary =   PDInstanceFlavor+                                                  <$> arbitrary+                                                  <*> arbitrary+instance Arbitrary PDImage          where arbitrary =   PDImage+                                                  <$> arbitrary+                                                  <*> arbitrary+                                                  <*> arbitrary+                                                  <*> arbitrary+instance Arbitrary PDImagePollster  where arbitrary =   PDImagePollster <$> arbitrary+instance Arbitrary PDSnapshot       where arbitrary =   PDSnapshot+                                                  <$> arbitrary+                                                  <*> arbitrary+                                                  <*> arbitrary+                                                  <*> arbitrary+instance Arbitrary PDIP             where arbitrary =   PDIP+                                                  <$> arbitrary+                                                  <*> arbitrary+                                                  <*> arbitrary+                                                  <*> arbitrary++instance CoArbitrary PFEndpoint       where coarbitrary = variant . fromEnum+instance CoArbitrary PFVolumeStatus   where coarbitrary = variant . fromEnum+instance CoArbitrary PFVolumeVerb     where coarbitrary = variant . fromEnum+instance CoArbitrary PFImageVerb      where coarbitrary = variant . fromEnum+instance CoArbitrary PFImageStatus    where coarbitrary = variant . fromEnum+instance CoArbitrary PFSnapshotVerb   where coarbitrary = variant . fromEnum+instance CoArbitrary PFSnapshotStatus where coarbitrary = variant . fromEnum+instance CoArbitrary PFIPVerb         where coarbitrary = variant . fromEnum+instance CoArbitrary PFIPStatus       where coarbitrary = variant . fromEnum++instance CoArbitrary PDCPU            where+  coarbitrary x = variant $ x ^. re pdCPU      . re prSimple+instance CoArbitrary PDVolume         where+  coarbitrary x = variant $ x ^. re pdVolume   . re prCompoundEvent+instance CoArbitrary PDSSD            where+  coarbitrary x = variant $ x ^. re pdSSD      . re prCompoundEvent+instance CoArbitrary PDImage          where+  coarbitrary x = variant $ x ^. re pdImage    . re prCompoundEvent+instance CoArbitrary PDImagePollster  where+  coarbitrary x = variant $ x ^. re pdImagePollster   . re prSimple+instance CoArbitrary PDSnapshot       where+  coarbitrary x = variant $ x ^. re pdSnapshot . re prCompoundEvent+instance CoArbitrary PDIP             where+  coarbitrary x = variant $ x ^. re pdIP       . re prCompoundEvent+instance CoArbitrary PDInstanceFlavor where+  coarbitrary x = variant $ x ^. re (pdInstanceFlavor testFlavors) . re prCompoundPollster+instance CoArbitrary PDInstanceVCPU   where+  coarbitrary x = variant $ x ^. re pdInstanceVCPU . re prCompoundPollster+instance CoArbitrary PDInstanceRAM    where+  coarbitrary x = variant $ x ^. re pdInstanceRAM  . re prCompoundPollster+instance CoArbitrary PDInstanceDisk   where+  coarbitrary x = variant $ x ^. re pdInstanceDisk . re prCompoundPollster+++testS, testE :: Word64+testS = 1300000000000000000+testE = 1400000000000000000+++-- INSTANCES -------------------------------------------------------------------++testFlavors :: FlavorMap+testFlavors = BM.fromList [ (flavorID0, flavorSP0)+                          , (flavorID1, flavorSP1)+                          , (flavorID2, flavorSP2) ]++flavorID0   = "deadbeef"+flavorSP0   = siphashID flavorID0+flavorID1   = "koolaid"+flavorSP1   = siphashID flavorID1+flavorID2   = "chicken"+flavorSP2   = siphashID flavorID2++flavorPR0, flavorPR1, flavorPR2 :: Word64+flavorPR0 = 1  + (0 `shift` 8) + (0 `shift` 16) + (fromIntegral flavorSP0 `shift` 32)+flavorPR1 = 9  + (0 `shift` 8) + (0 `shift` 16) + (fromIntegral flavorSP1 `shift` 32)+flavorPR2 = 15 + (0 `shift` 8) + (0 `shift` 16) + (fromIntegral flavorSP2 `shift` 32)++flavorPRs = [ flavorPR0, flavorPR1, flavorPR2 ]++flavorPD0 = PDInstanceFlavor InstanceActive flavorID0+flavorPD1 = PDInstanceFlavor InstanceReboot flavorID1+flavorPD2 = PDInstanceFlavor InstancePaused flavorID2++flavorPDs = [ flavorPD0, flavorPD1, flavorPD2 ]++flavorTimedPDs = [ Timed testS flavorPD1+                 , Timed (testS + 2) flavorPD1+                 , Timed (testS + 7) flavorPD2+                 , Timed (testS + 11) flavorPD1+                 , Timed (testS + 13) flavorPD1 ]++flavorTimedPDsResult :: [(PFValue PDInstanceFlavor, Word64)]+flavorTimedPDsResult = [ (flavorID1, 9)+                       , (flavorID2, 4) ]+++-- | Basic safety properties for filtered folding.+--   The set of keys in the result of the filtered fold should be a subset of+--   the result of the non-filtered fold.+--   For each defined key in the filtered result, the corresponding value+--   should be no larger than in the non-filtered result.+propSafetyInstance :: [Timed PDInstanceFlavor] -> Bool+propSafetyInstance x =+    let testPred (PDInstanceFlavor InstanceActive _) = True+        testPred _                                   = False+        fullResult     = L.fold (foldInstanceFlavor (const True)) x+        filteredResult = L.fold (foldInstanceFlavor testPred    ) x+        fullKeys       = M.keys fullResult+        filteredKeys   = M.keys filteredResult+    in  subset filteredKeys fullKeys &&+        all (\k -> isJust $ do+                v  <- M.lookup k fullResult+                v' <- M.lookup k filteredResult+                return $ v' <= v) filteredKeys++-- CPU -------------------------------------------------------------------------++cumulativeIncreasing = [30, 40, 50, 60]+cumulativeDecreasing = [40, 30, 20, 10]+cumulativeAny        = [20, 30, 10, 20, 30, 40, 10]++cpuIncreasing        = map PDCPU cumulativeIncreasing+cpuDecreasing        = map PDCPU cumulativeDecreasing+cpuAny               = map PDCPU cumulativeAny++neutronRxIncreasing  = map PDNeutronRx cumulativeIncreasing+neutronRxDecreasing  = map PDNeutronRx cumulativeDecreasing+neutronRxAny         = map PDNeutronRx cumulativeAny++neutronTxIncreasing  = map PDNeutronTx cumulativeIncreasing+neutronTxDecreasing  = map PDNeutronTx cumulativeDecreasing+neutronTxAny         = map PDNeutronTx cumulativeAny++diskReadIncreasing   = map PDDiskRead cumulativeIncreasing+diskReadDecreasing   = map PDDiskRead cumulativeDecreasing+diskReadAny          = map PDDiskRead cumulativeAny++diskWriteIncreasing  = map PDDiskWrite cumulativeIncreasing+diskWriteDecreasing  = map PDDiskWrite cumulativeDecreasing+diskWriteAny         = map PDDiskWrite cumulativeAny++cumulativeDecreasingResult, cumulativeIncreasingResult, cumulativeAnyResult :: Word64+cumulativeDecreasingResult = 60+cumulativeIncreasingResult = 30+cumulativeAnyResult        = 60+++-- VOLUME ----------------------------------------------------------------------++volumeNonDelete :: Gen PDVolume+volumeNonDelete = (arbitrary :: Gen PDVolume) `suchThat` ((/= VolumeDelete) . view volumeVerb)++-- Raw payloads for volume points+volumePRs = [volumePR0, volumePR1, volumePR2 ]+ssdPRs = volumePRs++volumePR0, volumePR1, volumePR2 :: Word64+volumePR0 = 2 + (1 `shift` 8) + (2 `shift` 16) + (10 `shift` 32)+volumePR1 = 2 + (1 `shift` 8) + (2 `shift` 16) + (30 `shift` 32)+volumePR2 = 4 + (3 `shift` 8) + (2 `shift` 16) + (30 `shift` 32)++-- Decoded payloads for volume points+volumePDs = [volumePD0, volumePD1, volumePD2 ]++volumePD0, volumePD1, volumePD2 :: PDVolume+volumePD0 = PDVolume VolumeCreating VolumeCreate End 10+volumePD1 = PDVolume VolumeCreating VolumeCreate End 30+volumePD2 = PDVolume VolumeDeleting VolumeDelete End 30++ssdPDs = [ssdPD0, ssdPD1, ssdPD2 ]++ssdPD0, ssdPD1, ssdPD2 :: PDSSD+ssdPD0 = PDSSD VolumeCreating VolumeCreate End 10+ssdPD1 = PDSSD VolumeCreating VolumeCreate End 30+ssdPD2 = PDSSD VolumeDeleting VolumeDelete End 30++volumeTimedPDs :: [Timed PDVolume]+volumeTimedPDs = [ Timed testS        volumePD0+                 , Timed (testS + 2)  volumePD1+                 , Timed (testS + 7)  volumePD1+                 , Timed (testS + 11) volumePD0+                 , Timed (testS + 21) volumePD2 ]++ssdTimedPDs :: [Timed PDSSD]+ssdTimedPDs = [ Timed testS        ssdPD0+              , Timed (testS + 2)  ssdPD1+              , Timed (testS + 7)  ssdPD1+              , Timed (testS + 11) ssdPD0+              , Timed (testS + 21) ssdPD2 ]++-- Volume events+-- Expected = 2 * 10 + 5 * 30 + 4 * 30 + 10 * 10+--          = (2 + 10) * 10 + (5 + 4) * 30+--          = 12 * 10 + 9 * 30+--          = 390+-- from borel-core+--+volumeTimedPDsResult :: Word64+volumeTimedPDsResult = 390++ssdTimedPDsResult :: Word64+ssdTimedPDsResult = volumeTimedPDsResult++-- IMAGE ----------------------------------------------------------------------++imageNonDelete :: Gen PDImage+imageNonDelete = (arbitrary :: Gen PDImage) `suchThat` ((/= ImageDelete) . view imageVerb)++-- Raw payloads for volume points+imagePRs = [imagePR0, imagePR1, imagePR2 ]++imagePR0, imagePR1, imagePR2 :: Word64+imagePR0 = 1 + (3 `shift` 8) + (0 `shift` 16) + (200000 `shift` 32)+imagePR1 = 1 + (1 `shift` 8) + (0 `shift` 16) + (400000 `shift` 32)+imagePR2 = 3 + (5 `shift` 8) + (0 `shift` 16) + (100000 `shift` 32)++-- Decoded payloads for image points+imagePDs = [imagePD0, imagePD1, imagePD2 ]++imagePD0, imagePD1, imagePD2 :: PDImage+imagePD0 = PDImage ImageActive  ImageUpload Instant 200000+imagePD1 = PDImage ImageActive  ImageServe  Instant 400000+imagePD2 = PDImage ImageDeleted ImageDelete Instant 100000++imageTimedPDs :: [Timed PDImage]+imageTimedPDs = [ Timed testS        imagePD0+                , Timed (testS + 5)  imagePD1+                , Timed (testS + 12) imagePD1+                , Timed (testS + 21) imagePD0+                , Timed (testS + 32) imagePD2 ]+++-- Image events+-- Expected = 5  * 200000+--          + 7  * 400000+--          + 9  * 400000+--          + 11 * 200000+--          = 16 * 200000+--          + 16 * 400000+--          = 9600000+--+imageTimedPDsResult :: Word64+imageTimedPDsResult = 9600000++imagePPD0, imagePPD1, imagePPD2 :: PDImagePollster+imagePPD0 = PDImagePollster 200000+imagePPD1 = PDImagePollster 400000+imagePPD2 = PDImagePollster 100000++imagePTimedPDs :: [Timed PDImagePollster]+imagePTimedPDs = [ Timed testS        imagePPD0+                 , Timed (testS + 5)  imagePPD1+                 , Timed (testS + 12) imagePPD2+                 , Timed (testS + 21) imagePPD1+                 , Timed (testS + 32) imagePPD2 ]++imagePTimedPDsResult :: Map Word64 Word64+imagePTimedPDsResult = M.fromList [ (200000, 5)+                                  , (400000, 18)+                                  , (100000, 9)+                                  ]++-- SNAPSHOT ----------------------------------------------------------------------++snapshotNonDelete :: Gen PDSnapshot+snapshotNonDelete = (arbitrary :: Gen PDSnapshot) `suchThat` ((/= SnapshotDelete) . view snapshotVerb)++-- Raw payloads for volume points+snapshotPRs = [snapshotPR0, snapshotPR1, snapshotPR2 ]++snapshotPR0, snapshotPR1, snapshotPR2 :: Word64+snapshotPR0 = 1 + (2 `shift` 8) + (2 `shift` 16) + (200 `shift` 32)+snapshotPR1 = 1 + (2 `shift` 8) + (2 `shift` 16) + (300 `shift` 32)+snapshotPR2 = 3 + (3 `shift` 8) + (2 `shift` 16) + (100 `shift` 32)++-- Decoded payloads for snapshot points+snapshotPDs = [snapshotPD0, snapshotPD1, snapshotPD2 ]++snapshotPD0, snapshotPD1, snapshotPD2 :: PDSnapshot+snapshotPD0 = PDSnapshot SnapshotAvailable SnapshotUpdate End 200+snapshotPD1 = PDSnapshot SnapshotAvailable SnapshotUpdate End 300+snapshotPD2 = PDSnapshot SnapshotDeleting  SnapshotDelete End 100++snapshotTimedPDs :: [Timed PDSnapshot]+snapshotTimedPDs = [ Timed testS        snapshotPD0+                , Timed (testS + 5)  snapshotPD1+                , Timed (testS + 12) snapshotPD1+                , Timed (testS + 21) snapshotPD0+                , Timed (testS + 32) snapshotPD2 ]+++-- Snapshot events+-- Expected = 5  * 200+--          + 7  * 300+--          + 9  * 300+--          + 11 * 200+--          = 16 * 200+--          + 16 * 300+--          = 8000+--+snapshotTimedPDsResult :: Word64+snapshotTimedPDsResult = 8000++-- IP ----------------------------------------------------------------------++-- Raw payloads for volume points+ipPRs = [ipPR0, ipPR1, ipPR2 ]++ipPR0, ipPR1, ipPR2 :: Word64+ipPR0 = 1 + (2 `shift` 8) + (2 `shift` 16) + (1 `shift` 32)+ipPR1 = 2 + (2 `shift` 8) + (2 `shift` 16) + (1 `shift` 32)+ipPR2 = 0 + (3 `shift` 8) + (2 `shift` 16) + (1 `shift` 32)++-- Decoded payloads for ip points+ipPDs = [ipPD0, ipPD1, ipPD2 ]++ipPD0, ipPD1, ipPD2 :: PDIP+ipPD0 = PDIP IPActive IPUpdate End IPAlloc+ipPD1 = PDIP IPDown   IPUpdate End IPAlloc+ipPD2 = PDIP IPNone   IPDelete End IPAlloc