Coverage for manila/tests/share/drivers/vastdata/test_driver_util.py: 98%

130 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2026-02-18 22:19 +0000

1# Copyright 2024 VAST Data Inc. 

2# All Rights Reserved. 

3# 

4# Licensed under the Apache License, Version 2.0 (the "License"); you may 

5# not use this file except in compliance with the License. You may obtain 

6# a copy of the License at 

7# 

8# http://www.apache.org/licenses/LICENSE-2.0 

9# 

10# Unless required by applicable law or agreed to in writing, software 

11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

13# License for the specific language governing permissions and limitations 

14# under the License. 

15import json 

16import pickle 

17from unittest import mock 

18 

19import ddt 

20 

21from manila.share.drivers.vastdata import driver_util 

22from manila import test 

23 

24 

25driver_util.CONF.debug = True 

26 

27 

28@ddt.ddt 

29class TestBunch(test.TestCase): 

30 def setUp(self): 

31 super(TestBunch, self).setUp() 

32 self.bunch = driver_util.Bunch(a=1, b=2) 

33 

34 def test_bunch_getattr(self): 

35 self.assertEqual(self.bunch.a, 1) 

36 

37 def test_bunch_setattr(self): 

38 self.bunch.c = 3 

39 self.assertEqual(self.bunch.c, 3) 

40 

41 def test_bunch_delattr(self): 

42 del self.bunch.a 

43 self.assertRaises(AttributeError, lambda: self.bunch.a) 

44 

45 def test_bunch_to_dict(self): 

46 self.assertEqual(self.bunch.to_dict(), {"a": 1, "b": 2}) 

47 

48 def test_bunch_from_dict(self): 

49 self.assertEqual( 

50 driver_util.Bunch.from_dict({"a": 1, "b": 2}), self.bunch 

51 ) 

52 

53 def test_bunch_to_json(self): 

54 self.assertEqual(self.bunch.to_json(), json.dumps({"a": 1, "b": 2})) 

55 

56 def test_bunch_without(self): 

57 self.assertEqual(self.bunch.without("a"), driver_util.Bunch(b=2)) 

58 

59 def test_bunch_but_with(self): 

60 self.assertEqual( 

61 self.bunch.but_with(c=3), driver_util.Bunch(a=1, b=2, c=3) 

62 ) 

63 

64 def test_bunch_delattr_missing(self): 

65 self.assertRaises( 

66 AttributeError, 

67 lambda: self.bunch.__delattr__("non_existing_attribute") 

68 ) 

69 

70 def test_bunch_from_json(self): 

71 json_bunch = json.dumps({"a": 1, "b": 2}) 

72 self.assertEqual(driver_util.Bunch.from_json(json_bunch), self.bunch) 

73 

74 def test_bunch_render(self): 

75 self.assertEqual(self.bunch.render(), "a=1, b=2") 

76 

77 def test_bunch_pickle(self): 

78 pickled_bunch = pickle.dumps(self.bunch) 

79 unpickled_bunch = pickle.loads(pickled_bunch) 

80 self.assertEqual(self.bunch, unpickled_bunch) 

81 

82 @ddt.data(True, False) 

83 def test_bunch_copy(self, deep): 

84 copy_bunch = self.bunch.copy(deep=deep) 

85 self.assertEqual(copy_bunch, self.bunch) 

86 self.assertIsNot(copy_bunch, self.bunch) 

87 

88 def test_name_starts_with_underscore_and_digit(self): 

89 bunch = driver_util.Bunch() 

90 bunch["1"] = "value" 

91 self.assertEqual(bunch._1, "value") 

92 

93 def test_bunch_recursion(self): 

94 x = driver_util.Bunch( 

95 a="a", b="b", d=driver_util.Bunch(x="axe", y="why") 

96 ) 

97 x.d.x = x 

98 x.d.y = x.b 

99 print(x) 

100 

101 def test_bunch_repr(self): 

102 self.assertEqual(repr(self.bunch), "Bunch(a=1, b=2)") 

103 

104 def test_getitem_with_integral_key(self): 

105 self.bunch["1"] = "value" 

106 self.assertEqual(self.bunch[1], "value") 

107 

108 def test_bunch_dir(self): 

109 self.assertEqual( 

110 set(i for i in dir(self.bunch) if not i.startswith("_")), 

111 { 

112 "a", 

113 "b", 

114 "but_with", 

115 "clear", 

116 "copy", 

117 "from_dict", 

118 "from_json", 

119 "fromkeys", 

120 "get", 

121 "items", 

122 "keys", 

123 "pop", 

124 "popitem", 

125 "render", 

126 "setdefault", 

127 "to_dict", 

128 "to_json", 

129 "update", 

130 "values", 

131 "without", 

132 }, 

133 ) 

134 

135 def test_bunch_edge_cases(self): 

136 # Test edge cases for attribute access, setting, and deletion 

137 self.bunch["key-with-special-chars_123"] = "value" 

138 self.assertEqual(self.bunch["key-with-special-chars_123"], "value") 

139 self.bunch["key-with-special-chars_123"] = None 

140 self.assertIsNone(self.bunch["key-with-special-chars_123"]) 

