content: {-# LANGUAGE TemplateHaskell #-}
  {-# OPTIONS_GHC -fno-warn-orphans #-}
  
  {-| Unittests for the types representing DRBD status -}
  
  {-
  
  Copyright (C) 2012 Google Inc.
  All rights reserved.
  
  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are
  met:
  
  1. Redistributions of source code must retain the above copyright notice,
  this list of conditions and the following disclaimer.
  
  2. Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.
  
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  -}
  
  module Test.Ganeti.Storage.Drbd.Types (testBlock_Drbd_Types) where
  
  import Test.QuickCheck
  
  import Test.Ganeti.TestHelper
  import Test.Ganeti.TestCommon
  
  import Text.JSON
  import Text.Printf
  
  import Ganeti.JSON
  
  import Ganeti.Storage.Drbd.Types
  
  {-# ANN module "HLint: ignore Use camelCase" #-}
  {-# ANN module "HLint: ignore Use string literal" #-}
  
  -- * Arbitrary instances
  
  $(genArbitrary ''ConnState)
  $(genArbitrary ''Role)
  $(genArbitrary ''DiskState)
  $(genArbitrary ''SizeUnit)
  $(genArbitrary ''TimeUnit)
  
  -- | Natural numbers generator.
  natural :: Gen Int
  natural = choose (0, maxBound :: Int)
  
  -- | Generator of percentages.
  percent :: Gen Double
  percent = choose (0 :: Double, 100 :: Double)
  
  -- | Generator of write order flags.
  wOrderFlag :: Gen Char
  wOrderFlag = elements ['b', 'f', 'd', 'n']
  
  -- | Property for testing the JSON serialization of a DeviceInfo.
  prop_DeviceInfo :: Property
  prop_DeviceInfo = property $ do
    minor <- natural
    state <- arbitrary
    locRole <- arbitrary
    remRole <- arbitrary
    locState <- arbitrary
    remState <- arbitrary
    alg <- choose ('A','C')
    ns <- natural
    nr <- natural
    dw <- natural
    dr <- natural
    al <- natural
    bm <- natural
    lc <- natural
    pe <- natural
    ua <- natural
    ap <- natural
    ep <- genMaybe natural
    wo <- genMaybe wOrderFlag
    oos <- genMaybe natural
    inst <- genMaybe arbitrary
    let obtained =
            showJSON $
              DeviceInfo minor state (LocalRemote locRole remRole)
                (LocalRemote locState remState) alg "r----" perfInd
                Nothing
                Nothing
                Nothing
                inst
        perfInd =
          PerfIndicators ns nr dw dr al bm lc pe ua ap ep wo oos
        expected =
          makeObj
            [ ("minor", showJSON minor)
            , ("connectionState", showJSON state)
            , ("localRole", showJSON locRole)
            , ("remoteRole", showJSON remRole)
            , ("localState", showJSON locState)
            , ("remoteState", showJSON remState)
            , ("replicationProtocol", showJSON alg)
            , ("ioFlags", showJSON "r----")
            , ("perfIndicators", showJSON perfInd)
            , ("instance", maybe JSNull showJSON inst)
            ]
    return $ obtained ==? expected
  
  -- | Property for testing the JSON serialization of a PerfIndicators.
  prop_PerfIndicators :: Property
  prop_PerfIndicators = property $ do
    ns <- natural
    nr <- natural
    dw <- natural
    dr <- natural
    al <- natural
    bm <- natural
    lc <- natural
    pe <- natural
    ua <- natural
    ap <- natural
    ep <- genMaybe natural
    wo <- genMaybe wOrderFlag
    oos <- genMaybe natural
    let expected =
          showJSON $
            PerfIndicators ns nr dw dr al bm lc pe ua ap ep wo oos
        obtained =
          optFieldsToObj
            [ Just ("networkSend", showJSON ns)
            , Just ("networkReceive", showJSON nr)
            , Just ("diskWrite", showJSON dw)
            , Just ("diskRead", showJSON dr)
            , Just ("activityLog", showJSON al)
            , Just ("bitMap", showJSON bm)
            , Just ("localCount", showJSON lc)
            , Just ("pending", showJSON pe)
            , Just ("unacknowledged", showJSON ua)
            , Just ("applicationPending", showJSON ap)
            , optionalJSField "epochs" ep
            , optionalJSField "writeOrder" wo
            , optionalJSField "outOfSync" oos
            ]
    return $ obtained ==? expected
  
  -- | Function for testing the JSON serialization of a SyncStatus.
  prop_SyncStatus :: Property
  prop_SyncStatus = property $ do
    perc <- percent
    numer <- natural
    denom <- natural
    sizeU1 <- arbitrary
    h <- choose (0, 23)
    m <- choose (0, 59)
    s <- choose (0, 59)
    sp <- natural
    wa <- genMaybe natural
    sizeU2 <- arbitrary
    timeU <- arbitrary
    let obtained = showJSON $
          SyncStatus perc numer denom sizeU1 (Time h m s) sp wa sizeU2 timeU
        expected = optFieldsToObj
          [ Just ("percentage", showJSON perc)
          , Just ("progress", showJSON $ show numer ++ "/" ++ show denom)
          , Just ("progressUnit", showJSON sizeU1)
          , Just ("timeToFinish", showJSON
              (printf "%02d:%02d:%02d" h m s :: String))
          , Just ("speed", showJSON sp)
          , optionalJSField "want" wa
          , Just ("speedUnit", showJSON $ show sizeU2 ++ "/" ++ show timeU)
          ]
    return $ obtained ==? expected
  
  testSuite "Block/Drbd/Types"
            [ 'prop_DeviceInfo
            , 'prop_PerfIndicators
            , 'prop_SyncStatus
            ]
  