root / test / hs / Test / Ganeti / Common.hs @ a59d5fa1
History | View | Annotate | Download (6.8 kB)
1 | 51000365 | Iustin Pop | {-# LANGUAGE TemplateHaskell #-} |
---|---|---|---|
2 | 51000365 | Iustin Pop | {-# OPTIONS_GHC -fno-warn-orphans #-} |
3 | 51000365 | Iustin Pop | |
4 | 51000365 | Iustin Pop | {-| Unittests for the 'Ganeti.Common' module. |
5 | 51000365 | Iustin Pop | |
6 | 51000365 | Iustin Pop | -} |
7 | 51000365 | Iustin Pop | |
8 | 51000365 | Iustin Pop | {- |
9 | 51000365 | Iustin Pop | |
10 | 9fb621af | Yiannis Tsiouris | Copyright (C) 2009, 2010, 2011, 2012, 2013 Google Inc. |
11 | 51000365 | Iustin Pop | |
12 | 51000365 | Iustin Pop | This program is free software; you can redistribute it and/or modify |
13 | 51000365 | Iustin Pop | it under the terms of the GNU General Public License as published by |
14 | 51000365 | Iustin Pop | the Free Software Foundation; either version 2 of the License, or |
15 | 51000365 | Iustin Pop | (at your option) any later version. |
16 | 51000365 | Iustin Pop | |
17 | 51000365 | Iustin Pop | This program is distributed in the hope that it will be useful, but |
18 | 51000365 | Iustin Pop | WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | 51000365 | Iustin Pop | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
20 | 51000365 | Iustin Pop | General Public License for more details. |
21 | 51000365 | Iustin Pop | |
22 | 51000365 | Iustin Pop | You should have received a copy of the GNU General Public License |
23 | 51000365 | Iustin Pop | along with this program; if not, write to the Free Software |
24 | 51000365 | Iustin Pop | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
25 | 51000365 | Iustin Pop | 02110-1301, USA. |
26 | 51000365 | Iustin Pop | |
27 | 51000365 | Iustin Pop | -} |
28 | 51000365 | Iustin Pop | |
29 | 51000365 | Iustin Pop | module Test.Ganeti.Common |
30 | 51000365 | Iustin Pop | ( testCommon |
31 | 51000365 | Iustin Pop | , checkOpt |
32 | 51000365 | Iustin Pop | , passFailOpt |
33 | 51000365 | Iustin Pop | , checkEarlyExit |
34 | 51000365 | Iustin Pop | ) where |
35 | 51000365 | Iustin Pop | |
36 | 51000365 | Iustin Pop | import Test.QuickCheck hiding (Result) |
37 | 51000365 | Iustin Pop | import Test.HUnit |
38 | 51000365 | Iustin Pop | |
39 | 51000365 | Iustin Pop | import qualified System.Console.GetOpt as GetOpt |
40 | 51000365 | Iustin Pop | import System.Exit |
41 | 51000365 | Iustin Pop | |
42 | 51000365 | Iustin Pop | import Test.Ganeti.TestHelper |
43 | 51000365 | Iustin Pop | import Test.Ganeti.TestCommon |
44 | 51000365 | Iustin Pop | |
45 | 51000365 | Iustin Pop | import Ganeti.BasicTypes |
46 | 51000365 | Iustin Pop | import Ganeti.Common |
47 | 9fb621af | Yiannis Tsiouris | import Ganeti.HTools.Program.Main (personalities) |
48 | 9fb621af | Yiannis Tsiouris | |
49 | 9fb621af | Yiannis Tsiouris | {-# ANN module "HLint: ignore Use camelCase" #-} |
50 | 51000365 | Iustin Pop | |
51 | 51000365 | Iustin Pop | -- | Helper to check for correct parsing of an option. |
52 | 51000365 | Iustin Pop | checkOpt :: (StandardOptions b) => |
53 | 51000365 | Iustin Pop | (a -> Maybe String) -- ^ Converts the value into a cmdline form |
54 | 51000365 | Iustin Pop | -> b -- ^ The default options |
55 | 51000365 | Iustin Pop | -> (String -> c) -- ^ Fail test function |
56 | 51000365 | Iustin Pop | -> (String -> d -> d -> c) -- ^ Check for equality function |
57 | 51000365 | Iustin Pop | -> (a -> d) -- ^ Transforms the value to a compare val |
58 | 51000365 | Iustin Pop | -> (a, GenericOptType b, b -> d) -- ^ Triple of value, the |
59 | 51000365 | Iustin Pop | -- option, function to |
60 | 51000365 | Iustin Pop | -- extract the set value |
61 | 51000365 | Iustin Pop | -- from the options |
62 | 51000365 | Iustin Pop | -> c |
63 | 51000365 | Iustin Pop | checkOpt repr defaults failfn eqcheck valfn |
64 | ce207617 | Iustin Pop | (val, opt@(GetOpt.Option _ longs _ _, _), fn) = |
65 | 51000365 | Iustin Pop | case longs of |
66 | 51000365 | Iustin Pop | [] -> failfn "no long options?" |
67 | 51000365 | Iustin Pop | cmdarg:_ -> |
68 | 51000365 | Iustin Pop | case parseOptsInner defaults |
69 | 51000365 | Iustin Pop | ["--" ++ cmdarg ++ maybe "" ("=" ++) (repr val)] |
70 | 22278fa7 | Iustin Pop | "prog" [opt] [] of |
71 | 51000365 | Iustin Pop | Left e -> failfn $ "Failed to parse option '" ++ cmdarg ++ ": " ++ |
72 | 51000365 | Iustin Pop | show e |
73 | 51000365 | Iustin Pop | Right (options, _) -> eqcheck ("Wrong value in option " ++ |
74 | 51000365 | Iustin Pop | cmdarg ++ "?") (valfn val) (fn options) |
75 | 51000365 | Iustin Pop | |
76 | 51000365 | Iustin Pop | -- | Helper to check for correct and incorrect parsing of an option. |
77 | 51000365 | Iustin Pop | passFailOpt :: (StandardOptions b) => |
78 | 51000365 | Iustin Pop | b -- ^ The default options |
79 | 51000365 | Iustin Pop | -> (String -> c) -- ^ Fail test function |
80 | 51000365 | Iustin Pop | -> c -- ^ Pass function |
81 | 51000365 | Iustin Pop | -> (GenericOptType b, String, String) |
82 | 51000365 | Iustin Pop | -- ^ The list of enabled options, fail value and pass value |
83 | 51000365 | Iustin Pop | -> c |
84 | 51000365 | Iustin Pop | passFailOpt defaults failfn passfn |
85 | ce207617 | Iustin Pop | (opt@(GetOpt.Option _ longs _ _, _), bad, good) = |
86 | 72747d91 | Iustin Pop | let first_opt = case longs of |
87 | 72747d91 | Iustin Pop | [] -> error "no long options?" |
88 | 72747d91 | Iustin Pop | x:_ -> x |
89 | 72747d91 | Iustin Pop | prefix = "--" ++ first_opt ++ "=" |
90 | 51000365 | Iustin Pop | good_cmd = prefix ++ good |
91 | 51000365 | Iustin Pop | bad_cmd = prefix ++ bad in |
92 | 22278fa7 | Iustin Pop | case (parseOptsInner defaults [bad_cmd] "prog" [opt] [], |
93 | 22278fa7 | Iustin Pop | parseOptsInner defaults [good_cmd] "prog" [opt] []) of |
94 | 51000365 | Iustin Pop | (Left _, Right _) -> passfn |
95 | 51000365 | Iustin Pop | (Right _, Right _) -> failfn $ "Command line '" ++ bad_cmd ++ |
96 | 51000365 | Iustin Pop | "' succeeded when it shouldn't" |
97 | 51000365 | Iustin Pop | (Left _, Left _) -> failfn $ "Command line '" ++ good_cmd ++ |
98 | 51000365 | Iustin Pop | "' failed when it shouldn't" |
99 | 51000365 | Iustin Pop | (Right _, Left _) -> |
100 | 51000365 | Iustin Pop | failfn $ "Command line '" ++ bad_cmd ++ |
101 | 51000365 | Iustin Pop | "' succeeded when it shouldn't, while command line '" ++ |
102 | 51000365 | Iustin Pop | good_cmd ++ "' failed when it shouldn't" |
103 | 51000365 | Iustin Pop | |
104 | 51000365 | Iustin Pop | -- | Helper to test that a given option is accepted OK with quick exit. |
105 | 51000365 | Iustin Pop | checkEarlyExit :: (StandardOptions a) => |
106 | 22278fa7 | Iustin Pop | a -> String -> [GenericOptType a] -> [ArgCompletion] |
107 | 22278fa7 | Iustin Pop | -> Assertion |
108 | 22278fa7 | Iustin Pop | checkEarlyExit defaults name options arguments = |
109 | 51000365 | Iustin Pop | mapM_ (\param -> |
110 | 22278fa7 | Iustin Pop | case parseOptsInner defaults [param] name options arguments of |
111 | 51000365 | Iustin Pop | Left (code, _) -> |
112 | 51000365 | Iustin Pop | assertEqual ("Program " ++ name ++ |
113 | 51000365 | Iustin Pop | " returns invalid code " ++ show code ++ |
114 | 51000365 | Iustin Pop | " for option " ++ param) ExitSuccess code |
115 | 51000365 | Iustin Pop | _ -> assertFailure $ "Program " ++ name ++ |
116 | 51000365 | Iustin Pop | " doesn't consider option " ++ |
117 | 51000365 | Iustin Pop | param ++ " as early exit one" |
118 | 51000365 | Iustin Pop | ) ["-h", "--help", "-V", "--version"] |
119 | 51000365 | Iustin Pop | |
120 | 51000365 | Iustin Pop | -- | Test parseYesNo. |
121 | 51000365 | Iustin Pop | prop_parse_yes_no :: Bool -> Bool -> String -> Property |
122 | 51000365 | Iustin Pop | prop_parse_yes_no def testval val = |
123 | 51000365 | Iustin Pop | forAll (elements [val, "yes", "no"]) $ \actual_val -> |
124 | 51000365 | Iustin Pop | if testval |
125 | 51000365 | Iustin Pop | then parseYesNo def Nothing ==? Ok def |
126 | 51000365 | Iustin Pop | else let result = parseYesNo def (Just actual_val) |
127 | 51000365 | Iustin Pop | in if actual_val `elem` ["yes", "no"] |
128 | 51000365 | Iustin Pop | then result ==? Ok (actual_val == "yes") |
129 | 51000365 | Iustin Pop | else property $ isBad result |
130 | 51000365 | Iustin Pop | |
131 | 9fb621af | Yiannis Tsiouris | -- | Check that formatCmdUsage works similar to Python _FormatUsage. |
132 | 9fb621af | Yiannis Tsiouris | case_formatCommands :: Assertion |
133 | 9fb621af | Yiannis Tsiouris | case_formatCommands = |
134 | 9fb621af | Yiannis Tsiouris | assertEqual "proper wrap for HTools Main" |
135 | 9fb621af | Yiannis Tsiouris | resCmdTest (formatCommands personalities) |
136 | 9fb621af | Yiannis Tsiouris | where resCmdTest :: [String] |
137 | 9fb621af | Yiannis Tsiouris | resCmdTest = |
138 | 9fb621af | Yiannis Tsiouris | [ " hail - Ganeti IAllocator plugin that implements the instance\ |
139 | 9fb621af | Yiannis Tsiouris | \ placement and" |
140 | 9fb621af | Yiannis Tsiouris | , " movement using the same algorithm as hbal(1)" |
141 | b6d9bec8 | Dato Simó | , " harep - auto-repair tool that detects certain kind of problems\ |
142 | b6d9bec8 | Dato Simó | \ with instances" |
143 | b6d9bec8 | Dato Simó | , " and applies the allowed set of solutions" |
144 | 9fb621af | Yiannis Tsiouris | , " hbal - cluster balancer that looks at the current state of\ |
145 | 9fb621af | Yiannis Tsiouris | \ the cluster and" |
146 | 9fb621af | Yiannis Tsiouris | , " computes a series of steps designed to bring the\ |
147 | 9fb621af | Yiannis Tsiouris | \ cluster into a" |
148 | 9fb621af | Yiannis Tsiouris | , " better state" |
149 | 9fb621af | Yiannis Tsiouris | , " hcheck - cluster checker; prints information about cluster's\ |
150 | 9fb621af | Yiannis Tsiouris | \ health and checks" |
151 | 9fb621af | Yiannis Tsiouris | , " whether a rebalance done using hbal would help" |
152 | 9fb621af | Yiannis Tsiouris | , " hinfo - cluster information printer; it prints information\ |
153 | 9fb621af | Yiannis Tsiouris | \ about the current" |
154 | 9fb621af | Yiannis Tsiouris | , " cluster state and its residing nodes/instances" |
155 | 9fb621af | Yiannis Tsiouris | , " hroller - cluster rolling maintenance helper; it helps\ |
156 | 9fb621af | Yiannis Tsiouris | \ scheduling node reboots" |
157 | 9fb621af | Yiannis Tsiouris | , " in a manner that doesn't conflict with the instances'\ |
158 | 9fb621af | Yiannis Tsiouris | \ topology" |
159 | 9fb621af | Yiannis Tsiouris | , " hscan - tool for scanning clusters via RAPI and saving their\ |
160 | 9fb621af | Yiannis Tsiouris | \ data in the" |
161 | 9fb621af | Yiannis Tsiouris | , " input format used by hbal(1) and hspace(1)" |
162 | 9fb621af | Yiannis Tsiouris | , " hspace - computes how many additional instances can be fit on a\ |
163 | 9fb621af | Yiannis Tsiouris | \ cluster, while" |
164 | 9fb621af | Yiannis Tsiouris | , " maintaining N+1 status." |
165 | 9fb621af | Yiannis Tsiouris | ] |
166 | 51000365 | Iustin Pop | |
167 | 51000365 | Iustin Pop | testSuite "Common" |
168 | 51000365 | Iustin Pop | [ 'prop_parse_yes_no |
169 | 9fb621af | Yiannis Tsiouris | , 'case_formatCommands |
170 | 51000365 | Iustin Pop | ] |