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 25from webkitpy.common.system.directoryfileset import DirectoryFileSet 26from webkitpy.common.system.zipfileset import ZipFileSet 27import re 28import testoutput 29import urllib 30 31 32class 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 121class 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