Statistics
| Branch: | Tag: | Revision:

root / htest / Test / Ganeti / HTools / CLI.hs @ 2e0bb81d

History | View | Annotate | Download (4.4 kB)

1
{-# LANGUAGE TemplateHaskell #-}
2
{-# OPTIONS_GHC -fno-warn-orphans #-}
3

    
4
{-| Unittests for ganeti-htools.
5

    
6
-}
7

    
8
{-
9

    
10
Copyright (C) 2009, 2010, 2011, 2012 Google Inc.
11

    
12
This program is free software; you can redistribute it and/or modify
13
it under the terms of the GNU General Public License as published by
14
the Free Software Foundation; either version 2 of the License, or
15
(at your option) any later version.
16

    
17
This program is distributed in the hope that it will be useful, but
18
WITHOUT ANY WARRANTY; without even the implied warranty of
19
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20
General Public License for more details.
21

    
22
You should have received a copy of the GNU General Public License
23
along with this program; if not, write to the Free Software
24
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25
02110-1301, USA.
26

    
27
-}
28

    
29
module Test.Ganeti.HTools.CLI (testHTools_CLI) where
30

    
31
import Test.QuickCheck
32

    
33
import Control.Monad
34
import Data.List
35
import Text.Printf (printf)
36
import qualified System.Console.GetOpt as GetOpt
37

    
38
import Test.Ganeti.TestHelper
39
import Test.Ganeti.TestCommon
40

    
41
import qualified Ganeti.HTools.CLI as CLI
42
import qualified Ganeti.HTools.Program as Program
43
import qualified Ganeti.HTools.Types as Types
44

    
45
-- | Test correct parsing.
46
prop_parseISpec :: String -> Int -> Int -> Int -> Property
47
prop_parseISpec descr dsk mem cpu =
48
  let str = printf "%d,%d,%d" dsk mem cpu::String
49
  in CLI.parseISpecString descr str ==? Types.Ok (Types.RSpec cpu mem dsk)
50

    
51
-- | Test parsing failure due to wrong section count.
52
prop_parseISpecFail :: String -> Property
53
prop_parseISpecFail descr =
54
  forAll (choose (0,100) `suchThat` ((/=) 3)) $ \nelems ->
55
  forAll (replicateM nelems arbitrary) $ \values ->
56
  let str = intercalate "," $ map show (values::[Int])
57
  in case CLI.parseISpecString descr str of
58
       Types.Ok v -> failTest $ "Expected failure, got " ++ show v
59
       _ -> passTest
60

    
61
-- | Test parseYesNo.
62
prop_parseYesNo :: Bool -> Bool -> [Char] -> Property
63
prop_parseYesNo def testval val =
64
  forAll (elements [val, "yes", "no"]) $ \actual_val ->
65
  if testval
66
    then CLI.parseYesNo def Nothing ==? Types.Ok def
67
    else let result = CLI.parseYesNo def (Just actual_val)
68
         in if actual_val `elem` ["yes", "no"]
69
              then result ==? Types.Ok (actual_val == "yes")
70
              else property $ Types.isBad result
71

    
72
-- | Helper to check for correct parsing of string arg.
73
checkStringArg :: [Char]
74
               -> (GetOpt.OptDescr (CLI.Options -> Types.Result CLI.Options),
75
                   CLI.Options -> Maybe [Char])
76
               -> Property
77
checkStringArg val (opt, fn) =
78
  let GetOpt.Option _ longs _ _ = opt
79
  in case longs of
80
       [] -> failTest "no long options?"
81
       cmdarg:_ ->
82
         case CLI.parseOptsInner ["--" ++ cmdarg ++ "=" ++ val] "prog" [opt] of
83
           Left e -> failTest $ "Failed to parse option: " ++ show e
84
           Right (options, _) -> fn options ==? Just val
85

    
86
-- | Test a few string arguments.
87
prop_StringArg :: [Char] -> Property
88
prop_StringArg argument =
89
  let args = [ (CLI.oDataFile,      CLI.optDataFile)
90
             , (CLI.oDynuFile,      CLI.optDynuFile)
91
             , (CLI.oSaveCluster,   CLI.optSaveCluster)
92
             , (CLI.oReplay,        CLI.optReplay)
93
             , (CLI.oPrintCommands, CLI.optShowCmds)
94
             , (CLI.oLuxiSocket,    CLI.optLuxi)
95
             ]
96
  in conjoin $ map (checkStringArg argument) args
97

    
98
-- | Helper to test that a given option is accepted OK with quick exit.
99
checkEarlyExit :: String -> [CLI.OptType] -> String -> Property
100
checkEarlyExit name options param =
101
  case CLI.parseOptsInner [param] name options of
102
    Left (code, _) ->
103
      printTestCase ("Program " ++ name ++
104
                     " returns invalid code " ++ show code ++
105
                     " for option " ++ param) (code == 0)
106
    _ -> failTest $ "Program " ++ name ++ " doesn't consider option " ++
107
         param ++ " as early exit one"
108

    
109
-- | Test that all binaries support some common options. There is
110
-- nothing actually random about this test...
111
prop_stdopts :: Property
112
prop_stdopts =
113
  let params = ["-h", "--help", "-V", "--version"]
114
      opts = map (\(name, (_, o)) -> (name, o)) Program.personalities
115
      -- apply checkEarlyExit across the cartesian product of params and opts
116
  in conjoin [checkEarlyExit n o p | p <- params, (n, o) <- opts]
117

    
118
testSuite "HTools/CLI"
119
          [ 'prop_parseISpec
120
          , 'prop_parseISpecFail
121
          , 'prop_parseYesNo
122
          , 'prop_StringArg
123
          , 'prop_stdopts
124
          ]