system_stub.py revision 23730a6e56a168d1879203e4b3819bb36e3d8f1f
1# Copyright (c) 2012 The Chromium 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
5"""Provides stubs for os, sys and subprocess for testing
6
7This test allows one to test code that itself uses os, sys, and subprocess.
8"""
9
10import os
11import re
12import shlex
13import sys
14
15
16class Override(object):
17  def __init__(self, base_module, module_list):
18    stubs = {'adb_commands': AdbCommandsModuleStub,
19             'cloud_storage': CloudStorageModuleStub,
20             'open': OpenFunctionStub,
21             'os': OsModuleStub,
22             'perf_control': PerfControlModuleStub,
23             'raw_input': RawInputFunctionStub,
24             'subprocess': SubprocessModuleStub,
25             'sys': SysModuleStub,
26             'thermal_throttle': ThermalThrottleModuleStub,
27    }
28    self.adb_commands = None
29    self.os = None
30    self.subprocess = None
31    self.sys = None
32
33    self._base_module = base_module
34    self._overrides = {}
35
36    for module_name in module_list:
37      self._overrides[module_name] = getattr(base_module, module_name, None)
38      setattr(self, module_name, stubs[module_name]())
39      setattr(base_module, module_name, getattr(self, module_name))
40
41    if self.os and self.sys:
42      self.os.path.sys = self.sys
43
44  def __del__(self):
45    assert not len(self._overrides)
46
47  def Restore(self):
48    for module_name, original_module in self._overrides.iteritems():
49      setattr(self._base_module, module_name, original_module)
50    self._overrides = {}
51
52
53class AdbCommandsModuleStub(object):
54# adb not even found
55# android_browser_finder not returning
56  class AdbCommandsStub(object):
57    def __init__(self, module, device):
58      self._module = module
59      self._device = device
60      self.is_root_enabled = True
61
62    def RunShellCommand(self, args):
63      if isinstance(args, basestring):
64        args = shlex.split(args)
65      handler = self._module.shell_command_handlers[args[0]]
66      return handler(args)
67
68    def IsRootEnabled(self):
69      return self.is_root_enabled
70
71    def RestartAdbdOnDevice(self):
72      pass
73
74    def IsUserBuild(self):
75      return False
76
77  def __init__(self):
78    self.attached_devices = []
79    self.shell_command_handlers = {}
80
81    def AdbCommandsStubConstructor(device=None):
82      return AdbCommandsModuleStub.AdbCommandsStub(self, device)
83    self.AdbCommands = AdbCommandsStubConstructor
84
85  @staticmethod
86  def IsAndroidSupported():
87    return True
88
89  def GetAttachedDevices(self):
90    return self.attached_devices
91
92  def SetupPrebuiltTools(self, _):
93    return True
94
95  def CleanupLeftoverProcesses(self):
96    pass
97
98
99class CloudStorageModuleStub(object):
100  INTERNAL_BUCKET = None
101  PUBLIC_BUCKET = None
102
103  class CloudStorageError(Exception):
104    pass
105
106  def __init__(self):
107    self.remote_paths = []
108    self.local_file_hashes = {}
109    self.local_hash_files = {}
110
111  def List(self, _):
112    return self.remote_paths
113
114  def Insert(self, bucket, remote_path, local_path):
115    pass
116
117  def CalculateHash(self, file_path):
118    return self.local_file_hashes[file_path]
119
120  def ReadHash(self, hash_path):
121    return self.local_hash_files[hash_path]
122
123
124class OpenFunctionStub(object):
125  class FileStub(object):
126    def __init__(self, data):
127      self._data = data
128
129    def __enter__(self):
130      return self
131
132    def __exit__(self, *args):
133      pass
134
135    def read(self, size=None):
136      if size:
137        return self._data[:size]
138      else:
139        return self._data
140
141  def __init__(self):
142    self.files = {}
143
144  def __call__(self, name, *args, **kwargs):
145    return OpenFunctionStub.FileStub(self.files[name])
146
147
148class OsModuleStub(object):
149  class OsPathModuleStub(object):
150    def __init__(self, sys_module):
151      self.sys = sys_module
152      self.files = []
153
154    def exists(self, path):
155      return path in self.files
156
157    def isfile(self, path):
158      return path in self.files
159
160    def join(self, *paths):
161      def IsAbsolutePath(path):
162        if self.sys.platform.startswith('win'):
163          return re.match('[a-zA-Z]:\\\\', path)
164        else:
165          return path.startswith('/')
166
167      # Per Python specification, if any component is an absolute path,
168      # discard previous components.
169      for index, path in reversed(list(enumerate(paths))):
170        if IsAbsolutePath(path):
171          paths = paths[index:]
172          break
173
174      if self.sys.platform.startswith('win'):
175        tmp = os.path.join(*paths)
176        return tmp.replace('/', '\\')
177      else:
178        tmp = os.path.join(*paths)
179        return tmp.replace('\\', '/')
180
181    @staticmethod
182    def expanduser(path):
183      return os.path.expanduser(path)
184
185    @staticmethod
186    def dirname(path):
187      return os.path.dirname(path)
188
189    @staticmethod
190    def splitext(path):
191      return os.path.splitext(path)
192
193  X_OK = os.X_OK
194
195  def __init__(self, sys_module=sys):
196    self.path = OsModuleStub.OsPathModuleStub(sys_module)
197    self.display = ':0'
198    self.local_app_data = None
199    self.program_files = None
200    self.program_files_x86 = None
201    self.devnull = os.devnull
202
203  def access(self, path, _):
204    return path in self.path.files
205
206  def getenv(self, name):
207    if name == 'DISPLAY':
208      return self.display
209    elif name == 'LOCALAPPDATA':
210      return self.local_app_data
211    elif name == 'PROGRAMFILES':
212      return self.program_files
213    elif name == 'PROGRAMFILES(X86)':
214      return self.program_files_x86
215    raise Exception('Unsupported getenv')
216
217
218class PerfControlModuleStub(object):
219  class PerfControlStub(object):
220    def __init__(self, adb):
221      pass
222
223  def __init__(self):
224    self.PerfControl = PerfControlModuleStub.PerfControlStub
225
226
227class RawInputFunctionStub(object):
228  def __init__(self):
229    self.input = ''
230
231  def __call__(self, name, *args, **kwargs):
232    return self.input
233
234
235class SubprocessModuleStub(object):
236  class PopenStub(object):
237    def __init__(self):
238      self.communicate_result = ('', '')
239
240    def __call__(self, args, **kwargs):
241      return self
242
243    def communicate(self):
244      return self.communicate_result
245
246  def __init__(self):
247    self.Popen = SubprocessModuleStub.PopenStub()
248    self.PIPE = None
249
250  def call(self, *args, **kwargs):
251    pass
252
253
254class SysModuleStub(object):
255  def __init__(self):
256    self.platform = ''
257
258
259class ThermalThrottleModuleStub(object):
260  class ThermalThrottleStub(object):
261    def __init__(self, adb):
262      pass
263
264  def __init__(self):
265    self.ThermalThrottle = ThermalThrottleModuleStub.ThermalThrottleStub
266