Coverage for mlos_bench/mlos_bench/tests/environments/composite_env_test.py: 100%

35 statements  

« prev     ^ index     » next       coverage.py v7.5.1, created at 2024-05-06 00:35 +0000

1# 

2# Copyright (c) Microsoft Corporation. 

3# Licensed under the MIT License. 

4# 

5""" 

6Unit tests for composite environment. 

7""" 

8 

9import pytest 

10 

11from mlos_bench.environments.composite_env import CompositeEnv 

12from mlos_bench.tunables.tunable_groups import TunableGroups 

13from mlos_bench.services.config_persistence import ConfigPersistenceService 

14 

15# pylint: disable=redefined-outer-name 

16 

17 

18@pytest.fixture 

19def composite_env(tunable_groups: TunableGroups) -> CompositeEnv: 

20 """ 

21 Test fixture for CompositeEnv. 

22 """ 

23 return CompositeEnv( 

24 name="Composite Test Environment", 

25 config={ 

26 "tunable_params": ["provision", "boot"], 

27 "const_args": { 

28 "vm_server_name": "Mock Server VM", 

29 "vm_client_name": "Mock Client VM", 

30 "someConst": "root", 

31 "global_param": "default" 

32 }, 

33 "children": [ 

34 { 

35 "name": "Mock Client Environment 1", 

36 "class": "mlos_bench.environments.mock_env.MockEnv", 

37 "config": { 

38 "tunable_params": ["provision"], 

39 "const_args": { 

40 "vmName": "$vm_client_name", 

41 "EnvId": 1, 

42 }, 

43 "required_args": ["vmName", "someConst", "global_param"], 

44 "range": [60, 120], 

45 "metrics": ["score"], 

46 } 

47 }, 

48 { 

49 "name": "Mock Server Environment 2", 

50 "class": "mlos_bench.environments.mock_env.MockEnv", 

51 "config": { 

52 "tunable_params": ["boot"], 

53 "const_args": { 

54 "vmName": "$vm_server_name", 

55 "EnvId": 2, 

56 "global_param": "local" 

57 }, 

58 "required_args": ["vmName"], 

59 "range": [60, 120], 

60 "metrics": ["score"], 

61 } 

62 }, 

63 { 

64 "name": "Mock Control Environment 3", 

65 "class": "mlos_bench.environments.mock_env.MockEnv", 

66 "config": { 

67 "tunable_params": ["boot"], 

68 "const_args": { 

69 "vmName": "Mock Control VM", 

70 "EnvId": 3, 

71 }, 

72 "required_args": ["vmName", "vm_server_name", "vm_client_name"], 

73 "range": [60, 120], 

74 "metrics": ["score"], 

75 } 

76 } 

77 ] 

78 }, 

79 tunables=tunable_groups, 

80 service=ConfigPersistenceService({}), 

81 global_config={ 

82 "global_param": "global_value" 

83 } 

84 ) 

85 

86 

87def test_composite_env_params(composite_env: CompositeEnv) -> None: 

88 """ 

89 Check that the const_args from the parent environment get propagated to the children. 

90 NOTE: The current logic is that variables flow down via required_args and const_args, parent 

91 """ 

92 assert composite_env.children[0].parameters == { 

93 "vmName": "Mock Client VM", # const_args from the parent thru variable substitution 

94 "EnvId": 1, # const_args from the child 

95 "vmSize": "Standard_B4ms", # tunable_params from the parent 

96 "someConst": "root", # pulled in from parent via required_args 

97 "global_param": "global_value" # pulled in from the global_config 

98 } 

99 assert composite_env.children[1].parameters == { 

100 "vmName": "Mock Server VM", # const_args from the parent 

101 "EnvId": 2, # const_args from the child 

102 "idle": "halt", # tunable_params from the parent 

103 # "someConst": "root" # not required, so not passed from the parent 

104 "global_param": "global_value" # pulled in from the global_config 

105 } 

