181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org""" 281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgTestCommon.py: a testing framework for commands and scripts 381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org with commonly useful error handling 481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgThe TestCommon module provides a simple, high-level interface for writing 681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgtests of executable commands and scripts, especially commands and scripts 781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgthat interact with the file system. All methods throw exceptions and 881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgexit on failure, with useful error messages. This makes a number of 981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgexplicit checks unnecessary, making the test scripts themselves simpler 1081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgto write and easier to read. 1181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 1281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgThe TestCommon class is a subclass of the TestCmd class. In essence, 1381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgTestCommon is a wrapper that handles common TestCmd error conditions in 1481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orguseful ways. You can use TestCommon directly, or subclass it for your 1581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgprogram and add additional (or override) methods to tailor it to your 1681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgprogram's specific needs. Alternatively, the TestCommon class serves 1781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgas a useful example of how to define your own TestCmd subclass. 1881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 1981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgAs a subclass of TestCmd, TestCommon provides access to all of the 2081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgvariables and methods from the TestCmd module. Consequently, you can 2181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orguse any variable or method documented in the TestCmd module without 2281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orghaving to explicitly import TestCmd. 2381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 2481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgA TestCommon environment object is created via the usual invocation: 2581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 2681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org import TestCommon 2781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org test = TestCommon.TestCommon() 2881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 2981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgYou can use all of the TestCmd keyword arguments when instantiating a 3081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgTestCommon object; see the TestCmd documentation for details. 3181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 3281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgHere is an overview of the methods and keyword arguments that are 3381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgprovided by the TestCommon class: 3481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 3581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org test.must_be_writable('file1', ['file2', ...]) 3681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 3781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org test.must_contain('file', 'required text\n') 3881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 3981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org test.must_contain_all_lines(output, lines, ['title', find]) 4081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 4181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org test.must_contain_any_line(output, lines, ['title', find]) 4281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 4381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org test.must_exist('file1', ['file2', ...]) 4481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 4581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org test.must_match('file', "expected contents\n") 4681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 4781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org test.must_not_be_writable('file1', ['file2', ...]) 4881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 49c3836fd58fdfa6f8bb2c70e40e6aaf11dfaa76d5sgk@chromium.org test.must_not_contain('file', 'banned text\n') 50c3836fd58fdfa6f8bb2c70e40e6aaf11dfaa76d5sgk@chromium.org 5181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org test.must_not_contain_any_line(output, lines, ['title', find]) 5281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 5381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org test.must_not_exist('file1', ['file2', ...]) 5481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 5581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org test.run(options = "options to be prepended to arguments", 5681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org stdout = "expected standard output from the program", 5781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org stderr = "expected error output from the program", 5881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org status = expected_status, 5981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org match = match_function) 6081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 6181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgThe TestCommon module also provides the following variables 6281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 6381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org TestCommon.python_executable 6481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org TestCommon.exe_suffix 6581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org TestCommon.obj_suffix 6681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org TestCommon.shobj_prefix 6781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org TestCommon.shobj_suffix 6881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org TestCommon.lib_prefix 6981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org TestCommon.lib_suffix 7081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org TestCommon.dll_prefix 7181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org TestCommon.dll_suffix 7281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 7381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org""" 7481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 75c3836fd58fdfa6f8bb2c70e40e6aaf11dfaa76d5sgk@chromium.org# Copyright 2000-2010 Steven Knight 7681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# This module is free software, and you may redistribute it and/or modify 7781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# it under the same terms as Python itself, so long as this copyright message 7881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# and disclaimer are retained in their original form. 7981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# 8081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 8181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF 8281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 8381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# DAMAGE. 8481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# 8581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 8681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 8781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, 8881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, 8981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 9081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 9181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org__author__ = "Steven Knight <knight at baldmt dot com>" 92c3836fd58fdfa6f8bb2c70e40e6aaf11dfaa76d5sgk@chromium.org__revision__ = "TestCommon.py 0.37.D001 2010/01/11 16:55:50 knight" 93c3836fd58fdfa6f8bb2c70e40e6aaf11dfaa76d5sgk@chromium.org__version__ = "0.37" 9481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 9581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgimport copy 9681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgimport os 9781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgimport os.path 9881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgimport stat 9981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgimport string 10081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgimport sys 10181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgimport types 10281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgimport UserList 10381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 10481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgfrom TestCmd import * 10581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgfrom TestCmd import __all__ 10681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 10781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org__all__.extend([ 'TestCommon', 10881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 'exe_suffix', 10981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 'obj_suffix', 11081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 'shobj_prefix', 11181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 'shobj_suffix', 11281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 'lib_prefix', 11381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 'lib_suffix', 11481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 'dll_prefix', 11581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 'dll_suffix', 11681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org ]) 11781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 11881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# Variables that describe the prefixes and suffixes on this system. 11981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgif sys.platform == 'win32': 12081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org exe_suffix = '.exe' 12181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org obj_suffix = '.obj' 12281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org shobj_suffix = '.obj' 12381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org shobj_prefix = '' 12481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org lib_prefix = '' 12581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org lib_suffix = '.lib' 12681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org dll_prefix = '' 12781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org dll_suffix = '.dll' 12881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgelif sys.platform == 'cygwin': 12981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org exe_suffix = '.exe' 13081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org obj_suffix = '.o' 13181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org shobj_suffix = '.os' 13281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org shobj_prefix = '' 13381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org lib_prefix = 'lib' 13481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org lib_suffix = '.a' 13581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org dll_prefix = '' 13681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org dll_suffix = '.dll' 13781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgelif string.find(sys.platform, 'irix') != -1: 13881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org exe_suffix = '' 13981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org obj_suffix = '.o' 14081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org shobj_suffix = '.o' 14181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org shobj_prefix = '' 14281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org lib_prefix = 'lib' 14381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org lib_suffix = '.a' 14481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org dll_prefix = 'lib' 14581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org dll_suffix = '.so' 14681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgelif string.find(sys.platform, 'darwin') != -1: 14781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org exe_suffix = '' 14881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org obj_suffix = '.o' 14981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org shobj_suffix = '.os' 15081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org shobj_prefix = '' 15181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org lib_prefix = 'lib' 15281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org lib_suffix = '.a' 15381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org dll_prefix = 'lib' 15481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org dll_suffix = '.dylib' 15581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgelif string.find(sys.platform, 'sunos') != -1: 15681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org exe_suffix = '' 15781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org obj_suffix = '.o' 15881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org shobj_suffix = '.os' 15981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org shobj_prefix = 'so_' 16081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org lib_prefix = 'lib' 16181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org lib_suffix = '.a' 16281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org dll_prefix = 'lib' 16381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org dll_suffix = '.dylib' 16481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgelse: 16581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org exe_suffix = '' 16681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org obj_suffix = '.o' 16781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org shobj_suffix = '.os' 16881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org shobj_prefix = '' 16981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org lib_prefix = 'lib' 17081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org lib_suffix = '.a' 17181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org dll_prefix = 'lib' 17281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org dll_suffix = '.so' 17381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 17481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgdef is_List(e): 17581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org return type(e) is types.ListType \ 17681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org or isinstance(e, UserList.UserList) 17781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 17881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgdef is_writable(f): 17981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org mode = os.stat(f)[stat.ST_MODE] 18081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org return mode & stat.S_IWUSR 18181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 18281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgdef separate_files(flist): 18381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org existing = [] 18481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org missing = [] 18581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org for f in flist: 18681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if os.path.exists(f): 18781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org existing.append(f) 18881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org else: 18981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org missing.append(f) 19081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org return existing, missing 19181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 192ca50e4158e519b054520ed2a897503a991889a94thakis@chromium.orgdef _failed(self, status = 0): 193ca50e4158e519b054520ed2a897503a991889a94thakis@chromium.org if self.status is None or status is None: 194ca50e4158e519b054520ed2a897503a991889a94thakis@chromium.org return None 195ca50e4158e519b054520ed2a897503a991889a94thakis@chromium.org try: 196ca50e4158e519b054520ed2a897503a991889a94thakis@chromium.org return _status(self) not in status 197ca50e4158e519b054520ed2a897503a991889a94thakis@chromium.org except TypeError: 198ca50e4158e519b054520ed2a897503a991889a94thakis@chromium.org # status wasn't an iterable 19981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org return _status(self) != status 20054d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.org 201ca50e4158e519b054520ed2a897503a991889a94thakis@chromium.orgdef _status(self): 202ca50e4158e519b054520ed2a897503a991889a94thakis@chromium.org return self.status 20381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 20481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.orgclass TestCommon(TestCmd): 20581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 20681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org # Additional methods from the Perl Test::Cmd::Common module 20781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org # that we may wish to add in the future: 20881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org # 20981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org # $test->subdir('subdir', ...); 21081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org # 21181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org # $test->copy('src_file', 'dst_file'); 21281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 21381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def __init__(self, **kw): 21481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """Initialize a new TestCommon instance. This involves just 21581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org calling the base class initialization, and then changing directory 21681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org to the workdir. 21781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 21881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org apply(TestCmd.__init__, [self], kw) 21981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org os.chdir(self.workdir) 22081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 22181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def must_be_writable(self, *files): 22281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """Ensures that the specified file(s) exist and are writable. 22381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org An individual file can be specified as a list of directory names, 22481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org in which case the pathname will be constructed by concatenating 22581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org them. Exits FAILED if any of the files does not exist or is 22681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org not writable. 22781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 22881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org files = map(lambda x: is_List(x) and apply(os.path.join, x) or x, files) 22981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org existing, missing = separate_files(files) 23081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org unwritable = filter(lambda x, iw=is_writable: not iw(x), existing) 23181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if missing: 23281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print "Missing files: `%s'" % string.join(missing, "', `") 23381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if unwritable: 23481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print "Unwritable files: `%s'" % string.join(unwritable, "', `") 23581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.fail_test(missing + unwritable) 23681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 23781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def must_contain(self, file, required, mode = 'rb'): 23881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """Ensures that the specified file contains the required text. 23981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 24081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org file_contents = self.read(file, mode) 24181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org contains = (string.find(file_contents, required) != -1) 24281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if not contains: 24381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print "File `%s' does not contain required string." % file 24481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print self.banner('Required string ') 24581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print required 24681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print self.banner('%s contents ' % file) 24781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print file_contents 24881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.fail_test(not contains) 24981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 25081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def must_contain_all_lines(self, output, lines, title=None, find=None): 25181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """Ensures that the specified output string (first argument) 25281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org contains all of the specified lines (second argument). 25381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 25481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org An optional third argument can be used to describe the type 25581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org of output being searched, and only shows up in failure output. 25681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 25781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org An optional fourth argument can be used to supply a different 25881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org function, of the form "find(line, output), to use when searching 25981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org for lines in the output. 26081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 26181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if find is None: 26281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org find = lambda o, l: string.find(o, l) != -1 26381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org missing = [] 26481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org for line in lines: 26581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if not find(output, line): 26681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org missing.append(line) 26781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 26881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if missing: 26981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if title is None: 27081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org title = 'output' 27181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org sys.stdout.write("Missing expected lines from %s:\n" % title) 27281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org for line in missing: 27381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org sys.stdout.write(' ' + repr(line) + '\n') 27481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org sys.stdout.write(self.banner(title + ' ')) 27581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org sys.stdout.write(output) 27681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.fail_test() 27781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 27881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def must_contain_any_line(self, output, lines, title=None, find=None): 27981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """Ensures that the specified output string (first argument) 28081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org contains at least one of the specified lines (second argument). 28181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 28281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org An optional third argument can be used to describe the type 28381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org of output being searched, and only shows up in failure output. 28481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 28581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org An optional fourth argument can be used to supply a different 28681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org function, of the form "find(line, output), to use when searching 28781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org for lines in the output. 28881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 28981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if find is None: 29081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org find = lambda o, l: string.find(o, l) != -1 29181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org for line in lines: 29281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if find(output, line): 29381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org return 29481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 29581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if title is None: 29681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org title = 'output' 29781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org sys.stdout.write("Missing any expected line from %s:\n" % title) 29881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org for line in lines: 29981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org sys.stdout.write(' ' + repr(line) + '\n') 30081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org sys.stdout.write(self.banner(title + ' ')) 30181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org sys.stdout.write(output) 30281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.fail_test() 30381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 30481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def must_contain_lines(self, lines, output, title=None): 30581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org # Deprecated; retain for backwards compatibility. 30681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org return self.must_contain_all_lines(output, lines, title) 30781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 30881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def must_exist(self, *files): 30981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """Ensures that the specified file(s) must exist. An individual 31081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org file be specified as a list of directory names, in which case the 31181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org pathname will be constructed by concatenating them. Exits FAILED 31281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if any of the files does not exist. 31381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 31481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org files = map(lambda x: is_List(x) and apply(os.path.join, x) or x, files) 31581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org missing = filter(lambda x: not os.path.exists(x), files) 31681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if missing: 31781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print "Missing files: `%s'" % string.join(missing, "', `") 31881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.fail_test(missing) 31981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 32081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def must_match(self, file, expect, mode = 'rb'): 32181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """Matches the contents of the specified file (first argument) 32281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org against the expected contents (second argument). The expected 32381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org contents are a list of lines or a string which will be split 32481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org on newlines. 32581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 32681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org file_contents = self.read(file, mode) 32781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org try: 32881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.fail_test(not self.match(file_contents, expect)) 32981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org except KeyboardInterrupt: 33081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org raise 33181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org except: 33281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print "Unexpected contents of `%s'" % file 33381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.diff(expect, file_contents, 'contents ') 33481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org raise 33581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 33684f26de1771168933a19776955b0713d3b5892b1bradnelson@google.com def must_not_contain(self, file, banned, mode = 'rb'): 33784f26de1771168933a19776955b0713d3b5892b1bradnelson@google.com """Ensures that the specified file doesn't contain the banned text. 33884f26de1771168933a19776955b0713d3b5892b1bradnelson@google.com """ 33984f26de1771168933a19776955b0713d3b5892b1bradnelson@google.com file_contents = self.read(file, mode) 34084f26de1771168933a19776955b0713d3b5892b1bradnelson@google.com contains = (string.find(file_contents, banned) != -1) 34184f26de1771168933a19776955b0713d3b5892b1bradnelson@google.com if contains: 34284f26de1771168933a19776955b0713d3b5892b1bradnelson@google.com print "File `%s' contains banned string." % file 34384f26de1771168933a19776955b0713d3b5892b1bradnelson@google.com print self.banner('Banned string ') 34484f26de1771168933a19776955b0713d3b5892b1bradnelson@google.com print banned 34584f26de1771168933a19776955b0713d3b5892b1bradnelson@google.com print self.banner('%s contents ' % file) 34684f26de1771168933a19776955b0713d3b5892b1bradnelson@google.com print file_contents 347c3836fd58fdfa6f8bb2c70e40e6aaf11dfaa76d5sgk@chromium.org self.fail_test(contains) 34884f26de1771168933a19776955b0713d3b5892b1bradnelson@google.com 34981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def must_not_contain_any_line(self, output, lines, title=None, find=None): 35081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """Ensures that the specified output string (first argument) 35181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org does not contain any of the specified lines (second argument). 35281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 35381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org An optional third argument can be used to describe the type 35481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org of output being searched, and only shows up in failure output. 35581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 35681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org An optional fourth argument can be used to supply a different 35781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org function, of the form "find(line, output), to use when searching 35881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org for lines in the output. 35981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 36081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if find is None: 36181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org find = lambda o, l: string.find(o, l) != -1 36281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org unexpected = [] 36381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org for line in lines: 36481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if find(output, line): 36581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org unexpected.append(line) 36681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 36781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if unexpected: 36881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if title is None: 36981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org title = 'output' 37081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org sys.stdout.write("Unexpected lines in %s:\n" % title) 37181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org for line in unexpected: 37281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org sys.stdout.write(' ' + repr(line) + '\n') 37381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org sys.stdout.write(self.banner(title + ' ')) 37481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org sys.stdout.write(output) 37581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.fail_test() 37681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 37781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def must_not_contain_lines(self, lines, output, title=None): 37881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org return self.must_not_contain_any_line(output, lines, title) 37981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 38081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def must_not_exist(self, *files): 38181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """Ensures that the specified file(s) must not exist. 38281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org An individual file be specified as a list of directory names, in 38381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org which case the pathname will be constructed by concatenating them. 38481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org Exits FAILED if any of the files exists. 38581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 38681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org files = map(lambda x: is_List(x) and apply(os.path.join, x) or x, files) 38781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org existing = filter(os.path.exists, files) 38881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if existing: 38981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print "Unexpected files exist: `%s'" % string.join(existing, "', `") 39081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.fail_test(existing) 39181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 39281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def must_not_be_writable(self, *files): 39381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """Ensures that the specified file(s) exist and are not writable. 39481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org An individual file can be specified as a list of directory names, 39581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org in which case the pathname will be constructed by concatenating 39681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org them. Exits FAILED if any of the files does not exist or is 39781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org writable. 39881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 39981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org files = map(lambda x: is_List(x) and apply(os.path.join, x) or x, files) 40081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org existing, missing = separate_files(files) 40181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org writable = filter(is_writable, existing) 40281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if missing: 40381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print "Missing files: `%s'" % string.join(missing, "', `") 40481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if writable: 40581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print "Writable files: `%s'" % string.join(writable, "', `") 40681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.fail_test(missing + writable) 40781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 40881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def _complete(self, actual_stdout, expected_stdout, 40981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org actual_stderr, expected_stderr, status, match): 41081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 41181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org Post-processes running a subcommand, checking for failure 41281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org status and displaying output appropriately. 41381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 41481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if _failed(self, status): 41581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org expect = '' 41681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if status != 0: 41781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org expect = " (expected %s)" % str(status) 41881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print "%s returned %s%s" % (self.program, str(_status(self)), expect) 41981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print self.banner('STDOUT ') 42081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print actual_stdout 42181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print self.banner('STDERR ') 42281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print actual_stderr 42381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.fail_test() 42481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if not expected_stdout is None and not match(actual_stdout, expected_stdout): 42581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.diff(expected_stdout, actual_stdout, 'STDOUT ') 42681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if actual_stderr: 42781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print self.banner('STDERR ') 42881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print actual_stderr 42981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.fail_test() 43081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if not expected_stderr is None and not match(actual_stderr, expected_stderr): 43181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print self.banner('STDOUT ') 43281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print actual_stdout 43381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.diff(expected_stderr, actual_stderr, 'STDERR ') 43481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.fail_test() 43581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 43681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def start(self, program = None, 43781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org interpreter = None, 43881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org arguments = None, 43981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org universal_newlines = None, 44081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org **kw): 44181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 44281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org Starts a program or script for the test environment. 44381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 44481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org This handles the "options" keyword argument and exceptions. 44581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 4463afe3277af466c60b6d35a56f578c09a4c5f4c98sbc@chromium.org options = kw.pop('options', None) 4473afe3277af466c60b6d35a56f578c09a4c5f4c98sbc@chromium.org if options: 4483afe3277af466c60b6d35a56f578c09a4c5f4c98sbc@chromium.org if arguments is None: 4493afe3277af466c60b6d35a56f578c09a4c5f4c98sbc@chromium.org arguments = options 4503afe3277af466c60b6d35a56f578c09a4c5f4c98sbc@chromium.org else: 4513afe3277af466c60b6d35a56f578c09a4c5f4c98sbc@chromium.org arguments = options + " " + arguments 4523afe3277af466c60b6d35a56f578c09a4c5f4c98sbc@chromium.org 45381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org try: 45481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org return apply(TestCmd.start, 45581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org (self, program, interpreter, arguments, universal_newlines), 45681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org kw) 45781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org except KeyboardInterrupt: 45881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org raise 45981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org except Exception, e: 46081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print self.banner('STDOUT ') 46181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org try: 46281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print self.stdout() 46381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org except IndexError: 46481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org pass 46581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print self.banner('STDERR ') 46681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org try: 46781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org print self.stderr() 46881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org except IndexError: 46981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org pass 47081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org cmd_args = self.command_args(program, interpreter, arguments) 47181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org sys.stderr.write('Exception trying to execute: %s\n' % cmd_args) 47281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org raise e 47381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 47481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def finish(self, popen, stdout = None, stderr = '', status = 0, **kw): 47581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 47681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org Finishes and waits for the process being run under control of 47781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org the specified popen argument. Additional arguments are similar 47881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org to those of the run() method: 47981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 48081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org stdout The expected standard output from 48181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org the command. A value of None means 48281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org don't test standard output. 48381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 48481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org stderr The expected error output from 48581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org the command. A value of None means 48681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org don't test error output. 48781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 48881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org status The expected exit status from the 48981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org command. A value of None means don't 49081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org test exit status. 49181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 49281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org apply(TestCmd.finish, (self, popen,), kw) 49381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org match = kw.get('match', self.match) 49481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self._complete(self.stdout(), stdout, 49581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.stderr(), stderr, status, match) 49681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 49781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def run(self, options = None, arguments = None, 49881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org stdout = None, stderr = '', status = 0, **kw): 49981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """Runs the program under test, checking that the test succeeded. 50081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 50181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org The arguments are the same as the base TestCmd.run() method, 50281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org with the addition of: 50381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 50481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org options Extra options that get appended to the beginning 50581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org of the arguments. 50681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 50781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org stdout The expected standard output from 50881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org the command. A value of None means 50981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org don't test standard output. 51081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 51181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org stderr The expected error output from 51281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org the command. A value of None means 51381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org don't test error output. 51481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 51581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org status The expected exit status from the 51681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org command. A value of None means don't 51781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org test exit status. 51881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 51981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org By default, this expects a successful exit (status = 0), does 52081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org not test standard output (stdout = None), and expects that error 52181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org output is empty (stderr = ""). 52281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 52381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if options: 52481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if arguments is None: 52581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org arguments = options 52681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org else: 52781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org arguments = options + " " + arguments 52881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org kw['arguments'] = arguments 5293afe3277af466c60b6d35a56f578c09a4c5f4c98sbc@chromium.org match = kw.pop('match', self.match) 53081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org apply(TestCmd.run, [self], kw) 53181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self._complete(self.stdout(), stdout, 53281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.stderr(), stderr, status, match) 53381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 53481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org def skip_test(self, message="Skipping test.\n"): 53581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """Skips a test. 53681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 53781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org Proper test-skipping behavior is dependent on the external 53881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org TESTCOMMON_PASS_SKIPS environment variable. If set, we treat 53981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org the skip as a PASS (exit 0), and otherwise treat it as NO RESULT. 54081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org In either case, we print the specified message as an indication 54181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org that the substance of the test was skipped. 54281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 54381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org (This was originally added to support development under Aegis. 54481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org Technically, skipping a test is a NO RESULT, but Aegis would 54581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org treat that as a test failure and prevent the change from going to 54681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org the next step. Since we ddn't want to force anyone using Aegis 54781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org to have to install absolutely every tool used by the tests, we 54881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org would actually report to Aegis that a skipped test has PASSED 54981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org so that the workflow isn't held up.) 55081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org """ 55181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if message: 55281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org sys.stdout.write(message) 55381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org sys.stdout.flush() 55481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org pass_skips = os.environ.get('TESTCOMMON_PASS_SKIPS') 55581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org if pass_skips in [None, 0, '0']: 55681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org # skip=1 means skip this function when showing where this 55781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org # result came from. They only care about the line where the 55881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org # script called test.skip_test(), not the line number where 55981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org # we call test.no_result(). 56081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.no_result(skip=1) 56181ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org else: 56281ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org # We're under the development directory for this change, 56381ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org # so this is an Aegis invocation; pass the test (exit 0). 56481ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org self.pass_test() 56581ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org 56681ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# Local Variables: 56781ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# tab-width:4 56881ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# indent-tabs-mode:nil 56981ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# End: 57081ac0047a01ca7d34b493fba09e7fd6a5acf09c5sgk@chromium.org# vim: set expandtab tabstop=4 shiftwidth=4: 571