prop_JobStatus :: Property
prop_JobStatus =
  forAll genJobId $ \jid ->
  forAll genQueuedOpCode $ \op ->
  let job1 = QueuedJob jid [op] justNoTs justNoTs justNoTs Nothing Nothing
      st1 = calcJobStatus job1
      op_succ = op { qoStatus = OP_STATUS_SUCCESS }
      op_err  = op { qoStatus = OP_STATUS_ERROR }
      op_cnl  = op { qoStatus = OP_STATUS_CANCELING }
      op_cnd  = op { qoStatus = OP_STATUS_CANCELED }
      -- computes status for a job with an added opcode before
      st_pre_op pop = calcJobStatus (job1 { qjOps = pop:qjOps job1 })
      -- computes status for a job with an added opcode after
      st_post_op pop = calcJobStatus (job1 { qjOps = qjOps job1 ++ [pop] })
  in conjoin
     [ counterexample "pre-success doesn't change status"
       (st_pre_op op_succ ==? st1)
     , counterexample "post-success doesn't change status"
       (st_post_op op_succ ==? st1)
     , counterexample "pre-error is error"
       (st_pre_op op_err ==? JOB_STATUS_ERROR)
     , counterexample "pre-canceling is canceling"
       (st_pre_op op_cnl ==? JOB_STATUS_CANCELING)
     , counterexample "pre-canceled is canceled"
       (st_pre_op op_cnd ==? JOB_STATUS_CANCELED)
     ]
prop_JobStatus :: Property
prop_JobStatus =
  forAll genJobId $ \jid ->
  forAll genQueuedOpCode $ \op ->
  let job1 = QueuedJob jid [op] justNoTs justNoTs justNoTs Nothing Nothing
      st1 = calcJobStatus job1
      op_succ = op { qoStatus = OP_STATUS_SUCCESS }
      op_err  = op { qoStatus = OP_STATUS_ERROR }
      op_cnl  = op { qoStatus = OP_STATUS_CANCELING }
      op_cnd  = op { qoStatus = OP_STATUS_CANCELED }
      -- computes status for a job with an added opcode before
      st_pre_op pop = calcJobStatus (job1 { qjOps = pop:qjOps job1 })
      -- computes status for a job with an added opcode after
      st_post_op pop = calcJobStatus (job1 { qjOps = qjOps job1 ++ [pop] })
  in conjoin
     [ counterexample "pre-success doesn't change status"
       (st_pre_op op_succ ==? st1)
     , counterexample "post-success doesn't change status"
       (st_post_op op_succ ==? st1)
     , counterexample "pre-error is error"
       (st_pre_op op_err ==? JOB_STATUS_ERROR)
     , counterexample "pre-canceling is canceling"
       (st_pre_op op_cnl ==? JOB_STATUS_CANCELING)
     , counterexample "pre-canceled is canceled"
       (st_pre_op op_cnd ==? JOB_STATUS_CANCELED)
     ]
prop_JobStatus =
  forAll genJobId $ \jid ->
  forAll genQueuedOpCode $ \op ->
  let job1 = QueuedJob jid [op] justNoTs justNoTs justNoTs Nothing Nothing
      st1 = calcJobStatus job1
      op_succ = op { qoStatus = OP_STATUS_SUCCESS }
      op_err  = op { qoStatus = OP_STATUS_ERROR }
      op_cnl  = op { qoStatus = OP_STATUS_CANCELING }
      op_cnd  = op { qoStatus = OP_STATUS_CANCELED }
      -- computes status for a job with an added opcode before
      st_pre_op pop = calcJobStatus (job1 { qjOps = pop:qjOps job1 })
      -- computes status for a job with an added opcode after
      st_post_op pop = calcJobStatus (job1 { qjOps = qjOps job1 ++ [pop] })
  in conjoin
     [ counterexample "pre-success doesn't change status"
       (st_pre_op op_succ ==? st1)
     , counterexample "post-success doesn't change status"
       (st_post_op op_succ ==? st1)
     , counterexample "pre-error is error"
       (st_pre_op op_err ==? JOB_STATUS_ERROR)
     , counterexample "pre-canceling is canceling"
       (st_pre_op op_cnl ==? JOB_STATUS_CANCELING)
     , counterexample "pre-canceled is canceled"
       (st_pre_op op_cnd ==? JOB_STATUS_CANCELED)
     ]