106 assert composite_env.children[2].parameters == { 

107 "vmName": "Mock Control VM", # const_args from the parent 

108 "EnvId": 3, # const_args from the child 

109 "idle": "halt", # tunable_params from the parent 

110 # "someConst": "root" # not required, so not passed from the parent 

111 "vm_client_name": "Mock Client VM", 

112 "vm_server_name": "Mock Server VM" 

113 # "global_param": "global_value" # not required, so not picked from the global_config 

114 } 

115 

116 

117def test_composite_env_setup(composite_env: CompositeEnv, tunable_groups: TunableGroups) -> None: 

118 """ 

119 Check that the child environments update their tunable parameters. 

120 """ 

121 tunable_groups.assign({ 

122 "vmSize": "Standard_B2s", 

123 "idle": "mwait", 

124 "kernel_sched_migration_cost_ns": 100000, 

125 }) 

126 

127 with composite_env as env_context: 

128 assert env_context.setup(tunable_groups) 

129 

130 assert composite_env.children[0].parameters == { 

131 "vmName": "Mock Client VM", # const_args from the parent 

132 "EnvId": 1, # const_args from the child 

133 "vmSize": "Standard_B2s", # tunable_params from the parent 

134 "someConst": "root", # pulled in from parent via required_args 

135 "global_param": "global_value" # pulled in from the global_config 

136 } 

137 assert composite_env.children[1].parameters == { 

138 "vmName": "Mock Server VM", # const_args from the parent 

139 "EnvId": 2, # const_args from the child 

140 "idle": "mwait", # tunable_params from the parent 

141 # "someConst": "root" # not required, so not passed from the parent 

142 "global_param": "global_value" # pulled in from the global_config 

143 } 

144 assert composite_env.children[2].parameters == { 

145 "vmName": "Mock Control VM", # const_args from the parent 

146 "EnvId": 3, # const_args from the child 

147 "idle": "mwait", # tunable_params from the parent 

148 "vm_client_name": "Mock Client VM", 

149 "vm_server_name": "Mock Server VM", 

150 # "global_param": "global_value" # not required, so not picked from the global_config 

151 } 

152 

153 

154@pytest.fixture 

155def nested_composite_env(tunable_groups: TunableGroups) -> CompositeEnv: 

156 """ 

157 Test fixture for CompositeEnv. 

158 """ 

159 return CompositeEnv( 

160 name="Composite Test Environment", 

161 config={ 

162 "tunable_params": ["provision", "boot"], 

163 "const_args": { 

164 "vm_server_name": "Mock Server VM", 

165 "vm_client_name": "Mock Client VM", 

166 "someConst": "root" 

167 }, 

168 "children": [ 

169 { 

170 "name": "Nested Composite Client Environment 1", 

171 "class": "mlos_bench.environments.composite_env.CompositeEnv", 

172 "config": { 

173 "tunable_params": ["provision"], 

174 "const_args": { 

175 "vmName": "$vm_client_name", 

176 "EnvId": 1, 

177 }, 

178 "required_args": ["vmName", "EnvId", "someConst", "vm_server_name"], 

179 "children": [ 

180 { 

181 "name": "Mock Client Environment 1", 

182 "class": "mlos_bench.environments.mock_env.MockEnv", 

183 "config": { 

184 "tunable_params": ["provision"], 

185 # TODO: Might be nice to include a "^" or "*" option 

186 # here to indicate that all required_args from 

187 # the parent should be included here too in 

188 # order to reduce duplication. 

189 "required_args": [ 

190 "vmName", 

191 "EnvId", 

192 "someConst", 

193 "vm_server_name", 

194 "global_param" 

195 ], 

196 "range": [60, 120], 

197 "metrics": ["score"], 

198 } 

199 }, 

200 # ... 

201 ], 

202 }, 

203 }, 

204 { 

205 "name": "Nested Composite Server Environment 2", 

206 "class": "mlos_bench.environments.composite_env.CompositeEnv", 

207 "config": { 

208 "tunable_params": ["boot"], 

209 "const_args": { 

210 "vmName": "$vm_server_name", 

211 "EnvId": 2, 

212 }, 

213 "required_args": ["vmName", "EnvId", "vm_client_name"], 

214 "children": [ 

215 { 

216 "name": "Mock Server Environment 2", 

217 "class": "mlos_bench.environments.mock_env.MockEnv", 

218 "config": { 

219 "tunable_params": ["boot"], 

220 "required_args": ["vmName", "EnvId", "vm_client_name"], 

221 "range": [60, 120], 

222 "metrics": ["score"], 

223 } 

224 }, 

225 # ... 

226 ], 

227 }, 

228 }, 

229 

230 ] 

231 }, 

232 tunables=tunable_groups, 

233 service=ConfigPersistenceService({}), 

234 global_config={ 

235 "global_param": "global_value" 

236 } 

237 ) 

