OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/python |
| 2 # Copyright (c) 2012 The Native Client Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 import optparse |
| 7 import os |
| 8 import subprocess |
| 9 import tempfile |
| 10 |
| 11 import corpus_errors |
| 12 import corpus_utils |
| 13 |
| 14 |
| 15 class UnexpectedValidateResult(Exception): |
| 16 pass |
| 17 |
| 18 |
| 19 def ValidateNexe(options, path, src_path, expect_pass): |
| 20 """Run the validator on a nexe, check if the result is expected. |
| 21 |
| 22 Args: |
| 23 options: bag of options. |
| 24 path: path to the nexe. |
| 25 src_path: path to nexe on server. |
| 26 expect_pass: boolean indicating if the nexe is expected to validate. |
| 27 Returns: |
| 28 True if validation matches expectations. |
| 29 """ |
| 30 process = subprocess.Popen( |
| 31 [options.validator, path], |
| 32 stdout=subprocess.PIPE, |
| 33 stderr=subprocess.PIPE) |
| 34 process_stdout, process_stderr = process.communicate() |
| 35 # Check if result is what we expect. |
| 36 did_pass = (process.returncode == 0) |
| 37 if expect_pass != did_pass: |
| 38 if options.verbose: |
| 39 print '-' * 70 |
| 40 print 'Validating: %s' % path |
| 41 print 'From: %s' % src_path |
| 42 print 'Size: %d' % os.path.getsize(path) |
| 43 print 'SHA1: %s' % corpus_utils.Sha1FromFilename(path) |
| 44 print 'Validator: %s' % options.validator |
| 45 print 'Unexpected return code: %s' % process.returncode |
| 46 print '>>> STDOUT' |
| 47 print process_stdout |
| 48 print '>>> STDERR' |
| 49 print process_stderr |
| 50 print '-' * 70 |
| 51 else: |
| 52 print 'Unexpected return code %d on sha1: %s' % ( |
| 53 process.returncode, corpus_utils.Sha1FromFilename(path)) |
| 54 return False |
| 55 return True |
| 56 |
| 57 |
| 58 def TestValidators(options, work_dir): |
| 59 """Test x86 validators on current snapshot. |
| 60 |
| 61 Args: |
| 62 options: bag of options. |
| 63 work_dir: directory to operate in. |
| 64 """ |
| 65 nexe_filename = os.path.join(work_dir, 'test.nexe') |
| 66 list_filename = os.path.join(work_dir, 'naclapps.list') |
| 67 filenames = corpus_utils.DownloadNexeList(list_filename) |
| 68 progress = corpus_utils.Progress(len(filenames)) |
| 69 for filename in filenames: |
| 70 progress.Tally() |
| 71 corpus_utils.PrimeCache(options.cache_dir, filename) |
| 72 # Stop here if downloading only. |
| 73 if options.download_only: |
| 74 continue |
| 75 # Skip if not the right architecture. |
| 76 architecture = corpus_utils.NexeArchitecture( |
| 77 corpus_utils.CachedPath(options.cache_dir, filename)) |
| 78 if architecture != options.architecture: |
| 79 continue |
| 80 # Validate a copy in case validator is mutating. |
| 81 corpus_utils.CopyFromCache(options.cache_dir, filename, nexe_filename) |
| 82 try: |
| 83 result = ValidateNexe( |
| 84 options, nexe_filename, filename, |
| 85 corpus_errors.NexeShouldValidate(filename)) |
| 86 progress.Result(result) |
| 87 if not result and not options.keep_going: |
| 88 break |
| 89 finally: |
| 90 try: |
| 91 os.remove(nexe_filename) |
| 92 except OSError: |
| 93 print 'ERROR - unable to remove %s' % nexe_filename |
| 94 progress.Summary(warn_only=True) |
| 95 |
| 96 |
| 97 def Main(): |
| 98 parser = optparse.OptionParser() |
| 99 parser.add_option( |
| 100 '--download-only', dest='download_only', |
| 101 default=False, action='store_true', |
| 102 help='download to cache without running the tests') |
| 103 parser.add_option( |
| 104 '-k', '--keep-going', dest='keep_going', |
| 105 default=False, action='store_true', |
| 106 help='keep going on failure') |
| 107 parser.add_option( |
| 108 '--validator', dest='validator', |
| 109 help='location of validator executable') |
| 110 parser.add_option( |
| 111 '--arch', dest='architecture', |
| 112 help='architecture of validator') |
| 113 parser.add_option( |
| 114 '-v', '--verbose', dest='verbose', default=False, action='store_true', |
| 115 help='run in verbose mode') |
| 116 parser.add_option( |
| 117 '--cache-dir', dest='cache_dir', |
| 118 default=corpus_utils.DefaultCacheDirectory(), |
| 119 help='directory to cache downloads in') |
| 120 options, args = parser.parse_args() |
| 121 if args: |
| 122 parser.error('unused arguments') |
| 123 if not options.download_only: |
| 124 if not options.validator: |
| 125 parser.error('no validator specified') |
| 126 if not options.architecture: |
| 127 parser.error('no architecture specified') |
| 128 |
| 129 work_dir = tempfile.mkdtemp(suffix='validate_nexes', prefix='tmp') |
| 130 try: |
| 131 TestValidators(options, work_dir) |
| 132 finally: |
| 133 corpus_utils.RemoveDir(work_dir) |
| 134 |
| 135 |
| 136 if __name__ == '__main__': |
| 137 Main() |
OLD | NEW |