system_stub.py revision 868fa2fe829687343ffae624259930155e16dbd8
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 join(self, *paths):
92      def IsAbsolutePath(path):
93        if self.sys.platform.startswith('win'):
94          return re.match('[a-zA-Z]:\\\\', path)
95        else:
96          return path.startswith('/')
97
98      # Per Python specification, if any component is an absolute path,
99      # discard previous components.
100      for index, path in reversed(list(enumerate(paths))):
101        if IsAbsolutePath(path):
102          paths = paths[index:]
103          break
104
105      if self.sys.platform.startswith('win'):
106        tmp = os.path.join(*paths)
107        return tmp.replace('/', '\\')
108      else:
109        tmp = os.path.join(*paths)
110        return tmp.replace('\\', '/')
111
112    def expanduser(self, filename):
113      return os.path.expanduser(filename)
114
115    def dirname(self, filename): # pylint: disable=R0201
116      return os.path.dirname(filename)
117
118  def __init__(self, sys_module=real_sys):
119    self.path = OsModuleStub.OsPathModuleStub(sys_module)
120    self.display = ':0'
121    self.local_app_data = None
122    self.program_files = None
123    self.program_files_x86 = None
124    self.devnull = os.devnull
125
126  def getenv(self, name):
127    if name == 'DISPLAY':
128      return self.display
129    elif name == 'LOCALAPPDATA':
130      return self.local_app_data
131    elif name == 'PROGRAMFILES':
132      return self.program_files
133    elif name == 'PROGRAMFILES(X86)':
134      return self.program_files_x86
135    raise Exception('Unsupported getenv')
136
137class SubprocessModuleStub(object):
138  class PopenStub(object):
139    def __init__(self):
140      self.communicate_result = ('', '')
141
142    def __call__(self, args, **kwargs):
143      return self
144
145    def communicate(self):
146      return self.communicate_result
147
148  def __init__(self):
149    self.Popen = SubprocessModuleStub.PopenStub()
150    self.PIPE = None
151
152  def call(self, *args, **kwargs):
153    raise NotImplementedError()
154
155class SysModuleStub(object):
156  def __init__(self):
157    self.platform = ''
158