238 

239 

240def test_nested_composite_env_params(nested_composite_env: CompositeEnv) -> None: 

241 """ 

242 Check that the const_args from the parent environment get propagated to the children. 

243 NOTE: The current logic is that variables flow down via required_args and const_args, parent 

244 """ 

245 assert isinstance(nested_composite_env.children[0], CompositeEnv) 

246 assert nested_composite_env.children[0].children[0].parameters == { 

247 "vmName": "Mock Client VM", # const_args from the parent thru variable substitution 

248 "EnvId": 1, # const_args from the child 

249 "vmSize": "Standard_B4ms", # tunable_params from the parent 

250 "someConst": "root", # pulled in from parent via required_args 

251 "vm_server_name": "Mock Server VM", 

252 "global_param": "global_value" # pulled in from the global_config 

253 } 

254 assert isinstance(nested_composite_env.children[1], CompositeEnv) 

255 assert nested_composite_env.children[1].children[0].parameters == { 

256 "vmName": "Mock Server VM", # const_args from the parent 

257 "EnvId": 2, # const_args from the child 

258 "idle": "halt", # tunable_params from the parent 

259 # "someConst": "root" # not required, so not passed from the parent 

260 "vm_client_name": "Mock Client VM", 

261 # "global_param": "global_value" # not required, so not picked from the global_config 

262 } 

263 

264 

265def test_nested_composite_env_setup(nested_composite_env: CompositeEnv, tunable_groups: TunableGroups) -> None: 

266 """ 

267 Check that the child environments update their tunable parameters. 

268 """ 

269 tunable_groups.assign({ 

270 "vmSize": "Standard_B2s", 

271 "idle": "mwait", 

272 "kernel_sched_migration_cost_ns": 100000, 

273 }) 

274 

275 with nested_composite_env as env_context: 

276 assert env_context.setup(tunable_groups) 

277 

278 assert isinstance(nested_composite_env.children[0], CompositeEnv) 

279 assert nested_composite_env.children[0].children[0].parameters == { 

280 "vmName": "Mock Client VM", # const_args from the parent 

281 "EnvId": 1, # const_args from the child 

282 "vmSize": "Standard_B2s", # tunable_params from the parent 

283 "someConst": "root", # pulled in from parent via required_args 

284 "vm_server_name": "Mock Server VM", 

285 "global_param": "global_value" # pulled in from the global_config 

286 } 

287 

288 assert isinstance(nested_composite_env.children[1], CompositeEnv) 

289 assert nested_composite_env.children[1].children[0].parameters == { 

290 "vmName": "Mock Server VM", # const_args from the parent 

291 "EnvId": 2, # const_args from the child 

292 "idle": "mwait", # tunable_params from the parent 

293 # "someConst": "root" # not required, so not passed from the parent 

294 "vm_client_name": "Mock Client VM", 

295 }