Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import copy, logging, os, pprint, re, threading, time, urllib | 5 import copy, logging, os, pprint, re, threading, time, urllib |
| 6 | 6 |
| 7 from autotest_lib.client.bin import site_ui_test | 7 from autotest_lib.client.bin import site_ui_test |
| 8 from autotest_lib.client.common_lib import error, site_httpd, site_ui, utils | 8 from autotest_lib.client.common_lib import error, site_httpd, site_ui, utils |
| 9 | 9 |
| 10 # HTML templates. | 10 # HTML templates. |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 82 <td>%(name)s</td> | 82 <td>%(name)s</td> |
| 83 <td>%(index)d</td> | 83 <td>%(index)d</td> |
| 84 <td>%(channels)d</td> | 84 <td>%(channels)d</td> |
| 85 <td>%(is_hardware)d</td> | 85 <td>%(is_hardware)d</td> |
| 86 <td>%(sample_format)s</td> | 86 <td>%(sample_format)s</td> |
| 87 <td>%(sample_rate)s</td> | 87 <td>%(sample_rate)s</td> |
| 88 <td>%(ports)s</td> | 88 <td>%(ports)s</td> |
| 89 </tr> | 89 </tr> |
| 90 ''' | 90 ''' |
| 91 | 91 |
| 92 _DEVICE_SECTION_ENTRY_PORT_START_TMPL = '''<tr> | |
| 93 <td>%(name)s</td> | |
| 94 <td>%(index)d</td> | |
| 95 <td>%(channels)d</td> | |
| 96 <td>%(is_hardware)d</td> | |
| 97 <td>%(sample_format)s</td> | |
| 98 <td>%(sample_rate)s</td> | |
| 99 ''' | |
| 100 _DEVICE_SECTION_ENTRY_PORT_END_TMPL = '''<td>%s</td> | |
| 101 </tr> | |
| 102 ''' | |
| 103 | |
| 92 _DEVICE_LIST_TEST = ''' | 104 _DEVICE_LIST_TEST = ''' |
| 93 <tr><td><table> <tr> | 105 <tr><td><table> <tr> |
| 94 <td>Device List Looks Correct?</td> | 106 <td>Device List Looks Correct?</td> |
| 95 <td class="action" id="summary"><a href="?test=summary&result=pass">pass</a> | 107 <td class="action" id="summary"><a href="?test=summary&result=pass">pass</a> |
| 96 <a href="?test=summary&result=fail">fail</a> | 108 <a href="?test=summary&result=fail">fail</a> |
| 97 </td> | 109 </td> |
| 98 </tr></table></td></tr> | 110 </tr></table></td></tr> |
| 99 ''' | 111 ''' |
| 100 | 112 |
| 101 _TEST_CONTROL_START = '<table><th>Test description</th><th>Invoke Link</th>' | 113 _TEST_CONTROL_START = '<table><th>Test description</th><th>Invoke Link</th>' |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 204 _STANZA_START_RE = re.compile(' (\*| ) index: (\d+)') | 216 _STANZA_START_RE = re.compile(' (\*| ) index: (\d+)') |
| 205 _NAME_RE = re.compile('\tname:\s+<(.+)>') | 217 _NAME_RE = re.compile('\tname:\s+<(.+)>') |
| 206 _FLAGS_RE = re.compile('\tflags:\s+(.+)') | 218 _FLAGS_RE = re.compile('\tflags:\s+(.+)') |
| 207 _MAX_VOLUME_RE = re.compile('\tvolume steps:\s+(\d+)') | 219 _MAX_VOLUME_RE = re.compile('\tvolume steps:\s+(\d+)') |
| 208 _BASE_VOLUME_RE = re.compile('\tbase volume:\s+(\d+)%') | 220 _BASE_VOLUME_RE = re.compile('\tbase volume:\s+(\d+)%') |
| 209 _SAMPLE_SPEC_RE = re.compile('\tsample spec:\s+(\S+) (\d+)ch (\d+)Hz') | 221 _SAMPLE_SPEC_RE = re.compile('\tsample spec:\s+(\S+) (\d+)ch (\d+)Hz') |
| 210 _CHANNEL_MAP_RE = re.compile('\tchannel map:\s+(.+)') | 222 _CHANNEL_MAP_RE = re.compile('\tchannel map:\s+(.+)') |
| 211 _TOP_LEVEL_RE = re.compile('\t\S') | 223 _TOP_LEVEL_RE = re.compile('\t\S') |
| 212 _PORTS_RE = re.compile('\tports:') | 224 _PORTS_RE = re.compile('\tports:') |
| 213 _PORT_SPEC_RE = re.compile('\t\t(\S+): .* \(priority \d+\)') | 225 _PORT_SPEC_RE = re.compile('\t\t(\S+): .* \(priority \d+\)') |
| 214 | 226 _ACTIVE_PORT_RE = re.compile('\tactive port: <(.+)>') |
| 215 | 227 |
| 216 class ToneThread(threading.Thread): | 228 class ToneThread(threading.Thread): |
| 217 """Wraps the running of test_tones in a thread.""" | 229 """Wraps the running of test_tones in a thread.""" |
| 218 def __init__(self, audio, config): | 230 def __init__(self, audio, config): |
| 219 threading.Thread.__init__(self) | 231 threading.Thread.__init__(self) |
| 220 self.audio = audio | 232 self.audio = audio |
| 221 self.config = config | 233 self.config = config |
| 222 | 234 |
| 223 def run(self): | 235 def run(self): |
| 224 self.audio.run_test_tones(self.config) | 236 self.audio.run_test_tones(self.config) |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 313 | 325 |
| 314 # Run test server. | 326 # Run test server. |
| 315 self._server_root = 'http://localhost:8000/' | 327 self._server_root = 'http://localhost:8000/' |
| 316 self._testServer = site_httpd.HTTPListener(port=8000, | 328 self._testServer = site_httpd.HTTPListener(port=8000, |
| 317 docroot=self.bindir) | 329 docroot=self.bindir) |
| 318 self._testServer.run() | 330 self._testServer.run() |
| 319 site_ui_test.UITest.initialize(self, creds) | 331 site_ui_test.UITest.initialize(self, creds) |
| 320 | 332 |
| 321 | 333 |
| 322 def cleanup(self): | 334 def cleanup(self): |
| 335 for device in self._playback_devices['info']: | |
| 336 if device['is_hardware']: | |
| 337 self.restore_playback_port(device) | |
| 323 self._testServer.stop() | 338 self._testServer.stop() |
| 324 site_ui_test.UITest.cleanup(self) | 339 site_ui_test.UITest.cleanup(self) |
| 325 | 340 |
| 326 | 341 |
| 327 def run_once(self, timeout=10000): | 342 def run_once(self, timeout=10000): |
| 328 self._testServer.add_url_handler( | 343 self._testServer.add_url_handler( |
| 329 '/%s' % _CONTROL_ENDPOINT, | 344 '/%s' % _CONTROL_ENDPOINT, |
| 330 lambda server, form, o=self: o.handle_control(server, form)) | 345 lambda server, form, o=self: o.handle_control(server, form)) |
| 331 self._testServer.add_url_handler( | 346 self._testServer.add_url_handler( |
| 332 '/%s' % _LIST_ENDPOINT, | 347 '/%s' % _LIST_ENDPOINT, |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 439 test_data = { | 454 test_data = { |
| 440 'test': _VOLUME_ENDPOINT, | 455 'test': _VOLUME_ENDPOINT, |
| 441 'device': device_num, | 456 'device': device_num, |
| 442 'port': port_num | 457 'port': port_num |
| 443 } | 458 } |
| 444 server.wfile.write( | 459 server.wfile.write( |
| 445 self.get_pass_fail_div(_CONTROL_ENDPOINT, test_data)) | 460 self.get_pass_fail_div(_CONTROL_ENDPOINT, test_data)) |
| 446 | 461 |
| 447 server.wfile.write(_VOLUME_INSTRUCTIONS) | 462 server.wfile.write(_VOLUME_INSTRUCTIONS) |
| 448 | 463 |
| 449 self.render_single_device_summary(server, device) | 464 self.render_single_device_summary(server, device, port) |
| 450 | 465 |
| 451 server.wfile.write(_VOLUME_TEST_DETAILS % device) | 466 server.wfile.write(_VOLUME_TEST_DETAILS % device) |
| 452 if device.has_key('channel_map'): | 467 if device.has_key('channel_map'): |
| 453 server.wfile.write('<p>Channels are: %s' % | 468 server.wfile.write('<p>Channels are: %s' % |
| 454 self._pp.pformat(device['channel_map'])) | 469 self._pp.pformat(device['channel_map'])) |
| 455 | 470 |
| 456 # End Page. | 471 # End Page. |
| 457 server.wfile.write(_HTML_FOOTER) | 472 server.wfile.write(_HTML_FOOTER) |
| 458 | 473 |
| 459 self._running_test = threading.Thread( | 474 self._running_test = threading.Thread( |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 476 test_data = { | 491 test_data = { |
| 477 'test': _PLAYBACK_ENDPOINT, | 492 'test': _PLAYBACK_ENDPOINT, |
| 478 'device': device_num, | 493 'device': device_num, |
| 479 'port': port_num | 494 'port': port_num |
| 480 } | 495 } |
| 481 server.wfile.write( | 496 server.wfile.write( |
| 482 self.get_pass_fail_div(_CONTROL_ENDPOINT, test_data)) | 497 self.get_pass_fail_div(_CONTROL_ENDPOINT, test_data)) |
| 483 | 498 |
| 484 server.wfile.write(_PLAYBACK_INSTRUCTIONS) | 499 server.wfile.write(_PLAYBACK_INSTRUCTIONS) |
| 485 | 500 |
| 486 self.render_single_device_summary(server, device) | 501 self.render_single_device_summary(server, device, port) |
| 487 self.render_channel_test_order(server, device, port) | 502 self.render_channel_test_order(server, device, port) |
| 488 | 503 |
| 489 # End Page. | 504 # End Page. |
| 490 server.wfile.write(_HTML_FOOTER) | 505 server.wfile.write(_HTML_FOOTER) |
| 491 | 506 |
| 492 self.wait_for_current_test() | 507 self.wait_for_current_test() |
| 493 self._running_test = threading.Thread( | 508 self._running_test = threading.Thread( |
| 494 target=lambda d=device,p=port: self.do_playback_test(d,p)) | 509 target=lambda d=device,p=port: self.do_playback_test(d,p)) |
| 495 self._running_test.start() | 510 self._running_test.start() |
| 496 | 511 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 510 test_data = { | 525 test_data = { |
| 511 'test': _RECORD_ENDPOINT, | 526 'test': _RECORD_ENDPOINT, |
| 512 'device': device_num, | 527 'device': device_num, |
| 513 'port': port_num | 528 'port': port_num |
| 514 } | 529 } |
| 515 server.wfile.write( | 530 server.wfile.write( |
| 516 self.get_pass_fail_div(_CONTROL_ENDPOINT, test_data)) | 531 self.get_pass_fail_div(_CONTROL_ENDPOINT, test_data)) |
| 517 | 532 |
| 518 server.wfile.write(_RECORD_INSTRUCTIONS) | 533 server.wfile.write(_RECORD_INSTRUCTIONS) |
| 519 | 534 |
| 520 self.render_single_device_summary(server, device) | 535 self.render_single_device_summary(server, device, port) |
| 521 self.render_channel_test_order(server, device, port) | 536 self.render_channel_test_order(server, device, port) |
| 522 | 537 |
| 523 # End Page. | 538 # End Page. |
| 524 server.wfile.write(_HTML_FOOTER) | 539 server.wfile.write(_HTML_FOOTER) |
| 525 | 540 |
| 526 self.wait_for_current_test() | 541 self.wait_for_current_test() |
| 527 self._running_test = threading.Thread( | 542 self._running_test = threading.Thread( |
| 528 target=lambda d=device,p=port: self.do_record_test(d,p)) | 543 target=lambda d=device,p=port: self.do_record_test(d,p)) |
| 529 self._running_test.start() | 544 self._running_test.start() |
| 530 | 545 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 593 server.wfile.write( | 608 server.wfile.write( |
| 594 self.get_record_item(device_num, port_num)) | 609 self.get_record_item(device_num, port_num)) |
| 595 else: | 610 else: |
| 596 server.wfile.write(self.get_record_item(device_num)) | 611 server.wfile.write(self.get_record_item(device_num)) |
| 597 server.wfile.write(_TEST_CONTROL_END) | 612 server.wfile.write(_TEST_CONTROL_END) |
| 598 | 613 |
| 599 # End Page. | 614 # End Page. |
| 600 server.wfile.write(_HTML_FOOTER) | 615 server.wfile.write(_HTML_FOOTER) |
| 601 | 616 |
| 602 | 617 |
| 603 def render_single_device_summary(self, server, device): | 618 def render_single_device_summary(self, server, device, port): |
| 604 """Output a HTML table with information on a single device""" | 619 """Output a HTML table with information on a single device""" |
| 605 server.wfile.write(_DEVICE_LIST_START) | 620 server.wfile.write(_DEVICE_LIST_START) |
| 606 server.wfile.write(_DEVICE_SECTION_START) | 621 server.wfile.write(_DEVICE_SECTION_START) |
| 607 server.wfile.write(_DEVICE_SECTION_ENTRY_TMPL % device) | 622 server.wfile.write(_DEVICE_SECTION_ENTRY_PORT_START_TMPL % device) |
| 623 server.wfile.write(_DEVICE_SECTION_ENTRY_PORT_END_TMPL % port) | |
| 608 server.wfile.write(_DEVICE_SECTION_END) | 624 server.wfile.write(_DEVICE_SECTION_END) |
|
davejcool
2010/09/04 00:45:44
On the performing test page, it was listing ALL po
| |
| 609 server.wfile.write(_DEVICE_LIST_END) | 625 server.wfile.write(_DEVICE_LIST_END) |
| 610 | 626 |
| 611 | 627 |
| 612 def render_channel_test_order(self, server, device, port): | 628 def render_channel_test_order(self, server, device, port): |
| 613 """Output HTML a table with device channel ordering info.""" | 629 """Output HTML a table with device channel ordering info.""" |
| 614 if port != None: | 630 if port != None: |
| 615 server.wfile.write('<p>Active port on device: %s' % port) | 631 server.wfile.write('<p>Active port on device: %s' % port) |
| 616 else: | 632 else: |
| 617 server.wfile.write('<p>Use default (only) port.') | 633 server.wfile.write('<p>Use default (only) port.') |
| 618 | 634 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 760 current_sink['sample_format'] = m.group(1) | 776 current_sink['sample_format'] = m.group(1) |
| 761 current_sink['channels'] = int(m.group(2)) | 777 current_sink['channels'] = int(m.group(2)) |
| 762 current_sink['sample_rate'] = int(m.group(3)) | 778 current_sink['sample_rate'] = int(m.group(3)) |
| 763 | 779 |
| 764 m = _CHANNEL_MAP_RE.match(line) | 780 m = _CHANNEL_MAP_RE.match(line) |
| 765 if m is not None: | 781 if m is not None: |
| 766 channel_map = [] | 782 channel_map = [] |
| 767 for channel in m.group(1).split(','): | 783 for channel in m.group(1).split(','): |
| 768 channel_map.append(channel) | 784 channel_map.append(channel) |
| 769 current_sink['channel_map'] = channel_map | 785 current_sink['channel_map'] = channel_map |
| 786 | |
| 787 m = _ACTIVE_PORT_RE.match(line) | |
| 788 if m is not None: | |
| 789 current_sink['active_port'] = m.group(1) | |
| 770 | 790 |
| 771 | 791 |
| 772 def parse_device_info(self, device_info_output): | 792 def parse_device_info(self, device_info_output): |
| 773 """Parses the output of a pacmd list-sources or list-sinks call.""" | 793 """Parses the output of a pacmd list-sources or list-sinks call.""" |
| 774 device_info = { 'info' : [] } | 794 device_info = { 'info' : [] } |
| 775 current_device = None | 795 current_device = None |
| 776 port_parsing_mode = False | 796 port_parsing_mode = False |
| 777 for line in device_info_output.split('\n'): | 797 for line in device_info_output.split('\n'): |
| 778 # Leave port_parsing_mode if we find a top-level attribute. | 798 # Leave port_parsing_mode if we find a top-level attribute. |
| 779 if port_parsing_mode and _TOP_LEVEL_RE.match(line) is not None: | 799 if port_parsing_mode and _TOP_LEVEL_RE.match(line) is not None: |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 843 """ | 863 """ |
| 844 self.do_pacmd('set-default-%s %d' % (type, device['index'])) | 864 self.do_pacmd('set-default-%s %d' % (type, device['index'])) |
| 845 logging.info( | 865 logging.info( |
| 846 '* Testing device %d (%s)' % (device['index'], device['name'])) | 866 '* Testing device %d (%s)' % (device['index'], device['name'])) |
| 847 | 867 |
| 848 if port is not None: | 868 if port is not None: |
| 849 self.do_pacmd('set-%s-port %d %s' % (type, device['index'], port)) | 869 self.do_pacmd('set-%s-port %d %s' % (type, device['index'], port)) |
| 850 logging.info('-- setting port %s' % port) | 870 logging.info('-- setting port %s' % port) |
| 851 | 871 |
| 852 | 872 |
| 873 def restore_playback_port(self, device): | |
| 874 """Restores the sink's active port to what it was before testing. | |
| 875 | |
| 876 Args: | |
| 877 device: A dictionary with the parsed device information. | |
| 878 """ | |
| 879 if device['active_port'] is not None: | |
| 880 self.do_pacmd('set-sink-port %d %s' % | |
| 881 (device['index'], device['active_port'])) | |
| 882 logging.info('Restoring device %d to port %s' % | |
| 883 (device['index'], device['active_port'])) | |
| 884 | |
| 885 | |
| 853 def do_signal_test_end(self): | 886 def do_signal_test_end(self): |
| 854 """Play 3 short 1000Hz tones to signal a test case's completion. | 887 """Play 3 short 1000Hz tones to signal a test case's completion. |
| 855 | 888 |
| 856 Playback is done on whatever the current default device is. | 889 Playback is done on whatever the current default device is. |
| 857 """ | 890 """ |
| 858 config = self.default_tone_config() | 891 config = self.default_tone_config() |
| 859 config['tone_length_sec'] = 0.3 | 892 config['tone_length_sec'] = 0.3 |
| 860 self.play_tone(config, 1000) | 893 self.play_tone(config, 1000) |
| 861 self.play_tone(config, 1000) | 894 self.play_tone(config, 1000) |
| 862 self.play_tone(config, 1000) | 895 self.play_tone(config, 1000) |
| 863 | 896 |
| 864 | 897 |
| 865 def do_record_test(self, device, port): | 898 def do_record_test(self, device, port): |
| 866 """Performs a record test for the given device and port. | 899 """Performs a record test for the given device and port. |
| 867 | 900 |
| 868 This sets the default playback device is set to whatever device | 901 This sets the default playback device is set to whatever device |
| 869 is returned first in enumerate_playback_devices(). The playback | 902 is returned first in enumerate_playback_devices(). The playback |
| 870 device is set to use its first port, unmuted, and set to the | 903 device is set to use the default port (active port before running |
| 871 test_volume. | 904 tests), unmuted, and set to the test_volume. |
| 872 | 905 |
| 873 For each channel on the given device and port, a sample is recorded | 906 For each channel on the given device and port, a sample is recorded |
| 874 and played-back at max source volume. Then once again with all | 907 and played-back at max source volume. Then once again with all |
| 875 channel enabled. | 908 channel enabled. |
| 876 | 909 |
| 877 Next, a sample is taken at base volume (no amplification) if | 910 Next, a sample is taken at base volume (no amplification) if |
| 878 that is available, and played back. | 911 that is available, and played back. |
| 879 | 912 |
| 880 This is followed by a sample at 1/2 amplifcation, and again with | 913 This is followed by a sample at 1/2 amplifcation, and again with |
| 881 the record device muted. | 914 the record device muted. |
| 882 | 915 |
| 883 Args: | 916 Args: |
| 884 device: device info dictionary gotten from | 917 device: device info dictionary gotten from |
| 885 enumerate_record devices() | 918 enumerate_record devices() |
| 886 port: String with the name of the port to use on the device. | 919 port: String with the name of the port to use on the device. |
| 887 Can be None if the device does not have multiple ports. | 920 Can be None if the device does not have multiple ports. |
| 888 """ | 921 """ |
| 889 # Configure the playback device to something normal. | 922 # Configure the playback device to something normal. |
| 890 playback_device = self._playback_devices['info'][0] | 923 playback_device = self._playback_devices['info'][0] |
| 891 playback_volume = self.get_test_volume(playback_device) | 924 playback_volume = self.get_test_volume(playback_device) |
| 892 playback_port = None | 925 playback_port = None |
|
davejcool
2010/09/04 00:45:44
Setting playback port the the system default, most
| |
| 893 if len(playback_device['ports']): | 926 if playback_device['active_port'] is not None: |
| 927 self.restore_playback_port(playback_device) | |
| 928 elif len(playback_device['ports']): | |
| 894 playback_port = playback_device['ports'][0] | 929 playback_port = playback_device['ports'][0] |
| 895 self.set_default_device_and_port('sink', playback_device, | 930 self.set_default_device_and_port('sink', playback_device, |
| 896 playback_port) | 931 playback_port) |
| 897 self.do_set_mute('sink', playback_device['index'], False) | 932 self.do_set_mute('sink', playback_device['index'], False) |
| 898 self.do_set_volume('sink', playback_device['index'], playback_volume) | 933 self.do_set_volume('sink', playback_device['index'], playback_volume) |
| 899 | 934 |
| 900 # Set record device. | 935 # Set record device. |
| 901 self.set_default_device_and_port('source', device, port) | 936 self.set_default_device_and_port('source', device, port) |
| 902 | 937 |
| 903 # Set to max hardware amplification volume. | 938 # Set to max hardware amplification volume. |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1242 cmd = ('%(exec)s ' | 1277 cmd = ('%(exec)s ' |
| 1243 '-t %(type)s -h %(frequency)f -l %(tone_length_sec)f ' | 1278 '-t %(type)s -h %(frequency)f -l %(tone_length_sec)f ' |
| 1244 '-c %(channels)d' % args) | 1279 '-c %(channels)d' % args) |
| 1245 if args['active_channel'] is not None: | 1280 if args['active_channel'] is not None: |
| 1246 cmd += ' -a %s' % args['active_channel'] | 1281 cmd += ' -a %s' % args['active_channel'] |
| 1247 if args['type'] == 'tone': | 1282 if args['type'] == 'tone': |
| 1248 logging.info('[tone %dHz]' % args['frequency']) | 1283 logging.info('[tone %dHz]' % args['frequency']) |
| 1249 elif args['type'] == 'scale': | 1284 elif args['type'] == 'scale': |
| 1250 logging.info('[A# harmonic minor scale]') | 1285 logging.info('[A# harmonic minor scale]') |
| 1251 utils.system(self.pacmd(cmd)) | 1286 utils.system(self.pacmd(cmd)) |
| OLD | NEW |