12fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#!/usr/bin/env python 22fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# Copyright (C) 2010 Google Inc. All rights reserved. 32fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# 42fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# Redistribution and use in source and binary forms, with or without 52fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# modification, are permitted provided that the following conditions 62fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# are met: 72fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# 82fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# 1. Redistributions of source code must retain the above copyright 92fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# notice, this list of conditions and the following disclaimer. 102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# 2. Redistributions in binary form must reproduce the above copyright 112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# notice, this list of conditions and the following disclaimer in the 122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# documentation and/or other materials provided with the distribution. 132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# 142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 252fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockfrom webkitpy.common.system.directoryfileset import DirectoryFileSet 262fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockfrom webkitpy.common.system.zipfileset import ZipFileSet 272fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockimport re 282fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockimport testoutput 292fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockimport urllib 302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 322fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockclass TestOutputSet(object): 332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def __init__(self, name, platform, zip_file, **kwargs): 342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self._name = name 352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self._platform = platform 362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self._zip_file = zip_file 372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self._include_expected = kwargs.get('include_expected', True) 382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block @classmethod 402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def from_zip_url(cls, platform, zip_path): 412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return TestOutputSet('local zip %s builder' % platform, platform, ZipFileSet(zip_path)) 422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block @classmethod 442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def from_zip(cls, platform, zip): 452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return TestOutputSet('local zip %s builder' % platform, platform, zip) 462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block @classmethod 482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def from_zip_map(cls, zip_map): 492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block output_sets = [] 502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block for k, v in zip_map.items(): 512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block output_sets.append(TestOutputSet.from_zip(k, v)) 522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return AggregateTestOutputSet(output_sets) 532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block @classmethod 552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def from_path(self, path, platform=None): 562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return TestOutputSet('local %s builder' % platform, platform, DirectoryFileSet(path)) 572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def name(self): 592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return self._name 602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def set_platform(self, platform): 622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self._platform = platform 632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def files(self): 652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return [self._zip_file.open(filename) for filename in self._zip_file.namelist()] 662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def _extract_output_files(self, name, exact_match): 682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block name_matcher = re.compile(name) 692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block actual_matcher = re.compile(r'-actual\.') 702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block expected_matcher = re.compile(r'-expected\.') 712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block checksum_files = [] 732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block text_files = [] 742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block image_files = [] 752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block for output_file in self.files(): 762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block name_match = name_matcher.search(output_file.name()) 772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block actual_match = actual_matcher.search(output_file.name()) 782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block expected_match = expected_matcher.search(output_file.name()) 792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if not (name_match and (actual_match or (self._include_expected and expected_match))): 802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block continue 812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if output_file.name().endswith('.checksum'): 822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block checksum_files.append(output_file) 832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block elif output_file.name().endswith('.txt'): 842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block text_files.append(output_file) 852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block elif output_file.name().endswith('.png'): 862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block image_files.append(output_file) 872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return (checksum_files, text_files, image_files) 892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def _extract_file_with_name(self, name, files): 912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block for file in files: 922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if file.name() == name: 932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return file 942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return None 952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def _make_output_from_image(self, image_file, checksum_files): 972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block checksum_file_name = re.sub('\.png', '.checksum', image_file.name()) 982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block checksum_file = self._extract_file_with_name(checksum_file_name, checksum_files) 992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return testoutput.ImageTestOutput(self._platform, image_file, checksum_file) 1002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def outputs_for(self, name, **kwargs): 1022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block target_type = kwargs.get('target_type', None) 1032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block exact_match = kwargs.get('exact_match', False) 1042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if re.search(r'\.x?html', name): 1052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block name = name[:name.rindex('.')] 1062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block (checksum_files, text_files, image_files) = self._extract_output_files(name, exact_match) 1082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block outputs = [self._make_output_from_image(image_file, checksum_files) for image_file in image_files] 1102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block outputs += [testoutput.TextTestOutput(self._platform, text_file) for text_file in text_files] 1122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if exact_match: 1142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block outputs = filter(lambda output: output.name() == name, outputs) 1152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block outputs = filter(lambda r: target_type in [None, r.type()], outputs) 1172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return outputs 1192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1212fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockclass AggregateTestOutputSet(object): 1222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """Set of test outputs from a list of builders""" 1232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def __init__(self, builders): 1242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self._builders = builders 1252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def outputs_for(self, name, **kwargs): 1272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return sum([builder.outputs_for(name, **kwargs) for builder in self._builders], []) 1282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def builders(self): 1302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return self._builders 131