• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2017 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import random
6import logging
7import time
8from autotest_lib.client.common_lib import error
9from autotest_lib.server.cros.cfm import cfm_base_test
10from autotest_lib.client.common_lib.cros.manual import audio_helper
11from autotest_lib.client.common_lib.cros.manual import cfm_helper
12from autotest_lib.client.common_lib.cros.manual import meet_helper
13from autotest_lib.client.common_lib.cros.manual import video_helper
14from autotest_lib.client.common_lib.cros.manual import get_usb_devices
15
16ATRUS = "Hangouts Meet speakermic"
17CORE_DIR_LINES = 5
18FAILURE_REASON = {
19                 'telemetry':
20                     ['No hangouts or meet telemetry API available',
21                      'telemetry api',
22                      'RPC: cfm_main_screen.',
23                      'Failed RPC',
24                      'cfm_main_screen',
25                      'Webview with screen param',
26                      'autotest_lib.client.common_lib.error.TestFail'],
27                 'chrome':[],
28                 'kernel':[],
29                 'atrus':[]
30}
31NUM_AUDIO_STREAM_IN_MEETING = 3
32LOG_CHECK_LIST = ['check_kernel_errorlog',
33                  'check_video_errorlog',
34                  'check_audio_errorlog',
35                  'check_chrome_errorlog',
36                  'check_atrus_errorlog',
37                  'check_usb_stability']
38TEST_DELAY = 0
39
40class enterprise_CFM_Test(cfm_base_test.CfmBaseTest):
41    """Executes multiple tests on CFM device based on control file,
42    after each test, perform mulitple verifications based on control
43    file. Test flow can be controlled by control file, such as abort
44    on failure, or continue on failure.
45    """
46    version = 1
47
48    def gpio_test(self):
49        """
50        Powercycle USB port on Guado.
51        """
52        if self.run_meeting_test:
53            if self.random:
54                min_meetings = random.randrange(-1, self.gpio_min_meets)
55            else:
56                min_meetings = self.gpio_min_meets
57            if self.meets_last_gpio <=  min_meetings:
58                logging.debug('Skip gpio test.')
59                return True, None
60        if cfm_helper.check_is_platform(self.client, 'guado'):
61            status, errmsg =  cfm_helper.gpio_usb_test(self.client,
62                              self.gpio_list,
63                              self.puts, self.gpio_pause,
64                              'guado')
65            self.gpio_no += 1
66            self.meets_last_gpio = 0
67        else:
68            logging.info('Skip gpio_test for non-guado CfM.')
69            return True, None
70
71        ## workaround for bug b/69261543
72        if self.is_in_meet:
73            self.is_camera_muted = self.cfm_facade.is_camera_muted()
74        return status, errmsg
75
76
77    def meeting_test(self):
78        """
79        Join/leave meeting.
80        """
81        if self.is_in_meet:
82            status, errmsg = meet_helper.leave_meeting(self.cfm_facade,
83                             self.is_meeting)
84            if status:
85                self.is_camera_muted = True
86                self.is_in_meet = False
87                return True, None
88            else:
89                if self.recover_on_failure or self.meets_last_reboot == 0:
90                    self.is_in_meet = False
91                else:
92                    self.is_in_meet = True
93                return False, errmsg
94        else:
95            status, errmsg = meet_helper.join_meeting(self.cfm_facade,
96                             self.is_meeting, self.meeting_code)
97            if status:
98                self.is_camera_muted = False
99                self.is_in_meet = True
100                self.meet_no += 1
101                self.meets_last_reboot += 1
102                self.meets_last_gpio += 1
103                return True, None
104            else:
105                if self.recover_on_failure or self.meets_last_reboot == 0:
106                    self.is_in_meet = True
107                else:
108                    self.is_in_meet = False
109                return False, errmsg
110
111    def reboot_test(self):
112        """
113        Reboot CfM.
114        """
115        if self.run_meeting_test:
116            if self.random:
117                min_meetings = random.randrange(-1, self.reboot_min_meets)
118            else:
119                min_meetings = self.reboot_min_meets
120            if self.meets_last_reboot <  min_meetings:
121                logging.info('Skip reboot CfM test')
122                return True, None
123        try:
124            self.client.reboot()
125            time.sleep(self.reboot_timeout)
126        except Exception as e:
127            errmsg = 'Reboot test fails for %s' % self.ip_addr
128            logging.exception(errmsg)
129            self.reboot_log = cfm_helper.check_last_reboot(self.client)
130            self.chrome_file = cfm_helper.check_chrome_logfile(self.client)
131            return False, errmsg
132        self.reboot_no += 1
133        self.meets_last_reboot = 0
134        if 'meeting_test' in self.action_config:
135            self.reboot_log = cfm_helper.check_last_reboot(self.client)
136            if list(set(self.verification_config) & set(LOG_CHECK_LIST)):
137                self.log_checking_point = cfm_helper.find_last_log(self.client,
138                                                                   self.speaker)
139            return self.restart_chrome_and_meeting(True)
140        self.reboot_log = cfm_helper.check_last_reboot(self.client)
141        self.chrome_file = cfm_helper.check_chrome_logfile(self.client)
142        if list(set(self.verification_config) & set(LOG_CHECK_LIST)):
143            self.log_checking_point = cfm_helper.find_last_log(self.client,
144                                                               self.speaker)
145        return True, None
146
147    def restart_chrome_and_meeting(self, recovery):
148        """
149        Restart Chrome and Join/Start meeting if previous state is in meeting.
150        """
151        result, errmsg = meet_helper.restart_chrome(self.cfm_facade,
152                                                    self.is_meeting,
153                                                    recovery)
154        logging.info('restart chrome result:%s, msg = %s', result,errmsg)
155        if not result:
156            logging.info('restart chrome result: False, msg = %s', errmsg)
157            self.chrome_file = cfm_helper.check_chrome_logfile(self.client)
158            return False, errmsg
159        if self.is_in_meet:
160            logging.info('start meeting if needed')
161            self.is_in_meet = False
162            self.chrome_file = cfm_helper.check_chrome_logfile(self.client)
163            test_result, ret_msg =  self.meeting_test()
164            if test_result:
165                try:
166                    self.is_camera_muted =  self.cfm_facade.is_camera_muted()
167                    self.is_mic_muted = self.cfm_facade.is_mic_muted()
168                except Exception as e:
169                    errmsg = 'Fail to run telemetry api to check camera..'
170                    logging.exception(errmsg)
171                    return False, errmsg
172        self.chrome_file = cfm_helper.check_chrome_logfile(self.client)
173        return True, None
174
175    # TODO(mzhuo): Adding resetusb test.
176    def reset_usb_test(self):
177        """
178        Reset USB port
179        """
180        return True, None
181
182    def mute_unmute_camera_test(self):
183        """
184        Mute or unmute camera.
185        """
186        if not self.camera:
187            logging.info('Skip mute/unmute camera testing.')
188            return True, None
189        if self.is_in_meet:
190            if self.is_camera_muted:
191                status, errmsg = meet_helper.mute_unmute_camera(
192                                 self.cfm_facade, True)
193                if status:
194                    self.is_camera_muted = False
195                else:
196                    return False, errmsg
197            else:
198                status, errmsg =  meet_helper.mute_unmute_camera(
199                                  self.cfm_facade, False)
200                if status:
201                    self.is_camera_muted = True
202                else:
203                    return False, errmsg
204        return True, None
205
206    def mute_unmute_mic_test(self):
207        """
208        Mute or unmute microphone.
209        """
210        if not self.speaker and not cfm_helper.check_is_platform(self.client,
211                                                                 'buddy'):
212            logging.info('Skip mute/unmute microphone testing.')
213            return True, None
214        if self.is_in_meet:
215            if self.is_mic_muted:
216                status, errmsg =  meet_helper.mute_unmute_mic(self.cfm_facade,
217                                  True)
218                if status:
219                    self.is_mic_muted = False
220                else:
221                    return False, errmsg
222            else:
223                status, errmsg =  meet_helper.mute_unmute_mic(self.cfm_facade,
224                                  False)
225                if status:
226                    self.is_mic_muted = True
227                else:
228                    return False, errmsg
229        return True, None
230
231
232    def speaker_volume_test(self):
233        """
234        Update speaker volume.
235        """
236        if not self.speaker and not cfm_helper.check_is_platform(self.client,
237                                                                 'buddy'):
238            logging.info('Skip update volume of speaker testing.')
239            return True, None
240        if self.is_in_meet:
241            test_result, ret_msg =  meet_helper.speaker_volume_test(
242                                   self.cfm_facade,
243                                   self.vol_change_step,
244                                   self.vol_change_mode, self.random)
245            if test_result:
246                self.speaker_volume = int(ret_msg)
247                return True, None
248            else:
249                return False, ret_msg
250        else:
251            return True, None
252
253    # TODO(mzhuo): Adding test to turn on/off monite.
254    def flap_monitor_test(self):
255        """
256        Connect or disconnect monitor.
257        """
258        return True, None
259
260    def check_usb_enumeration(self):
261        """
262        Verify all usb devices which were enumerated originally are enumerated.
263        """
264        return cfm_helper.check_usb_enumeration(self.client,
265                                                self.puts)
266
267    def check_usb_inf_init(self):
268        """
269        Verify all usb devices which were enumerated originally have
270        valid interfaces: video interface, audio interface or touch
271        interface.
272        """
273        return cfm_helper.check_usb_interface_initializion(self.client,
274               self.puts)
275
276    def check_v4l2_interface(self):
277        """
278        Verify camera has v4l2 file handler created.
279        """
280        if not self.camera:
281            return True, None
282        return video_helper.check_v4l2_interface(self.client,
283               self.camera, self.name_camera)
284
285    def check_audio_card(self):
286        """
287        Verify speaker/microphone has audip file handler created.
288        """
289        if not self.speaker:
290            return True, None
291        return audio_helper.check_soundcard_by_name(self.client,
292               self.name_speaker)
293
294    def check_cras_speaker(self):
295        """
296        Verify cras server detects speaker.
297        """
298        if not self.speaker:
299            return True, None
300        return audio_helper.check_speaker_exist_cras(self.client,
301               self.name_speaker)
302
303    def check_cras_mic(self):
304        """
305        Verify cras server detects microphone.
306        """
307        if not self.speaker:
308            return True, None
309        return audio_helper.check_microphone_exist_cras(self.client,
310               self.name_speaker)
311
312    def check_cras_mic_mute(self):
313        """
314        Verify cras shows mic muted or unmuted as expected.
315        """
316        if not self.speaker or not self.is_in_meet:
317            return True, None
318        return audio_helper.check_cras_mic_mute(self.client, self.cfm_facade)
319
320    def check_cras_pspeaker(self):
321        """
322        Verify cras shows correct preferred speaker.
323        """
324        if not self.speaker:
325            return True, None
326        return  audio_helper.check_is_preferred_speaker(self.client,
327                self.name_speaker)
328
329    def check_cras_speaker_vol(self):
330        """
331        Verify cras shows correct volume for speaker.
332        """
333        if not self.speaker or not self.is_in_meet:
334            return True, None
335        return audio_helper.check_default_speaker_volume(self.client,
336               self.cfm_facade)
337
338    def check_cras_pmic(self):
339        """
340        Verify cras shows correct preferred microphone.
341        """
342        if not self.speaker:
343            return True, None
344        return  audio_helper.check_is_preferred_mic(self.client,
345                self.name_speaker)
346
347    # TODO(mzhuo): add verification for preferred camera
348    def check_prefer_camera(self):
349        """
350        Verify preferred camera is correct.
351        """
352        return True, None
353
354    #TODO(mzhuo): add verification to verify camera is muted or unmuted
355    #in video stack in kernel space.
356    def check_camera_mute(self):
357        """
358        Verify camera is muted or unmuted as expected.
359        """
360        return True, None
361
362    def check_video_stream(self):
363        """
364        Verify camera is streaming or not streaming as expected.
365        """
366        if not self.camera:
367            return True, None
368        return video_helper.check_video_stream(self.client,
369               self.is_camera_muted, self.camera, self.name_camera)
370
371    def check_audio_stream(self):
372        """
373        Verify speaker is streaming or not streaming as expected.
374        """
375        if not self.speaker:
376            return True, None
377        return audio_helper.check_audio_stream(self.client,
378               self.is_in_meet)
379
380    # TODO(mzhuo): Adding verification for speaker in Hotrod App
381    def check_hotrod_speaker(self):
382        """
383        Verify hotrod shows all speakers.
384        """
385        return True, None
386
387    # TODO(mzhuo): Adding verification for mic in Hotrod App
388    def check_hotrod_mic(self):
389        """
390        Verify hotrod shows all microphone.
391        """
392        return True, None
393
394    # TODO(mzhuo): Adding verification for camera in Hotrod App
395    def check_hotrod_camera(self):
396        """
397        Verify hotrod shows all cameras.
398        """
399        return True, None
400
401     # TODO(mzhuo): Adding verification for speaker in Hotrod App
402    def check_hotrod_pspeaker(self):
403        """
404        Verify hotrod selects correct preferred speaker.
405        """
406        return True, None
407
408    # TODO(mzhuo): Adding verification for mic in Hotrod App
409    def check_hotrod_pmic(self):
410        """
411        Verify hotrod selects correct preferred microphone.
412        """
413        return True, None
414
415
416    # TODO(mzhuo): Adding verification for camera in Hotrod App
417    def check_hotrod_pcamera(self):
418        """
419        Verify hotrod selects correct preferred camera.
420        """
421        return True, None
422
423    #TODO(mzhuo): Adding verififaction in hotrod layer for speaker volume
424    def check_hotrod_speaker_vol(self):
425        """
426        Verify hotrod can set volume for speaker.
427        """
428        return True, None
429
430    #TODO(mzhuo): Adding verififaction in hotrod layer for mic mute status
431    def check_hotrod_mic_state(self):
432        """
433        Verify hotrod can mute or unmute microphone.
434        """
435        return True, None
436
437    #TODO(mzhuo): Adding verififaction in hotrod layer for camera status
438    def check_hotrod_camera_state(self):
439        """
440        Verify hotrod can mute or unmute camera.
441        """
442        return True, None
443
444    def check_kernel_errorlog(self):
445        """
446        Check /var/log/message does not contain any element in
447        error_key_words['kernel'].
448        """
449        return cfm_helper.check_log(self.client, self.log_checking_point,
450                                    self.error_key_words, 'kernel',
451                                    'messages')
452
453    def check_chrome_errorlog(self):
454        """
455        Check /var/log/chrome/chrome does not contain any element in
456        error_key_words['chrome'].
457        """
458        return cfm_helper.check_log(self.client, self.log_checking_point,
459                                    self.error_key_words, 'chrome',
460                                    'chrome')
461
462    def check_atrus_errorlog(self):
463        """
464        Check /var/log/atrus.log does not contain any element in
465        error_key_words['atrus'].
466        """
467        if self.current_test in ['gpio_test', 'resetusb_test']:
468            return True, None
469        if not self.name_speaker:
470            return True, None
471        if self.name_speaker not in ATRUS:
472            logging.info('Speaker %s', self.name_speaker)
473            return True, None
474        if cfm_helper.check_is_platform(self.client, 'guado'):
475            return cfm_helper.check_log(self.client, self.log_checking_point,
476                                        self.error_key_words, 'atrus', 'atrus')
477        else:
478            return True, None
479
480    def check_video_errorlog(self):
481        """
482        Check /var/log/message does not contain any element in
483        error_key_words['video'].
484        """
485        return cfm_helper.check_log(self.client, self.log_checking_point,
486                                    self.error_key_words, 'video',
487                                    'messages')
488
489    def check_audio_errorlog(self):
490        """
491        Check /var/log/message does not contain any element in
492        error_key_words['audio'].
493        """
494        return cfm_helper.check_log(self.client, self.log_checking_point,
495                                    self.error_key_words, 'audio',
496                                    'messages')
497
498    def check_usb_errorlog(self):
499        """
500        Check /var/log/message does not contain any element in
501        error_key_words['usb'].
502        """
503        return cfm_helper.check_log(self.client, self.log_checking_point,
504               self.error_key_words, 'usb', 'messages')
505
506    def check_usb_stability(self):
507        """
508        Check if no disruptive test done, USB device should not go offline.
509        """
510        if self.current_test in ['gpio_test', 'reboot_test', 'resetusb_test']:
511            return True, None
512        return cfm_helper.check_log(self.client, self.log_checking_point,
513                                    self.error_key_words,
514                                    'usb_stability', 'messages')
515
516    def check_process_crash(self):
517        """
518        check no process crashing.
519        """
520        test_result, self.cdlines = cfm_helper.check_process_crash(self.client,
521                                self.cdlines)
522        return test_result, str(self.cdlines)
523
524    #TODO(mzhuo): Adding verififaction to check whether there is kernel panic
525    def check_kernel_panic(self):
526        """
527        Check no kernel panic reported.
528        """
529        return True, None
530
531
532    def check_chrome_restarted(self):
533        """
534        Check whether chrome is killed and restarted.
535        """
536        if self.chrome_file == cfm_helper.check_chrome_logfile(self.client):
537            return True, None
538        else:
539            self.chrome_file = cfm_helper.check_chrome_logfile(self.client)
540            return False, 'Chrome is restarted unexpectly.'
541
542    def check_cfm_rebooted(self):
543        """
544        Check whether CfM is rebooted.
545        """
546        logging.info('Last reboot: %s', self.reboot_log)
547        if self.reboot_log == cfm_helper.check_last_reboot(self.client):
548            return True, None
549        else:
550            self.reboot_log = cfm_helper.check_last_reboot(self.client)
551            return False, 'CfM is rebooted unexpectly.'
552
553    def initialize_action_check_config(self, action_config, verification_config,
554                                       fixedmode):
555        """
556        Initialize action list based on control file.
557        @param action_config: dict defines the number of test should be done
558                              for each test
559        @param fixedmode: if True all tests are executed in fixed order;
560                     if False all tests are executed in random order.
561        """
562        self.action_config =  []
563        if action_config['meeting_test'] == 1:
564            self.action_config = ['meeting_test']
565        if not self.camera:
566            action_config['mute_unmute_camera_test'] = 0
567            verification_config['check_v4l2_interface'] = False
568            verification_config['check_video_stream'] = False
569            verification_config['check_video_errorlog'] = False
570        if not self.speaker:
571            if not cfm_helper.check_is_platform(self.client, 'buddy'):
572                action_config['mute_unmute_mic_test'] = 0
573                action_config['speaker_volume_test']  = 0
574            verification_config['check_audio_card'] = False
575            verification_config['check_cras_speaker'] = False
576            verification_config['check_cras_mic'] = False
577            verification_config['check_cras_pspeaker'] = False
578            verification_config['check_cras_pmic'] = False
579            verification_config['check_audio_stream'] = False
580            verification_config['check_audio_errorlog'] = False
581            verification_config['check_cras_speaker_vol'] = False
582            verification_config['check_cras_mic_mute'] = False
583        not_in_meeting_action = ['meeting_test', 'gpio_test', 'reboot_test']
584
585        if fixedmode:
586            for action, nof_times in action_config.iteritems():
587                if not action in not_in_meeting_action:
588                    self.action_config.extend(nof_times * [action])
589        else:
590            for action, nof_times in action_config.iteritems():
591                if not action in not_in_meeting_action and nof_times  > 0:
592                    dup_test = max(1, random.randrange(0, nof_times))
593                    for _ in range(dup_test):
594                        self.action_config.insert(max(1, random.randrange(-1,
595                             len(self.action_config))), action)
596
597        if action_config['meeting_test'] == 1:
598            self.action_config.append('meeting_test')
599
600        for action, nof_times in action_config.iteritems():
601            if action == 'meeting_test':
602                continue
603            if action in not_in_meeting_action and nof_times  > 0:
604                dup_test = max(1, random.randrange(0, nof_times))
605                for _ in range(dup_test):
606                    self.action_config.insert(max(0, random.randrange(-1,
607                         len(self.action_config))), action)
608
609        logging.info('Test list = %s', self.action_config)
610        self.verification_config = [v for v in verification_config.keys()
611                                    if verification_config[v]]
612        logging.info('Verification list = %s', self.verification_config)
613
614
615    def initialize_test(self, test_config, action_config, verification_config,
616                        error_key_words, test_flow_control):
617        """
618        Initialize the list of tests and verifications;
619        and polulate data needed for test:
620            USB devices: which can be retrieved from control file or
621            automatically detected by script;
622            Test loop, meeting mode, meeting code, test flow contro
623            variables.
624        """
625        self.gpio_pause = test_config['gpiopause']
626        self.reboot_timeout =  test_config['reboot_timeout']
627        self.vol_change_step = test_config['vol_change_step']
628        self.vol_change_mode = test_config['vol_change_mode']
629        self.gpio_list = test_config['gpio_list']
630        self.is_meeting = test_config['is_meeting']
631        self.meeting_code = test_config ['meeting_code']
632        self.reboot_min_meets = test_config['reboot_after_min_meets']
633        self.gpio_min_meets = test_config['gpio_after_min_meets']
634        self.run_meeting_test = action_config['meeting_test']
635        self.random = test_flow_control['random_mode']
636        self.recover_on_failure = test_flow_control['recovery_on_fatal_failure']
637        self.error_key_words = error_key_words
638        if test_config['puts']:
639            self.puts = test_config['puts'].split(',')
640        else:
641            self.puts = None
642
643        if verification_config['check_process_crash']:
644            cfm_helper.clear_core_file(self.client)
645
646        self.action_fun = {
647            'gpio_test': self.gpio_test,
648            'meeting_test': self.meeting_test,
649            'reboot_test': self.reboot_test,
650            'reset_usb_test': self.reset_usb_test,
651            'mute_unmute_camera_test': self.mute_unmute_camera_test,
652            'mute_unmute_mic_test': self.mute_unmute_mic_test,
653            'speaker_volume_test': self.speaker_volume_test,
654            'flap_monitor_test': self.flap_monitor_test
655            }
656        self.veri_fun = {
657            'check_usb_enumeration': self.check_usb_enumeration,
658            'check_usb_inf_init': self.check_usb_inf_init,
659            'check_v4l2_interface': self.check_v4l2_interface,
660            'check_audio_card': self.check_audio_card,
661            'check_cras_speaker': self.check_cras_speaker,
662            'check_cras_mic': self.check_cras_mic,
663            'check_cras_pspeaker': self.check_cras_pspeaker,
664            'check_cras_pmic': self.check_cras_pmic,
665            'check_cras_speaker_vol': self.check_cras_speaker_vol,
666            'check_cras_mic_mute': self.check_cras_mic_mute,
667            'check_prefer_camera': self.check_prefer_camera,
668            'check_camera_mute': self.check_camera_mute,
669            'check_audio_stream': self.check_audio_stream,
670            'check_video_stream': self.check_video_stream,
671            'check_hotrod_speaker': self.check_hotrod_speaker,
672            'check_hotrod_mic': self.check_hotrod_mic,
673            'check_hotrod_camera': self.check_hotrod_camera,
674            'check_hotrod_pspeaker': self.check_hotrod_pspeaker,
675            'check_hotrod_pmic': self.check_hotrod_pmic,
676            'check_hotrod_pcamera': self.check_hotrod_pcamera,
677            'check_hotrod_speaker_vol': self.check_hotrod_speaker_vol,
678            'check_hotrod_mic_state': self.check_hotrod_mic_state,
679            'check_hotrod_camera_state': self.check_hotrod_camera_state,
680            'check_usb_errorlog': self.check_usb_errorlog,
681            'check_kernel_errorlog': self.check_kernel_errorlog,
682            'check_video_errorlog': self.check_video_errorlog,
683            'check_audio_errorlog': self.check_audio_errorlog,
684            'check_chrome_errorlog': self.check_chrome_errorlog,
685            'check_atrus_errorlog': self.check_atrus_errorlog,
686            'check_usb_stability': self.check_usb_stability,
687            'check_process_crash': self.check_process_crash,
688            'check_kernel_panic': self.check_kernel_panic,
689            'check_cfm_rebooted':self.check_cfm_rebooted,
690            'check_chrome_restarted':self.check_chrome_restarted
691             }
692
693        self.usb_data = []
694        self.speaker = None
695        self.speaker_volume = None
696        self.camera = None
697        self.name_speaker = None
698        self.mimo_sis = None
699        self.mimo_display = None
700        self.is_in_meet = False
701        self.is_camera_muted = True
702        self.is_mic_muted = False
703        self.meets_last_reboot = 0
704        self.meets_last_gpio = 0
705        self.meet_no = 0
706        self.reboot_no = 0
707        self.gpio_no = 0
708        self.cdlines = CORE_DIR_LINES
709
710        usb_data = cfm_helper.retrieve_usb_devices(self.client)
711        if not usb_data:
712            logging.info('\n\nEnterprise_CFM_Test_Failed.')
713            raise error.TestFail('Fails to find any usb devices on CfM.')
714        peripherals = cfm_helper.extract_peripherals_for_cfm(usb_data)
715        if not peripherals:
716            logging.info('\n\nEnterprise_CFM_Test_Failed.')
717            raise error.TestFail('Fails to find any periphereal on CfM.')
718        if not self.puts:
719            self.puts = peripherals.keys()
720        else:
721            if [put for put in self.puts if not put in peripherals.keys()]:
722                logging.info('Fails to find target device %s', put)
723                logging.info('\nEnterprise_CFM_Test_Failed.')
724                raise error.TestFail('Fails to find device')
725        for _put in self.puts:
726            if _put in get_usb_devices.CAMERA_MAP.keys():
727                self.camera = _put
728            if _put in get_usb_devices.SPEAKER_MAP.keys():
729                self.speaker = _put
730        if self.camera:
731            self.name_camera = get_usb_devices.get_device_prod(self.camera)
732            logging.info('Camera under test: %s %s',
733                          self.camera, self.name_camera)
734        if self.speaker:
735            self.name_speaker = get_usb_devices.get_device_prod(self.speaker)
736            logging.info('Speaker under test: %s %s',
737                          self.speaker, self.name_speaker)
738        if not test_flow_control['skip_cfm_check']:
739            if cfm_helper.check_is_platform(self.client, 'guado'):
740                if not cfm_helper.check_peripherals_for_cfm(peripherals):
741                    logging.info('Sanity Check on CfM fails.')
742                    logging.info('\n\nEnterprise_CFM_Test_Failed.')
743                    raise error.TestFail('Sanity Check on CfM fails.')
744        self.ip_addr = cfm_helper.get_mgmt_ipv4(self.client)
745        logging.info('CfM %s passes sanity check, will start test.',
746                      self.ip_addr)
747
748        self.initialize_action_check_config(action_config,
749                                            verification_config, True)
750
751        if list(set(self.verification_config) & set(LOG_CHECK_LIST)):
752            self.log_checking_point = cfm_helper.find_last_log(self.client,
753                                      self.speaker)
754        self.chrome_file = cfm_helper.check_chrome_logfile(self.client)
755        self.reboot_log = cfm_helper.check_last_reboot(self.client)
756
757
758    def recovery_routine(self, failure_msg):
759        """
760        Telemetry api often returns API timeout, or javascript timeout due to
761        various reasons. To workout the problem before the fix is ready script
762        checks if errmsg from test failure or verification failure has keywords
763        defined in FAILURE_REASON['telemetry']. If yes, script checks whether
764        CfM is rebooted or Chrome browser is rebooted unexpectly. If no, script
765        restarts chrome. If yes no chrome restart is done to preserve valid
766        failure state.
767        @param failure_msg: failure message returned from test failure or
768                            verification failure
769        @return True if recovery is successfully done,
770                False, if recovery is not done, or fails.
771        """
772        loop_result = False
773        to_be_recovered = False
774        if not self.check_chrome_restarted():
775            self.chrome_file = cfm_helper.check_chrome_logfile(self.client)
776            return False
777        if not self.check_cfm_rebooted():
778            self.reboot_log = cfm_helper.check_last_reboot(self.client)
779            return False
780        for _err in FAILURE_REASON['telemetry']:
781            if _err in failure_msg:
782                to_be_recovered = True
783                break
784        if to_be_recovered:
785            logging.info('Restart Chrome to recover......')
786            result, emsg = self.restart_chrome_and_meeting(True)
787            if result:
788                loop_result = True
789                if list(set(self.verification_config) & set(LOG_CHECK_LIST)):
790                    self.log_checking_point = cfm_helper.find_last_log(
791                                              self.client,
792                                              self.speaker)
793        return loop_result
794
795
796    def process_test_result(self, loop_result, loop_no, test_no,
797                            failed_tests, failed_verifications,
798                            failed_tests_loop,
799                            failed_verifications_loop, test_flow_control,
800                            test_config, finished_tests_verifications,
801                            test_done):
802        """
803        Proceess test result data, and print out test report.
804        @params loop_result: True when all tests and verifications pass,
805                             False if any test or verification fails.
806        @param loop_no: sequence number of the loop.
807        @param test_no: sequence number of the test.
808        @param failed_tests: failed tests.
809        @param failed_verifications: failed verifications.
810        @param failed_tests_loop: failed tests in the loop.
811        @param failed_verifications_loop: failed verifications in the loop.
812        @param test_flow_control: variable of flow control defined in
813                                  control file
814        @param test_config: variable of test config defined in control file
815        @param finished_tests_verifications: data to keep track number of
816               tests and verifications performed.
817        @param test_done: True if all loops are done; False otherwose.
818        """
819        if 'reboot_test' in finished_tests_verifications.keys():
820            finished_tests_verifications['reboot_test'] = self.reboot_no
821        if not loop_result and not test_done:
822            logging.info('\n\nVerification_or_Test_Fail on %s for loop NO:'
823                         ' %d, Test: %d', self.ip_addr, loop_no, test_no)
824            if failed_tests_loop:
825                logging.info('----- Failed_Tests: %s', failed_tests_loop)
826            if failed_verifications_loop:
827                logging.info('----- Failed_Verifications: %s',
828                             failed_verifications_loop)
829        if test_flow_control['report']:
830            logging.info('\n\n\n----------------Summary---------------')
831            logging.info('---Loop %d, Test: %d, Meet: %d, Reboot: %d, Gpio: %s',
832                         loop_no, test_no, self.meet_no, self.reboot_no,
833                         self.gpio_no)
834            for testname, counter in failed_tests.iteritems():
835                logging.info('----Test: %s, Failed times: %d, Total Run: %d',
836                           testname, counter,
837                           finished_tests_verifications[testname])
838            for veriname, counter in failed_verifications.iteritems():
839                logging.info('----Verification: %s, Failed times: %d,'
840                             'Total Run: %d',
841                             veriname, counter,
842                             finished_tests_verifications[veriname])
843            if self.random:
844                time.sleep(random.randrange(0, test_config['loop_timeout']))
845            else:
846                 time.sleep(test_config['loop_timeout'])
847        if not test_done:
848            if list(set(self.verification_config) & set(LOG_CHECK_LIST)):
849                self.log_checking_point = cfm_helper.find_last_log(self.client,
850                                          self.speaker)
851
852    def run_once(self, host, run_test_only, test_config, action_config,
853                 verification_config,
854                 error_key_words, test_flow_control):
855        """Runs the test."""
856        logging.info('Start_Test_Script:Enterprise_CFM_Test')
857        self.client = host
858        if test_flow_control['reboot_before_start']:
859            try:
860                self.client.reboot()
861            except Exception as e:
862                errmsg = ('Reboot test fails for %s.'
863                          '% self.ip_addr')
864                logging.exception(errmsg)
865                raise error.TestFail(errmsg)
866            if action_config['meeting_test'] > 0:
867                result, errmsg = meet_helper.restart_chrome(self.cfm_facade,
868                                 test_config['is_meeting'], True)
869                if not result:
870                    logging.info('Restart chrome fails, msg = %s', errmsg)
871                    raise error.TestFail(errmsg)
872
873        self.initialize_test(test_config, action_config, verification_config,
874                              error_key_words, test_flow_control)
875        test_no = 0
876        failed_tests = {}
877        failed_verifications = {}
878        finished_tests_verifications = {}
879        test_failure_reason = []
880        verification_failure_reason = []
881
882
883        for loop_no in xrange(1, test_config['repeat'] + 1):
884            logging.info('=============%s:Test_Loop_No:%d=============',
885                         self.ip_addr, loop_no)
886            logging.info('Action list: %s', self.action_config)
887            failed_tests_loop = []
888            failed_verifications_loop = []
889            for test in self.action_config:
890                loop_result = True
891                if not test in finished_tests_verifications.keys():
892                    finished_tests_verifications[test] = 1
893                else:
894                    finished_tests_verifications[test] += 1
895                self.current_test = test
896                logging.info('\nStart_test:%s', test)
897                test_result, test_msg = self.action_fun[test]()
898                test_no += 1
899                if test_result:
900                    logging.info('Test_Result:%s:SUCCESS', test)
901                else:
902                    logging.info('Test_Result:%s:FAILURE:%s', test, test_msg)
903                    test_failure_reason.append(test_msg)
904                    failed_tests_loop.append(test)
905                    loop_result = False
906                    if not test in failed_tests.keys():
907                        failed_tests[test] = 1
908                    else:
909                        failed_tests[test] += 1
910                    logging.info('\n%s:Test_failure:%s:%s', self.ip_addr,
911                                 test, test_msg)
912                    if self.recover_on_failure or self.meets_last_reboot < 1:
913                        loop_result = self.recovery_routine(test_msg)
914                if self.random:
915                    time.sleep(random.randrange(test_config['min_timeout'],
916                                                test_config['action_timeout']))
917                else:
918                    time.sleep(test_config['min_timeout'])
919
920                for verification in self.verification_config:
921                    if not verification in finished_tests_verifications.keys():
922                        finished_tests_verifications[verification] = 1
923                    else:
924                        finished_tests_verifications[verification] += 1
925
926                    logging.info('\nStart_verification:%s', verification)
927                    veri_result, veri_msg = self.veri_fun[verification]()
928                    if veri_result:
929                        logging.info('Verification_Result:%s:SUCCESS',
930                                     verification)
931                    else:
932                        logging.info('Verification_Result:%s:FAILURE:%s',
933                                     verification, veri_msg)
934                        verification_failure_reason.append(veri_msg)
935                        failed_verifications_loop.append(verification)
936                        if not verification in failed_verifications.keys():
937                            failed_verifications[verification] = 1
938                        else:
939                            failed_verifications[verification] += 1
940                        logging.info('%s:Verification_fail:%s:%s',
941                                     self.ip_addr, verification, veri_msg)
942                        loop_result = False
943                        if self.recover_on_failure:
944                            loop_result = self.recovery_routine(veri_msg)
945
946                self.process_test_result(loop_result, loop_no, test_no,
947                                         failed_tests,
948                                         failed_verifications,
949                                         failed_tests_loop,
950                                         failed_verifications_loop,
951                                         test_flow_control,
952                                         test_config,
953                                         finished_tests_verifications, False)
954                if not loop_result:
955                    if test_flow_control['abort_on_failure']:
956                        logging.info('Enterprise_CFM_Test_Failed.')
957                        time.sleep(test_config['debug_timeout'])
958                        logging.info('Enterprise_CFM_Test_Finished.')
959                        raise error.TestFail(
960                            'Test_or_Verification_fails after {}.'.format(test))
961                    else:
962                        logging.info('Enterprise_CFM_Test_Failure_Detected.')
963
964            if self.random:
965                self.initialize_action_check_config(action_config,
966                                                    verification_config, False)
967
968        logging.info('Enterprise_CFM_Test_Finished.')
969        self.process_test_result(loop_result, loop_no, test_no,
970                                 failed_tests,
971                                 failed_verifications,
972                                 failed_tests_loop,
973                                 failed_verifications_loop,
974                                 test_flow_control,
975                                 test_config,
976                                 finished_tests_verifications, True)
977        if test_failure_reason:
978            logging.debug('Test failure reason %s', test_failure_reason)
979        if verification_failure_reason:
980            logging.debug('Verification failure reason %s',
981                         verification_failure_reason)
982