ya2 · news · projects · code · about

c236c9a2f1a9346acf80cfb2f484acba92a14027
[pmachines.git] / tests / functional_test.py
1 '''Create ref:
2 * M-x fla-set-fun-test
3 * rm options.ini
4 * python main.py --functional-test --functional-ref & python -m ya2.tools.functional_test.py 1
5 * python main.py --functional-test --functional-ref & python -m ya2.tools.functional_test.py 2
6 * M-x fla-unset-fun-test'''
7 from panda3d.core import load_prc_file_data
8 load_prc_file_data('', 'window-type none')
9 import datetime
10 from time import sleep
11 from os import getcwd, system
12 from multiprocessing.connection import Client
13 from logging import debug, info
14 from pathlib import Path
15 from shutil import rmtree
16 from os import makedirs
17 from os.path import join, exists
18 from glob import glob
19 from sys import exit, argv
20 from panda3d.core import Filename
21 from direct.showbase.ShowBase import ShowBase
22 from direct.gui.OnscreenText import OnscreenText
23 from ya2.gameobject import GameObject
24 from ya2.build.build import _branch
25
26
27 class FunctionalTest(GameObject):
28
29 screenshot_time = 1.2
30 evt_time = 1.0
31 drag_time = 1.0
32 start_time = 2
33
34 def __init__(self, idx, offset):
35 super().__init__()
36 info('test idx: %s' % idx)
37 self._offset = offset
38 sleep(5)
39 address = ('localhost', 6000)
40 self._conn = Client(address)
41 self._curr_time = 0
42 self._tasks = []
43 self._prev_time = 0
44 taskMgr.add(self.on_frame_unpausable, 'on-frame-unpausable')
45 self._conn.send(['set_idx', idx])
46 self._do_screenshots(idx)
47
48 def _do_screenshot(self, name):
49 time = datetime.datetime.now().strftime('%y%m%d%H%M%S')
50 name = name + '.png'
51 self._conn.send(['screenshot', name])
52 info('screenshot %s' % name)
53
54 def _screenshot(self, time, name):
55 self._tasks += [(
56 self._curr_time + time,
57 lambda: self._do_screenshot(name),
58 'screenshot: %s' % name)]
59 self._curr_time += time
60
61 def __mouse_click(self, pos, btn):
62 offset_x = int((1920 - 1360) / 2) #+ 1 # xfce decorations
63 offset_y = int((1080 - 768) / 2) #+ 24 + self._offset # xfce decorations
64 btn = 3 if btn == 'right' else 1
65 system('xdotool mousemove %s %s' % (offset_x + pos[0], offset_y + pos[1]))
66 def click(task):
67 system('xdotool click %s' % btn)
68 taskMgr.do_method_later(.28, click, 'click')
69
70 def __mouse_drag(self, start, end, btn):
71 offset_x = int((1920 - 1360) / 2) #+ 1 # xfce decorations
72 offset_y = int((1080 - 768) / 2) #+ 24 + self._offset # xfce decorations
73 btn = 3 if btn == 'right' else 1
74 system('xdotool mousemove %s %s' % (offset_x + start[0], offset_y + start[1]))
75 def mousedown(task):
76 system('xdotool mousedown %s' % btn)
77 def mousemove(task):
78 system('xdotool mousemove %s %s' % (offset_x + end[0], offset_y + end[1]))
79 def mouseup(task):
80 system('xdotool mouseup %s' % btn)
81 taskMgr.do_method_later(.28, mouseup, 'mouseup')
82 taskMgr.do_method_later(.28, mousemove, 'mousemove')
83 taskMgr.do_method_later(.28, mousedown, 'mousedown')
84
85 def _event(self, time, evt, mouse_args=None):
86 if evt == 'mouseclick':
87 cback = lambda: self.__mouse_click(*mouse_args)
88 elif evt == 'mousedrag':
89 cback = lambda: self.__mouse_drag(*mouse_args)
90 self._tasks += [(
91 self._curr_time + time,
92 cback,
93 'event: %s' % evt)]
94 self._curr_time += time
95
96 def _enforce_res(self, time, res):
97 def cback():
98 self._conn.send(['enforce_res', res])
99 info('enforce_res %s' % res)
100 self._tasks += [(
101 self._curr_time + time,
102 cback,
103 'enforce res: %s' % res)]
104 self._curr_time += time
105
106 def _enforce_resolution(self, time, res):
107 def cback():
108 self._conn.send(['enforce_resolution', res])
109 info('enforce_resolution %s (send)' % res)
110 self._tasks += [(
111 self._curr_time + time,
112 cback,
113 'enforce resolution: %s' % res)]
114 self._curr_time += time
115
116 def _verify(self):
117 def __verify():
118 self._conn.send(['verify'])
119 info('verify')
120 self._tasks += [(
121 self._curr_time + 3,
122 lambda: __verify(),
123 'verify')]
124 self._curr_time += 3
125
126 def _exit(self):
127 def do_exit():
128 self._conn.close()
129 exit()
130 self._tasks += [(
131 self._curr_time + 3,
132 lambda: do_exit(),
133 'exit')]
134
135 def on_frame_unpausable(self, task):
136 for tsk in self._tasks:
137 #if self._prev_time <= tsk[0] < self.eng.event.unpaused_time:
138 if self._prev_time <= tsk[0] < globalClock.getFrameTime():
139 debug('%s %s' % (tsk[0], tsk[2]))
140 tsk[1]()
141 self._prev_time = globalClock.getFrameTime() # self.eng.event.unpaused_time
142 return task.cont
143
144 def _do_screenshots_1(self):
145 info('_do_screenshots_1')
146 self._screenshot(FunctionalTest.start_time, 'main_menu')
147 self._do_screenshots_credits()
148 self._do_screenshots_options()
149 self._do_screenshots_exit()
150
151 def _do_screenshots_credits(self):
152 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 450), 'left'])
153 self._screenshot(FunctionalTest.screenshot_time, 'credits_menu')
154 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 680), 'left'])
155 self._screenshot(FunctionalTest.screenshot_time, 'main_menu_back_from_credits')
156
157 def _do_screenshots_options(self):
158 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 300), 'left'])
159 self._screenshot(FunctionalTest.screenshot_time, 'options_menu')
160 # languages
161 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 60), 'left'])
162 self._screenshot(FunctionalTest.screenshot_time, 'open_languages')
163 self._event(FunctionalTest.evt_time, 'mouseclick', [(980, 120), 'left'])
164 self._screenshot(FunctionalTest.screenshot_time, 'options_menu_italian')
165 # volume
166 self._event(FunctionalTest.evt_time, 'mouseclick', [(740, 163), 'left'])
167 self._screenshot(FunctionalTest.screenshot_time, 'options_menu_drag_1')
168 # antialiasing
169 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 440), 'left'])
170 self._screenshot(FunctionalTest.screenshot_time, 'antialiasing_no')
171 # shadows
172 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 540), 'left'])
173 self._screenshot(FunctionalTest.screenshot_time, 'shadows_no')
174 # test aa and shadows
175 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 680), 'left']) # back
176 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 140), 'left']) # play
177 self._event(FunctionalTest.evt_time, 'mouseclick', [(230, 160), 'left']) # domino
178 self._event(FunctionalTest.evt_time, 'mouseclick', [(900, 490), 'left']) # close instructions
179 self._screenshot(FunctionalTest.screenshot_time, 'aa_no_shadows_no')
180 self._event(FunctionalTest.evt_time, 'mouseclick', [(25, 740), 'left']) # home
181
182 def _do_screenshots_restore_options(self):
183 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 300), 'left'])
184 self._screenshot(FunctionalTest.screenshot_time, 'options_menu_restored')
185 # languages
186 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 60), 'left'])
187 self._screenshot(FunctionalTest.screenshot_time, 'open_languages_restored')
188 self._event(FunctionalTest.evt_time, 'mouseclick', [(980, 20), 'left'])
189 self._screenshot(FunctionalTest.screenshot_time, 'options_menu_english')
190 # volume
191 self._event(FunctionalTest.evt_time, 'mouseclick', [(719, 163), 'left'])
192 self._screenshot(FunctionalTest.screenshot_time, 'options_menu_drag_2')
193 # fullscreen
194 # the first one is because of the windowed mode in test
195 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 250), 'left'])
196 self._screenshot(FunctionalTest.screenshot_time, 'fullscreen')
197 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 250), 'left'])
198 self._screenshot(FunctionalTest.screenshot_time, 'fullscreen')
199 #self._event(8 + FunctionalTest.evt_time, 'mouseclick', [(440, 120), 'left'])
200 self._event(8 + FunctionalTest.evt_time, 'mouseclick', [(680, 250), 'left'])
201 self._screenshot(8 + FunctionalTest.screenshot_time, 'back_from_fullscreen')
202 # resolution
203 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 340), 'left'])
204 self._screenshot(FunctionalTest.screenshot_time, 'resolutions')
205 self._enforce_resolution(FunctionalTest.evt_time, '1440x900')
206 self._event(FunctionalTest.evt_time, 'mouseclick', [(1000, 440), 'left'])
207 self._screenshot(FunctionalTest.screenshot_time, '1440x900')
208 self._event(FunctionalTest.evt_time, 'mouseclick', [(740, 400), 'left'])
209 self._screenshot(FunctionalTest.screenshot_time, 'resolutions_2')
210 self._enforce_resolution(FunctionalTest.evt_time, '1360x768')
211 self._event(FunctionalTest.evt_time, 'mouseclick', [(1110, 80), 'left'])
212 self._screenshot(FunctionalTest.screenshot_time, '1360x768')
213 # antialiasing
214 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 440), 'left'])
215 self._screenshot(FunctionalTest.screenshot_time, 'antialiasing_yes')
216 # shadows
217 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 540), 'left'])
218 self._screenshot(FunctionalTest.screenshot_time, 'shadows_yes')
219 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 680), 'left']) # back
220
221 def _do_screenshots_play(self):
222 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 140), 'left']) # play
223 self._screenshot(FunctionalTest.screenshot_time, 'play_menu')
224 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 680), 'left']) # back
225 self._screenshot(FunctionalTest.screenshot_time, 'back_from_play')
226 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 140), 'left']) # play
227 self._event(FunctionalTest.evt_time, 'mouseclick', [(230, 160), 'left']) # domino scene
228 self._screenshot(FunctionalTest.screenshot_time, 'scene_domino_instructions')
229 self._event(FunctionalTest.evt_time, 'mouseclick', [(850, 490), 'left']) # close instructions
230 self._screenshot(FunctionalTest.screenshot_time, 'scene_domino')
231 self._event(FunctionalTest.evt_time, 'mouseclick', [(25, 740), 'left']) # home
232 self._screenshot(FunctionalTest.screenshot_time, 'home_back_from_scene')
233 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 140), 'left']) # play
234 self._event(FunctionalTest.evt_time, 'mouseclick', [(230, 160), 'left']) # domino
235 self._event(FunctionalTest.evt_time, 'mouseclick', [(850, 490), 'left']) # close instructions
236 self._event(FunctionalTest.evt_time, 'mouseclick', [(70, 740), 'left']) # info
237 self._screenshot(FunctionalTest.screenshot_time, 'info')
238 self._event(FunctionalTest.evt_time, 'mouseclick', [(850, 490), 'left']) # close instructions
239 # self._event(FunctionalTest.drag_time, 'mousedrag', [(35, 60), (430, 280), 'left']) # drag a piece
240 # self._screenshot(FunctionalTest.screenshot_time, 'domino_dragged')
241 # self._event(FunctionalTest.evt_time, 'mouseclick', [(1220, 740), 'left']) # rewind
242 # self._screenshot(FunctionalTest.screenshot_time, 'rewind')
243 self._event(FunctionalTest.drag_time, 'mousedrag', [(35, 60), (550, 380), 'left']) # drag a piece
244 # self._event(FunctionalTest.drag_time, 'mousedrag', [(35, 60), (715, 380), 'left']) # drag a piece
245 self._event(FunctionalTest.evt_time, 'mouseclick', [(1340, 740), 'left']) # play
246 self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_domino')
247 self._event(FunctionalTest.evt_time, 'mouseclick', [(630, 450), 'left']) # home
248 self._screenshot(FunctionalTest.screenshot_time, 'home_back_from_fail')
249 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 140), 'left']) # play
250 self._event(FunctionalTest.evt_time, 'mouseclick', [(230, 160), 'left']) # domino
251 self._event(FunctionalTest.evt_time, 'mouseclick', [(850, 490), 'left']) # close instructions
252 self._event(FunctionalTest.drag_time, 'mousedrag', [(35, 60), (550, 380), 'left']) # drag a piece
253 self._event(FunctionalTest.drag_time, 'mousedrag', [(35, 60), (715, 380), 'left']) # drag a piece
254 self._event(FunctionalTest.evt_time, 'mouseclick', [(1340, 740), 'left']) # play
255 self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_domino_2')
256 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 450), 'left']) # replay
257 self._event(FunctionalTest.drag_time, 'mousedrag', [(35, 60), (570, 380), 'left']) # drag a piece
258 self._event(FunctionalTest.drag_time, 'mousedrag', [(570, 355), (605, 355), 'right']) # rotate the piece
259 self._event(FunctionalTest.drag_time, 'mousedrag', [(35, 60), (715, 380), 'left']) # drag a piece
260 self._enforce_res(FunctionalTest.evt_time, 'win')
261 self._event(FunctionalTest.evt_time, 'mouseclick', [(1340, 740), 'left']) # play
262 self._screenshot(16 + FunctionalTest.screenshot_time, 'win_domino')
263 self._enforce_res(FunctionalTest.evt_time, '')
264 self._event(FunctionalTest.evt_time, 'mouseclick', [(735, 450), 'left']) # next
265 self._screenshot(FunctionalTest.screenshot_time, 'scene_box')
266 # scene 2
267 self._event(FunctionalTest.evt_time, 'mouseclick', [(880, 490), 'left']) # close instructions
268 self._event(FunctionalTest.drag_time, 'mousedrag', [(65, 60), (710, 620), 'left']) # drag a box
269 self._event(FunctionalTest.drag_time, 'mousedrag', [(65, 60), (710, 540), 'left']) # drag a box
270 self._event(FunctionalTest.evt_time, 'mouseclick', [(1340, 740), 'left']) # play
271 self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_box')
272 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 450), 'left']) # replay
273 self._event(FunctionalTest.drag_time, 'mousedrag', [(65, 60), (710, 620), 'left']) # drag a box
274 self._event(FunctionalTest.drag_time, 'mousedrag', [(65, 60), (710, 540), 'left']) # drag a box
275 self._event(FunctionalTest.drag_time, 'mousedrag', [(65, 60), (705, 460), 'left']) # drag a box
276 self._enforce_res(FunctionalTest.evt_time, 'win')
277 self._event(FunctionalTest.evt_time, 'mouseclick', [(1340, 740), 'left']) # play
278 self._screenshot(16 + FunctionalTest.screenshot_time, 'win_box')
279 self._enforce_res(FunctionalTest.evt_time, '')
280 self._event(FunctionalTest.evt_time, 'mouseclick', [(735, 450), 'left']) # next
281 self._screenshot(FunctionalTest.screenshot_time, 'scene_box_domino')
282 # scene 3
283 self._event(FunctionalTest.evt_time, 'mouseclick', [(930, 485), 'left']) # close instructions
284 self._event(FunctionalTest.drag_time, 'mousedrag', [(65, 60), (910, 440), 'left']) # drag a box
285 self._event(FunctionalTest.drag_time, 'mousedrag', [(65, 60), (910, 360), 'left']) # drag a box
286 self._event(FunctionalTest.evt_time, 'mouseclick', [(1340, 740), 'left']) # play
287 self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_box_domino')
288 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 450), 'left']) # replay
289 self._event(FunctionalTest.drag_time, 'mousedrag', [(65, 60), (910, 440), 'left']) # drag a box
290 self._event(FunctionalTest.drag_time, 'mousedrag', [(65, 60), (835, 250), 'left']) # drag a box
291 self._enforce_res(FunctionalTest.evt_time, 'win')
292 self._event(FunctionalTest.evt_time, 'mouseclick', [(1340, 740), 'left']) # play
293 self._screenshot(16 + FunctionalTest.screenshot_time, 'win_box_domino')
294 self._enforce_res(FunctionalTest.evt_time, '')
295 self._event(FunctionalTest.evt_time, 'mouseclick', [(735, 450), 'left']) # next
296 self._screenshot(FunctionalTest.screenshot_time, 'scene_basketball')
297 # scene 4
298 self._event(FunctionalTest.evt_time, 'mouseclick', [(870, 490), 'left']) # close instructions
299 self._event(FunctionalTest.drag_time, 'mousedrag', [(55, 50), (650, 310), 'left']) # drag a ball
300 self._event(FunctionalTest.evt_time, 'mouseclick', [(1340, 740), 'left']) # play
301 self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_basketball')
302 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 450), 'left']) # replay
303 self._event(FunctionalTest.drag_time, 'mousedrag', [(55, 50), (380, 50), 'left']) # drag a ball
304 self._enforce_res(FunctionalTest.evt_time, 'win')
305 self._event(FunctionalTest.evt_time, 'mouseclick', [(1340, 740), 'left']) # play
306 self._screenshot(16 + FunctionalTest.screenshot_time, 'win_basketball')
307 self._enforce_res(FunctionalTest.evt_time, '')
308 self._event(FunctionalTest.evt_time, 'mouseclick', [(735, 450), 'left']) # next
309 self._screenshot(FunctionalTest.screenshot_time, 'scene_domino_box_basketball')
310 # scene 5
311 self._event(FunctionalTest.evt_time, 'mouseclick', [(865, 490), 'left']) # close instructions
312 self._event(FunctionalTest.drag_time, 'mousedrag', [(65, 60), (580, 440), 'left']) # drag a box
313 self._event(FunctionalTest.drag_time, 'mousedrag', [(30, 60), (590, 370), 'left']) # drag a piece
314 self._event(FunctionalTest.evt_time, 'mouseclick', [(1340, 740), 'left']) # play
315 self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_domino_box_basketball')
316 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 450), 'left']) # replay
317 self._event(FunctionalTest.drag_time, 'mousedrag', [(65, 60), (580, 440), 'left']) # drag a box
318 self._event(FunctionalTest.drag_time, 'mousedrag', [(30, 60), (660, 440), 'left']) # drag a piece
319 self._event(FunctionalTest.drag_time, 'mousedrag', [(660, 425), (625, 425), 'right']) # rotate a piece
320 self._event(FunctionalTest.drag_time, 'mousedrag', [(660, 435), (650, 445), 'left']) # drag a piece
321 self._enforce_res(FunctionalTest.evt_time, 'win')
322 self._event(FunctionalTest.evt_time, 'mouseclick', [(1340, 740), 'left']) # play
323 self._screenshot(16 + FunctionalTest.screenshot_time, 'win_domino_box_basketball')
324 self._enforce_res(FunctionalTest.evt_time, '')
325 self._event(FunctionalTest.evt_time, 'mouseclick', [(735, 450), 'left']) # next
326 self._screenshot(FunctionalTest.screenshot_time, 'scene_teeter_tooter')
327 # scene 6
328 self._event(FunctionalTest.evt_time, 'mouseclick', [(870, 485), 'left']) # close instructions
329 self._event(FunctionalTest.drag_time, 'mousedrag', [(60, 60), (490, 300), 'left']) # drag a box
330 self._event(FunctionalTest.evt_time, 'mouseclick', [(1340, 740), 'left']) # play
331 self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_teeter_tooter')
332 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 450), 'left']) # replay
333 self._event(FunctionalTest.drag_time, 'mousedrag', [(60, 60), (490, 150), 'left']) # drag a box
334 self._event(FunctionalTest.drag_time, 'mousedrag', [(515, 115), (515, 122), 'right']) # rotate a box
335 self._enforce_res(FunctionalTest.evt_time, 'win')
336 self._event(FunctionalTest.evt_time, 'mouseclick', [(1340, 740), 'left']) # play
337 self._screenshot(16 + FunctionalTest.screenshot_time, 'win_teeter_tooter')
338 self._enforce_res(FunctionalTest.evt_time, '')
339 self._event(FunctionalTest.evt_time, 'mouseclick', [(735, 450), 'left']) # next
340 self._screenshot(FunctionalTest.screenshot_time, 'scene_teeter_domino_box_basketball')
341 # scene 7
342 self._event(FunctionalTest.evt_time, 'mouseclick', [(930, 485), 'left']) # close instructions
343 self._event(FunctionalTest.drag_time, 'mousedrag', [(60, 60), (155, 180), 'left']) # drag a box
344 self._event(FunctionalTest.evt_time, 'mouseclick', [(1340, 740), 'left']) # play
345 self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_teeter_domino_box_basketball')
346 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 450), 'left']) # replay
347 self._event(FunctionalTest.drag_time, 'mousedrag', [(60, 60), (170, 80), 'left']) # drag a box
348 self._event(FunctionalTest.drag_time, 'mousedrag', [(195, 50), (195, 80), 'right']) # rotate a box
349 self._enforce_res(FunctionalTest.evt_time, 'win')
350 self._event(FunctionalTest.evt_time, 'mouseclick', [(1340, 740), 'left']) # play
351 self._screenshot(16 + FunctionalTest.screenshot_time, 'win_teeter_domino_box_basketball')
352 self._enforce_res(FunctionalTest.evt_time, '')
353 self._event(FunctionalTest.evt_time, 'mouseclick', [(630, 450), 'left']) # home
354 self._screenshot(FunctionalTest.screenshot_time, 'home_from_play')
355
356 def _exit(self):
357 self._tasks += [(
358 self._curr_time + 3,
359 lambda: exit(),
360 'exit')]
361
362 def _do_screenshots_exit(self):
363 self._verify()
364 self._event(FunctionalTest.evt_time, 'mouseclick', [(680, 600), 'left'])
365 self._exit()
366
367 def _do_screenshots_2(self):
368 info('_do_screenshots_2')
369 self._screenshot(FunctionalTest.start_time, 'main_menu_2')
370 self._do_screenshots_restore_options()
371 self._do_screenshots_play()
372 self._do_screenshots_exit()
373
374 def _do_screenshots(self, idx):
375 [self._do_screenshots_1, self._do_screenshots_2][int(idx) - 1]()
376
377
378 class TestApp(ShowBase):
379
380 def __init__(self):
381 ShowBase.__init__(self)
382 offset = int(argv[2]) if len(argv) >= 3 else 0
383 fun_test = FunctionalTest(int(argv[1]), offset)
384
385
386 TestApp().run()