blob: 84e6979d97a5fc3efad617a42425f1cd1cf287c1 [file] [log] [blame]
Chris Masone6fed6462011-10-20 16:36:43 -07001# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import common
Chris Masonefef21382012-01-17 11:16:32 -08006import compiler, logging, os, random, re, time, urllib2
Chris Masone6fed6462011-10-20 16:36:43 -07007from autotest_lib.client.common_lib import control_data, error, utils
Chris Masonefef21382012-01-17 11:16:32 -08008from autotest_lib.client.common_lib.cros import dev_server
9
10
11class ControlFileNotFound(Exception):
12 """Raised when a control file cannot be found and/or read."""
13 pass
14
15
16class NoControlFileList(Exception):
17 """Raised when to indicate that a listing can't be done."""
18 pass
Chris Masone6fed6462011-10-20 16:36:43 -070019
20
21class ControlFileGetter(object):
22 """
23 Interface for classes that can list and fetch known control files.
Chris Masone6fed6462011-10-20 16:36:43 -070024 """
25
Chris Masone6fed6462011-10-20 16:36:43 -070026 def __init__(self):
27 pass
28
29
30 def get_control_file_list(self):
31 """
Chris Masonefef21382012-01-17 11:16:32 -080032 Gather a list of paths to control files.
Chris Masone6fed6462011-10-20 16:36:43 -070033
Chris Masonefef21382012-01-17 11:16:32 -080034 @return A list of file paths.
35 @throws NoControlFileList if there is an error while listing.
Chris Masone6fed6462011-10-20 16:36:43 -070036 """
37 pass
38
39
40 def get_control_file_contents(self, test_path):
41 """
42 Given a path to a control file, return its contents.
43
Chris Masonefef21382012-01-17 11:16:32 -080044 @param test_path: the path to the control file.
Chris Masone6fed6462011-10-20 16:36:43 -070045 @return the contents of the control file specified by the path.
Chris Masonefef21382012-01-17 11:16:32 -080046 @throws ControlFileNotFound if the file cannot be retrieved.
Chris Masone6fed6462011-10-20 16:36:43 -070047 """
48 pass
49
50
51 def get_control_file_contents_by_name(self, test_name):
52 """
53 Given the name of a control file, return its contents.
54
Chris Masonefef21382012-01-17 11:16:32 -080055 @param test_name: the name of the test whose control file is desired.
56 @return the contents of the control file specified by the name.
57 @throws ControlFileNotFound if the file cannot be retrieved.
Chris Masone6fed6462011-10-20 16:36:43 -070058 """
59 pass
60
61
Chris Masonefef21382012-01-17 11:16:32 -080062class CacheingControlFileGetter(ControlFileGetter):
63 """Wraps ControlFileGetter to cache the retrieved control file list."""
64 def __init__(self):
65 super(CacheingControlFileGetter, self).__init__()
66 self._files = []
67
68
69 def get_control_file_list(self):
70 """
71 Gather a list of paths to control files.
72
73 Gets a list of control files; populates |self._files| with that list
74 and then returns the paths to all useful files in the list.
75
76 @return A list of file paths.
77 @throws NoControlFileList if there is an error while listing.
78 """
79 self._files = self._get_control_file_list()
80 return self._files
81
82
83 def get_control_file_contents_by_name(self, test_name):
84 """
85 Given the name of a control file, return its contents.
86
87 Searches through previously-compiled list in |self._files| for a
88 test named |test_name| and returns the contents of the control file
89 for that test if it is found.
90
91 @param test_name: the name of the test whose control file is desired.
92 @return the contents of the control file specified by the name.
93 @throws ControlFileNotFound if the file cannot be retrieved.
94 """
95 if not self._files and not self.get_control_file_list():
96 raise ControlFileNotFound('No control files found.')
97 regexp = re.compile(os.path.join(test_name, 'control'))
98 candidates = filter(regexp.search, self._files)
99 if not candidates:
100 raise ControlFileNotFound('No control file for ' + test_name)
101 if len(candidates) > 1:
102 raise ControlFileNotFound(test_name + ' is not unique.')
103 return self.get_control_file_contents(candidates[0])
104
105
106class FileSystemGetter(CacheingControlFileGetter):
107 """
108 Class that can list and fetch known control files from disk.
109
110 @var _CONTROL_PATTERN: control file name format to match.
111 """
112
113 _CONTROL_PATTERN = '^control(?:\..+)?$'
114
115 def __init__(self, paths):
116 """
117 @param paths: base directories to start search.
118 """
119 super(FileSystemGetter, self).__init__()
120 self._paths = paths
121
122
Chris Masone6fed6462011-10-20 16:36:43 -0700123 def _is_useful_file(self, name):
124 return '__init__.py' not in name and '.svn' not in name
125
126
Chris Masonefef21382012-01-17 11:16:32 -0800127 def _get_control_file_list(self):
Chris Masone6fed6462011-10-20 16:36:43 -0700128 """
Chris Masonefef21382012-01-17 11:16:32 -0800129 Gather a list of paths to control files under |self._paths|.
Chris Masone6fed6462011-10-20 16:36:43 -0700130
Chris Masonefef21382012-01-17 11:16:32 -0800131 Searches under |self._paths| for files that match
132 |self._CONTROL_PATTERN|. Populates |self._files| with that list
133 and then returns the paths to all useful files in the list.
Chris Masone6fed6462011-10-20 16:36:43 -0700134
Chris Masonefef21382012-01-17 11:16:32 -0800135 @return A list of files that match |self._CONTROL_PATTERN|.
136 @throws NoControlFileList if we find no files.
Chris Masone6fed6462011-10-20 16:36:43 -0700137 """
138 regexp = re.compile(self._CONTROL_PATTERN)
139 directories = self._paths
140 while len(directories) > 0:
141 directory = directories.pop()
142 if not os.path.exists(directory):
143 continue
144 for name in os.listdir(directory):
145 fullpath = os.path.join(directory, name)
146 if os.path.isfile(fullpath):
147 if regexp.search(name):
148 # if we are a control file
149 self._files.append(fullpath)
150 elif os.path.isdir(fullpath):
151 directories.append(fullpath)
Chris Masonefef21382012-01-17 11:16:32 -0800152 if not self._files:
153 msg = 'No control files under ' + ','.join(self._paths)
154 raise NoControlFileList(msg)
Chris Masone6fed6462011-10-20 16:36:43 -0700155 return [f for f in self._files if self._is_useful_file(f)]
156
157
158 def get_control_file_contents(self, test_path):
Chris Masonefef21382012-01-17 11:16:32 -0800159 """
160 Get the contents of the control file at |test_path|.
161
162 @return The contents of the aforementioned file.
163 @throws ControlFileNotFound if the file cannot be retrieved.
164 """
165 try:
166 return utils.read_file(test_path)
167 except EnvironmentError as (errno, strerror):
168 msg = "Can't retrieve {0}: {1} ({2})".format(test_path,
169 strerror,
170 errno)
171 raise ControlFileNotFound(msg)
Chris Masone6fed6462011-10-20 16:36:43 -0700172
173
Chris Masonefef21382012-01-17 11:16:32 -0800174class DevServerGetter(CacheingControlFileGetter):
175 def __init__(self, build, ds=None):
176 """
177 @param build: The build from which to get control files.
178 @param ds: An existing dev_server.DevServer object to use.
179 """
180 super(DevServerGetter, self).__init__()
181 self._dev_server = ds if ds else dev_server.DevServer()
182 self._build = build
183
184
185 def _get_control_file_list(self):
186 """
187 Gather a list of paths to control files from |self._dev_server|.
188
189 Get a listing of all the control files for |self._build| on
190 |self._dev_server|. Populates |self._files| with that list
191 and then returns paths (under the autotest dir) to them.
192
193 @return A list of control file paths. None on failure.
194 @throws NoControlFileList if there is an error while listing.
195 """
196 try:
197 return self._dev_server.list_control_files(self._build)
198 except urllib2.HTTPError as e:
199 raise NoControlFileList(e)
200
201
202 def get_control_file_contents(self, test_path):
203 """
204 Return the contents of |test_path| from |self._dev_server|.
205
206 Get the contents of the control file at |test_path| for |self._build| on
207 |self._dev_server|.
208
209 @return The contents of |test_path|. None on failure.
210 @throws ControlFileNotFound if the file cannot be retrieved.
211 """
212 try:
213 return self._dev_server.get_control_file(self._build, test_path)
214 except urllib2.HTTPError as e:
215 raise ControlFileNotFound(e)