1 #!/usr/bin/env python 2 # Copyright (C) 2010 Google Inc. All rights reserved. 3 # 4 # Redistribution and use in source and binary forms, with or without 5 # modification, are permitted provided that the following conditions 6 # are met: 7 # 8 # 1. Redistributions of source code must retain the above copyright 9 # notice, this list of conditions and the following disclaimer. 10 # 2. Redistributions in binary form must reproduce the above copyright 11 # notice, this list of conditions and the following disclaimer in the 12 # documentation and/or other materials provided with the distribution. 13 # 14 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 15 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 18 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 25 from webkitpy.common.system.directoryfileset import DirectoryFileSet 26 from webkitpy.common.system.zipfileset import ZipFileSet 27 import re 28 import testoutput 29 import urllib 30 31 32 class TestOutputSet(object): 33 def __init__(self, name, platform, zip_file, **kwargs): 34 self._name = name 35 self._platform = platform 36 self._zip_file = zip_file 37 self._include_expected = kwargs.get('include_expected', True) 38 39 @classmethod 40 def from_zip_url(cls, platform, zip_path): 41 return TestOutputSet('local zip %s builder' % platform, platform, ZipFileSet(zip_path)) 42 43 @classmethod 44 def from_zip(cls, platform, zip): 45 return TestOutputSet('local zip %s builder' % platform, platform, zip) 46 47 @classmethod 48 def from_zip_map(cls, zip_map): 49 output_sets = [] 50 for k, v in zip_map.items(): 51 output_sets.append(TestOutputSet.from_zip(k, v)) 52 return AggregateTestOutputSet(output_sets) 53 54 @classmethod 55 def from_path(self, path, platform=None): 56 return TestOutputSet('local %s builder' % platform, platform, DirectoryFileSet(path)) 57 58 def name(self): 59 return self._name 60 61 def set_platform(self, platform): 62 self._platform = platform 63 64 def files(self): 65 return [self._zip_file.open(filename) for filename in self._zip_file.namelist()] 66 67 def _extract_output_files(self, name, exact_match): 68 name_matcher = re.compile(name) 69 actual_matcher = re.compile(r'-actual\.') 70 expected_matcher = re.compile(r'-expected\.') 71 72 checksum_files = [] 73 text_files = [] 74 image_files = [] 75 for output_file in self.files(): 76 name_match = name_matcher.search(output_file.name()) 77 actual_match = actual_matcher.search(output_file.name()) 78 expected_match = expected_matcher.search(output_file.name()) 79 if not (name_match and (actual_match or (self._include_expected and expected_match))): 80 continue 81 if output_file.name().endswith('.checksum'): 82 checksum_files.append(output_file) 83 elif output_file.name().endswith('.txt'): 84 text_files.append(output_file) 85 elif output_file.name().endswith('.png'): 86 image_files.append(output_file) 87 88 return (checksum_files, text_files, image_files) 89 90 def _extract_file_with_name(self, name, files): 91 for file in files: 92 if file.name() == name: 93 return file 94 return None 95 96 def _make_output_from_image(self, image_file, checksum_files): 97 checksum_file_name = re.sub('\.png', '.checksum', image_file.name()) 98 checksum_file = self._extract_file_with_name(checksum_file_name, checksum_files) 99 return testoutput.ImageTestOutput(self._platform, image_file, checksum_file) 100 101 def outputs_for(self, name, **kwargs): 102 target_type = kwargs.get('target_type', None) 103 exact_match = kwargs.get('exact_match', False) 104 if re.search(r'\.x?html', name): 105 name = name[:name.rindex('.')] 106 107 (checksum_files, text_files, image_files) = self._extract_output_files(name, exact_match) 108 109 outputs = [self._make_output_from_image(image_file, checksum_files) for image_file in image_files] 110 111 outputs += [testoutput.TextTestOutput(self._platform, text_file) for text_file in text_files] 112 113 if exact_match: 114 outputs = filter(lambda output: output.name() == name, outputs) 115 116 outputs = filter(lambda r: target_type in [None, r.type()], outputs) 117 118 return outputs 119 120 121 class AggregateTestOutputSet(object): 122 """Set of test outputs from a list of builders""" 123 def __init__(self, builders): 124 self._builders = builders 125 126 def outputs_for(self, name, **kwargs): 127 return sum([builder.outputs_for(name, **kwargs) for builder in self._builders], []) 128 129 def builders(self): 130 return self._builders 131