system_stub.py revision 3551c9c881056c480085172ff9840cab31610854
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"""Provides stubs for os, sys and subprocess for testing
5
6This test allows one to test code that itself uses os, sys, and subprocess.
7"""
8
9import os
10import re
11import shlex
12import sys as real_sys
13
14class Override(object):
15  def __init__(self, base_module, module_list):
16    stubs = {'adb_commands': AdbCommandsModuleStub,
17             'os': OsModuleStub,
18             'subprocess': SubprocessModuleStub,
19             'sys': SysModuleStub,
20    }
21    self.adb_commands = None
22    self.os = None
23    self.subprocess = None
24    self.sys = None
25
26    self._base_module = base_module
27    self._overrides = {}
28
29    for module_name in module_list:
30      self._overrides[module_name] = getattr(base_module, module_name)
31      setattr(self, module_name, stubs[module_name]())
32      setattr(base_module, module_name, getattr(self, module_name))
33
34    if self.os and self.sys:
35      self.os.path.sys = self.sys
36
37  def __del__(self):
38    assert not len(self._overrides)
39
40  def Restore(self):
41    for module_name, original_module in self._overrides.iteritems():
42      setattr(self._base_module, module_name, original_module)
43    self._overrides = {}
44
45class AdbCommandsModuleStub(object):
46# adb not even found
47# android_browser_finder not returning
48  class AdbCommandsStub(object):
49    def __init__(self, module, device):
50      self._module = module
51      self._device = device
52      self.is_root_enabled = True
53
54    def RunShellCommand(self, args):
55      if isinstance(args, basestring):
56        args = shlex.split(args)
57      handler = self._module.shell_command_handlers[args[0]]
58      return handler(args)
59
60    def IsRootEnabled(self):
61      return self.is_root_enabled
62
63  def __init__(self):
64    self.attached_devices = []
65    self.shell_command_handlers = {}
66
67    def AdbCommandsStubConstructor(device=None):
68      return AdbCommandsModuleStub.AdbCommandsStub(self, device)
69    self.AdbCommands = AdbCommandsStubConstructor
70
71  @staticmethod
72  def IsAndroidSupported():
73    return True
74
75  def GetAttachedDevices(self):
76    return self.attached_devices
77
78  @staticmethod
79  def HasForwarder(_=None):
80    return True
81
82class OsModuleStub(object):
83  class OsPathModuleStub(object):
84    def __init__(self, sys_module):
85      self.sys = sys_module
86      self.files = []
87
88    def exists(self, path):
89      return path in self.files
90
91    def isfile(self, path):
92      return path in self.files
93
94    def join(self, *paths):
95      def IsAbsolutePath(path):
96        if self.sys.platform.startswith('win'):
97          return re.match('[a-zA-Z]:\\\\', path)
98        else:
99          return path.startswith('/')
100
101      # Per Python specification, if any component is an absolute path,
102      # discard previous components.
103      for index, path in reversed(list(enumerate(paths))):
104        if IsAbsolutePath(path):
105          paths = paths[index:]
106          break
107
108      if self.sys.platform.startswith('win'):
109        tmp = os.path.join(*paths)
110        return tmp.replace('/', '\\')
111      else:
112        tmp = os.path.join(*paths)
113        return tmp.replace('\\', '/')
114
115    def expanduser(self, filename):
116      return os.path.expanduser(filename)
117
118    def dirname(self, filename): # pylint: disable=R0201
119      return os.path.dirname(filename)
120
121  X_OK = os.X_OK
122
123  def __init__(self, sys_module=real_sys):
124    self.path = OsModuleStub.OsPathModuleStub(sys_module)
125    self.display = ':0'
126    self.local_app_data = None
127    self.program_files = None
128    self.program_files_x86 = None
129    self.devnull = os.devnull
130
131  def access(self, path, _):
132    return path in self.path.files
133
134  def getenv(self, name):
135    if name == 'DISPLAY':
136      return self.display
137    elif name == 'LOCALAPPDATA':
138      return self.local_app_data
139    elif name == 'PROGRAMFILES':
140      return self.program_files
141    elif name == 'PROGRAMFILES(X86)':
142      return self.program_files_x86
143    raise Exception('Unsupported getenv')
144
145class SubprocessModuleStub(object):
146  class PopenStub(object):
147    def __init__(self):
148      self.communicate_result = ('', '')
149
150    def __call__(self, args, **kwargs):
151      return self
152
153    def communicate(self):
154      return self.communicate_result
155
156  def __init__(self):
157    self.Popen = SubprocessModuleStub.PopenStub()
158    self.PIPE = None
159
160  def call(self, *args, **kwargs):
161    raise NotImplementedError()
162
163class SysModuleStub(object):
164  def __init__(self):
165    self.platform = ''
166