diff --git a/ceilometer-common.cabal b/ceilometer-common.cabal
--- a/ceilometer-common.cabal
+++ b/ceilometer-common.cabal
@@ -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
diff --git a/lib/Ceilometer/Client.hs b/lib/Ceilometer/Client.hs
--- a/lib/Ceilometer/Client.hs
+++ b/lib/Ceilometer/Client.hs
@@ -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
 
 
diff --git a/tests/Fold.hs b/tests/Fold.hs
new file mode 100644
--- /dev/null
+++ b/tests/Fold.hs
@@ -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)
diff --git a/tests/Prisms.hs b/tests/Prisms.hs
new file mode 100644
--- /dev/null
+++ b/tests/Prisms.hs
@@ -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
diff --git a/tests/SampleData.hs b/tests/SampleData.hs
new file mode 100644
--- /dev/null
+++ b/tests/SampleData.hs
@@ -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