141 del self.bunch["key-with-special-chars_123"] 

142 self.assertRaises( 

143 KeyError, 

144 lambda: self.bunch["key-with-special-chars_123"] 

145 ) 

146 

147 def test_bunch_deep_copy(self): 

148 nested_bunch = driver_util.Bunch(x=driver_util.Bunch(y=1)) 

149 deep_copy = nested_bunch.copy(deep=True) 

150 self.assertIsNot(nested_bunch["x"], deep_copy["x"]) 

151 self.assertEqual(nested_bunch["x"]["y"], deep_copy["x"]["y"]) 

152 

153 def test_bunch_serialization(self): 

154 # Test serialization with nested structures 

155 nested_bunch = driver_util.Bunch(a=1, b=driver_util.Bunch(c=2)) 

156 self.assertEqual(nested_bunch.to_dict(), {"a": 1, "b": {"c": 2}}) 

157 self.assertEqual( 

158 nested_bunch.to_json(), 

159 json.dumps({"a": 1, "b": {"c": 2}}) 

160 ) 

161 

162 

163class TestBunchify(test.TestCase): 

164 def test_bunchify(self): 

165 self.assertEqual( 

166 driver_util.bunchify({"a": 1, "b": 2}, c=3), 

167 driver_util.Bunch(a=1, b=2, c=3) 

168 ) 

169 x = driver_util.bunchify(dict(a=[dict(b=5), 9, (1, 2)], c=8)) 

170 self.assertEqual(x.a[0].b, 5) 

171 self.assertEqual(x.a[1], 9) 

172 self.assertIsInstance(x.a[2], tuple) 

173 self.assertEqual(x.c, 8) 

174 self.assertEqual(x.pop("c"), 8) 

175 

176 def test_bunchify_edge_cases(self): 

177 # Test edge cases for bunchify function 

178 self.assertEqual(driver_util.bunchify({}), driver_util.Bunch()) 

179 

180 def test_bunchify_nested_structures(self): 

181 # Test bunchify with nested structures 

182 nested_dict = {"a": [{"b": 1}, 2]} 

183 self.assertEqual(driver_util.bunchify(nested_dict).a[0].b, 1) 

184 

185 

186class TestUnbunchify(test.TestCase): 

187 def test_unbunchify(self): 

188 self.assertEqual( 

189 driver_util.unbunchify(driver_util.Bunch(a=1, b=2)), 

190 {"a": 1, "b": 2} 

191 ) 

192 

193 

194@ddt.ddt 

195class TestGenerateIpRange(test.TestCase): 

196 

197 @ddt.data( 

198 ( 

199 [["15.0.0.1", "15.0.0.4"], ["10.0.0.27", "10.0.0.30"]], 

200 [ 

201 "15.0.0.1", 

202 "15.0.0.2", 

203 "15.0.0.3", 

204 "15.0.0.4", 

205 "10.0.0.27", 

206 "10.0.0.28", 

207 "10.0.0.29", 

208 "10.0.0.30", 

209 ], 

210 ), 

211 ( 

212 [["15.0.0.1", "15.0.0.1"], ["10.0.0.20", "10.0.0.20"]], 

213 ["15.0.0.1", "10.0.0.20"], 

214 ), 

215 ([], []), 

216 ) 

217 @ddt.unpack 

218 def test_generate_ip_range(self, ip_ranges, expected): 

219 ips = driver_util.generate_ip_range(ip_ranges) 

220 assert ips == expected 

221 

222 def test_generate_ip_range_edge_cases(self): 

223 # Test edge cases for generate_ip_range function 

224 self.assertEqual(driver_util.generate_ip_range([]), []) 

225 self.assertEqual(driver_util.generate_ip_range( 

226 [["15.0.0.1", "15.0.0.1"]]), ["15.0.0.1"] 

227 ) 

228 

229 def test_generate_ip_range_large_range(self): 

230 # Test with a large range of IPs 

231 start_ip = "192.168.0.1" 

232 end_ip = "192.168.255.255" 

233 ips = driver_util.generate_ip_range([[start_ip, end_ip]]) 

234 self.assertEqual(len(ips), 65535) 

235 

236 

237class MockClass1: 

238 def method1(self): 

239 return 1 

240 

241 def _private_method(self): 

242 return 2 

243 

244 

245class TestDecorateMethodsWith(test.TestCase): 

246 

247 def test_decorate_methods_with(self): 

248 decorated_cls = driver_util.decorate_methods_with( 

249 mock.Mock())(MockClass1) 

250 self.assertTrue(hasattr(decorated_cls, 'method1')) 

251 self.assertTrue(hasattr(decorated_cls, '_private_method')) 

252 

253 

254class MockClass2: 

255 @driver_util.verbose_driver_trace 

256 def method1(self): 

257 return 1 

258 

259 

260class TestVerboseDriverTrace(test.TestCase): 

261 

262 def test_verbose_driver_trace_debug_true(self): 

263 mock_instance = MockClass2() 

264 with mock.patch.object( 

265 driver_util.LOG, 'debug') as mock_debug: 

266 mock_instance.method1() 

267 self.assertEqual(mock_debug.call_count, 2)