hnormalise-0.3.3.0: test/HNormalise/Torque/ParserSpec.hs
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedStrings #-}
module HNormalise.Torque.ParserSpec (main, spec) where
--------------------------------------------------------------------------------
import Data.Text (Text)
import qualified Data.Text.Read as TR
import Test.Hspec
import Test.Hspec.Attoparsec
--------------------------------------------------------------------------------
import HNormalise.Torque.Parser
import HNormalise.Torque.Internal
--------------------------------------------------------------------------------
main :: IO ()
main = hspec spec
--------------------------------------------------------------------------------
spec :: Spec
spec = do
describe "parseTorqueWalltime" $ do
it "parse walltime given as SS" $ do
let s = ("1234567" :: Text)
Right (s', _) = TR.decimal s
s ~> parseTorqueWalltime `shouldParse` TorqueWalltime { days = 0, hours = 0, minutes = 0, seconds = s' }
it "parse walltime given as MM:SS" $ do
let s = ("12:13") :: Text
s ~> parseTorqueWalltime `shouldParse` TorqueWalltime { days = 0, hours = 0, minutes = 12, seconds = 13}
it "parse walltime given as HH:MM:SS" $ do
let s = ("11:12:13") :: Text
s ~> parseTorqueWalltime `shouldParse` TorqueWalltime { days = 0, hours = 11, minutes = 12, seconds = 13 }
it "parse walltime given as MM:SS" $ do
let s = ("10:11:12:13") :: Text
s ~> parseTorqueWalltime `shouldParse` TorqueWalltime { days = 10, hours = 11, minutes = 12, seconds = 13 }
describe "parseTorqueMemory" $ do
it "parse memory value in bytes (lowercase)" $ do
let s = "123b" :: Text
s ~> parseTorqueMemory `shouldParse` 123
it "parse memory value in bytes (uppercase)" $ do
let s = "123B" :: Text
s ~> parseTorqueMemory `shouldParse` 123
it "parse memory value in bytes (lowercase)" $ do
let s = "123kb" :: Text
s ~> parseTorqueMemory `shouldParse` (123 * 1024)
it "parse memory value in bytes (mixed case)" $ do
let s = "123Kb" :: Text
s ~> parseTorqueMemory `shouldParse` (123 * 1024)
it "parse memory value in bytes (mixed case)" $ do
let s = "123kB" :: Text
s ~> parseTorqueMemory `shouldParse` (123 * 1024)
it "parse memory value in bytes (uppercase)" $ do
let s = "123KB" :: Text
s ~> parseTorqueMemory `shouldParse` (123 * 1024)
it "parse memory value in bytes (lowercase)" $ do
let s = "123mb" :: Text
s ~> parseTorqueMemory `shouldParse` (123 * 1024 * 1024)
it "parse memory value in bytes (mixed case)" $ do
let s = "123Mb" :: Text
s ~> parseTorqueMemory `shouldParse` (123 * 1024 * 1024)
it "parse memory value in bytes (mixed case)" $ do
let s = "123mB" :: Text
s ~> parseTorqueMemory `shouldParse` (123 * 1024 * 1024)
it "parse memory value in bytes (uppercase)" $ do
let s = "123MB" :: Text
s ~> parseTorqueMemory `shouldParse` (123 * 1024 * 1024)
it "parse memory value in bytes (lowercase)" $ do
let s = "123gb" :: Text
s ~> parseTorqueMemory `shouldParse` (123 * 1024 * 1024 * 1024)
it "parse memory value in bytes (mixed case)" $ do
let s = "123Gb" :: Text
s ~> parseTorqueMemory `shouldParse` (123 * 1024 * 1024 * 1024)
it "parse memory value in bytes (mixed case)" $ do
let s = "123gB" :: Text
s ~> parseTorqueMemory `shouldParse` (123 * 1024 * 1024 * 1024)
it "parse memory value in bytes (uppercase)" $ do
let s = "123GB" :: Text
s ~> parseTorqueMemory `shouldParse` (123 * 1024 * 1024 * 1024)
describe "parseTorqueJobName" $ do
it "parse regular torque job name" $ do
let s = "123456789.master.mycluster.mydomain;" :: Text
s ~> parseTorqueJobName `shouldParse` TorqueJobName { number = 123456789, array_id = Nothing, master = "master", cluster = "mycluster" }
it "parse array torque job name" $ do
let s = "123456[789].master.mycluster.mydomain;" :: Text
s ~> parseTorqueJobName `shouldParse` TorqueJobName { number = 123456, array_id = Just 789, master = "master", cluster = "mycluster" }
describe "parseTorqueResourceRequest" $ do
it "parse mandatory fields in expected order" $ do
let s = "Resource_List.neednodes=1:ppn=1 Resource_List.nodect=1 Resource_List.nodes=1:ppn=1 Resource_List.walltime=01:00:00" :: Text
s ~> parseTorqueResourceRequest `shouldParse` TorqueResourceRequest
{ mem = Nothing
, advres = Nothing
, naccesspolicy = Nothing
, ncpus = Nothing
, neednodes = Left TorqueJobShortNode { number = 1, ppn = Just 1 }
, nice = Nothing
, nodeCount = 1
, nodes = Left TorqueJobShortNode { number = 1, ppn = Just 1 }
, select = Nothing
, qos = Nothing
, pmem = Nothing
, vmem = Nothing
, pvmem = Nothing
, walltime = TorqueWalltime { days = 0, hours = 1, minutes = 0, seconds = 0 }
}
it "parse mandatory fields in reverse order" $ do
let s = "Resource_List.walltime=01:00:00 Resource_List.nodes=1:ppn=1 Resource_List.nodect=1 Resource_List.neednodes=1:ppn=1" :: Text
s ~> parseTorqueResourceRequest `shouldParse` TorqueResourceRequest
{ mem = Nothing
, advres = Nothing
, naccesspolicy = Nothing
, ncpus = Nothing
, neednodes = Left TorqueJobShortNode { number = 1, ppn = Just 1 }
, nice = Nothing
, nodeCount = 1
, nodes = Left TorqueJobShortNode { number = 1, ppn = Just 1 }
, select = Nothing
, qos = Nothing
, pmem = Nothing
, vmem = Nothing
, pvmem = Nothing
, walltime = TorqueWalltime { days = 0, hours = 1, minutes = 0, seconds = 0 }
}
it "parse mandatory fields plus mem fields" $ do
let s = "Resource_List.vmem=1mb Resource_List.walltime=01:00:00 Resource_List.pvmem=400kb Resource_List.pmem=200kB Resource_List.nodes=1:ppn=1 Resource_List.nodect=1 Resource_List.neednodes=1:ppn=1" :: Text
s ~> parseTorqueResourceRequest `shouldParse` TorqueResourceRequest
{ mem = Nothing
, advres = Nothing
, naccesspolicy = Nothing
, ncpus = Nothing
, neednodes = Left TorqueJobShortNode { number = 1, ppn = Just 1 }
, nice = Nothing
, nodeCount = 1
, nodes = Left TorqueJobShortNode { number = 1, ppn = Just 1 }
, select = Nothing
, qos = Nothing
, pmem = Just $ 200 * 1024
, vmem = Just $ 1 * 1024 * 1024
, pvmem = Just $ 400 * 1024
, walltime = TorqueWalltime { days = 0, hours = 1, minutes = 0, seconds = 0 }
}
it "parse mandatory fields plus reservation field" $ do
let s = "Resource_List.walltime=01:00:00 Resource_List.advres=myreservation.1 Resource_List.nodes=1:ppn=1 Resource_List.nodect=1 Resource_List.neednodes=1:ppn=1" :: Text
s ~> parseTorqueResourceRequest `shouldParse` TorqueResourceRequest
{ mem = Nothing
, advres = Just "myreservation.1"
, naccesspolicy = Nothing
, ncpus = Nothing
, neednodes = Left TorqueJobShortNode { number = 1, ppn = Just 1 }
, nice = Nothing
, nodeCount = 1
, nodes = Left TorqueJobShortNode { number = 1, ppn = Just 1 }
, select = Nothing
, qos = Nothing
, pmem = Nothing
, vmem = Nothing
, pvmem = Nothing
, walltime = TorqueWalltime { days = 0, hours = 1, minutes = 0, seconds = 0 }
}
it "parse mandatory fields plus qos field" $ do
let s = "Resource_List.walltime=01:00:00 Resource_List.nodes=1:ppn=1 Resource_List.qos=someqos Resource_List.nodect=1 Resource_List.neednodes=1:ppn=1" :: Text
s ~> parseTorqueResourceRequest `shouldParse` TorqueResourceRequest
{ mem = Nothing
, advres = Nothing
, naccesspolicy = Nothing
, ncpus = Nothing
, neednodes = Left TorqueJobShortNode { number = 1, ppn = Just 1 }
, nice = Nothing
, nodeCount = 1
, nodes = Left TorqueJobShortNode { number = 1, ppn = Just 1 }
, select = Nothing
, qos = Just "someqos"
, pmem = Nothing
, vmem = Nothing
, pvmem = Nothing
, walltime = TorqueWalltime { days = 0, hours = 1, minutes = 0, seconds = 0 }
}
describe "parseTorqueHostList" $ do
it "parse comma separated list of single cores" $ do
let s = "node1001.mycluster.mydomain/1,3,5,7" :: Text
s ~> parseTorqueHostList `shouldParse` [ TorqueExecHost
{ name = "node1001.mycluster.mydomain"
, cores = [1,3,5,7]
}]
it "parse comma separated list of core rangess" $ do
let s = "node1001.mycluster.mydomain/1-3,5-7" :: Text
s ~> parseTorqueHostList `shouldParse` [ TorqueExecHost
{ name = "node1001.mycluster.mydomain"
, cores = [1,2,3,5,6,7]
}]
it "parse comma separated list of single cores and core ranges" $ do
let s = "node1001.mycluster.mydomain/1,3,5-7,9,12-14" :: Text
s ~> parseTorqueHostList `shouldParse` [ TorqueExecHost
{ name = "node1001.mycluster.mydomain"
, cores = [1,3,5,6,7,9,12,13,14]
}]
it "parse multiple nodes with one comma separated list of single cores and one core range" $ do
let s = "node1001.mycluster.mydomain/1,3,5,7+node1002.mycluster.mydomain/4-6" :: Text
s ~> parseTorqueHostList `shouldParse` [
TorqueExecHost
{ name = "node1001.mycluster.mydomain"
, cores = [1,3,5,7]
},
TorqueExecHost
{ name = "node1002.mycluster.mydomain"
, cores = [4,5,6]
}
]
describe "parseTorqueExit" $ do
it "parse job exit log line" $ do
let s = "torque: 04/05/2017 13:06:53;E;45.master23.banette.gent.vsc;user=vsc40075 group=vsc40075 jobname=STDIN queue=short ctime=1491390300 qtime=1491390300 etime=1491390300 start=1491390307 owner=vsc40075@gligar01.gligar.gent.vsc exec_host=node2801.banette.gent.vsc/0-1+node2803.banette.gent.vsc/0-1 Resource_List.nodes=node2801.banette.gent.vsc:ppn=2+node2803.banette.gent.vsc:ppn=2 Resource_List.vmem=1gb Resource_List.nodect=2 Resource_List.neednodes=node2801.banette.gent.vsc:ppn=2+node2803.banette.gent.vsc:ppn=2 Resource_List.nice=0 Resource_List.walltime=01:00:00 session=15273 total_execution_slots=4 unique_node_count=2 end=1491390413 Exit_status=0 resources_used.cput=0 resources_used.energy_used=0 resources_used.mem=55048kb resources_used.vmem=92488kb resources_used.walltime=00:01:44" :: Text
s ~> parseTorqueExit `shouldParse` ("torque", TorqueJobExit
{ name = TorqueJobName { number = 45, array_id = Nothing, master = "master23", cluster = "banette" }
, user = "vsc40075"
, group = "vsc40075"
, jobname = "STDIN"
, queue = "short"
, startCount = Nothing
, owner = "vsc40075@gligar01.gligar.gent.vsc"
, session = 15273
, times = TorqueJobTime
{ ctime = 1491390300
, qtime = 1491390300
, etime = 1491390300
, startTime = 1491390307
, endTime = 1491390413
}
, execHost =
[ TorqueExecHost
{ name = "exec_host=node2801.banette.gent.vsc"
, cores = [0,1]
}
, TorqueExecHost
{ name = "node2803.banette.gent.vsc"
, cores = [0,1]
}
]
, resourceRequest = TorqueResourceRequest
{ mem = Nothing
, advres = Nothing
, naccesspolicy = Nothing
, ncpus = Nothing
, neednodes = Right
[ TorqueJobFQNode
{ name = "node2801.banette.gent.vsc"
, ppn = 2
}
, TorqueJobFQNode
{ name = "node2803.banette.gent.vsc"
, ppn = 2
}
]
, nice = Just 0
, nodeCount = 2
, nodes = Right
[ TorqueJobFQNode
{ name = "node2801.banette.gent.vsc"
, ppn = 2
}
, TorqueJobFQNode
{ name = "node2803.banette.gent.vsc"
, ppn = 2
}
]
, select = Nothing
, qos = Nothing
, vmem = Just $ 1 * 1024 * 1024 * 1024
, pmem = Nothing
, pvmem = Nothing
, walltime = TorqueWalltime { days = 0, hours = 1, minutes = 0, seconds = 0}
}
, resourceUsage = TorqueResourceUsage
{ cputime = 0
, energy = 0
, mem = 55048 * 1024
, vmem = 92488 * 1024
, walltime = TorqueWalltime { days = 0, hours = 0, minutes = 1, seconds = 44 }
}
, totalExecutionSlots = 4
, uniqueNodeCount = 2
, exitStatus = 0
})