test_utils.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. # Copyright (C) 2011, 2012 Google Inc.
  2. #
  3. # This file is part of YouCompleteMe.
  4. #
  5. # YouCompleteMe is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # YouCompleteMe is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
  17. from __future__ import unicode_literals
  18. from __future__ import print_function
  19. from __future__ import division
  20. from __future__ import absolute_import
  21. from future import standard_library
  22. standard_library.install_aliases()
  23. from builtins import * # noqa
  24. from mock import MagicMock
  25. from hamcrest import assert_that, equal_to
  26. import re
  27. import sys
  28. BUFNR_REGEX = re.compile( r"^bufnr\('(.+)', ([0-9]+)\)$" )
  29. BUFWINNR_REGEX = re.compile( r"^bufwinnr\(([0-9]+)\)$" )
  30. BWIPEOUT_REGEX = re.compile( r"^(?:silent! )bwipeout!? ([0-9]+)$" )
  31. # One-and only instance of mocked Vim object. The first 'import vim' that is
  32. # executed binds the vim module to the instance of MagicMock that is created,
  33. # and subsquent assignments to sys.modules[ 'vim' ] don't retrospectively
  34. # update them. The result is that while running the tests, we must assign only
  35. # one instance of MagicMock to sys.modules[ 'vim' ] and always return it.
  36. #
  37. # More explanation is available:
  38. # https://github.com/Valloric/YouCompleteMe/pull/1694
  39. VIM_MOCK = MagicMock()
  40. def MockGetBufferNumber( buffer_filename ):
  41. for buffer in VIM_MOCK.buffers:
  42. if buffer[ 'filename' ] == buffer_filename:
  43. return buffer[ 'number' ]
  44. return -1
  45. def MockGetBufferWindowNumber( buffer_number ):
  46. for buffer in VIM_MOCK.buffers:
  47. if buffer[ 'number' ] == buffer_number and 'window' in buffer:
  48. return buffer[ 'window' ]
  49. return -1
  50. def MockVimEval( value ):
  51. if value == "g:ycm_min_num_of_chars_for_completion":
  52. return 0
  53. if value == "g:ycm_server_python_interpreter":
  54. return ''
  55. if value == "tempname()":
  56. return '_TEMP_FILE_'
  57. if value == "&previewheight":
  58. # Default value from Vim
  59. return 12
  60. match = BUFNR_REGEX.search( value )
  61. if match:
  62. return MockGetBufferNumber( match.group( 1 ) )
  63. match = BUFWINNR_REGEX.search( value )
  64. if match:
  65. return MockGetBufferWindowNumber( int( match.group( 1 ) ) )
  66. raise ValueError( 'Unexpected evaluation: ' + value )
  67. def MockWipeoutBuffer( buffer_number ):
  68. buffers = VIM_MOCK.buffers
  69. for index, buffer in enumerate( buffers ):
  70. if buffer[ 'number' ] == buffer_number:
  71. return buffers.pop( index )
  72. def MockVimCommand( command ):
  73. match = BWIPEOUT_REGEX.search( command )
  74. if match:
  75. return MockWipeoutBuffer( int( match.group( 1 ) ) )
  76. raise RuntimeError( 'Unexpected command: ' + command )
  77. def MockVimModule():
  78. """The 'vim' module is something that is only present when running inside the
  79. Vim Python interpreter, so we replace it with a MagicMock for tests. If you
  80. need to add additional mocks to vim module functions, then use 'patch' from
  81. mock module, to ensure that the state of the vim mock is returned before the
  82. next test. That is:
  83. from ycm.test_utils import MockVimModule
  84. from mock import patch
  85. # Do this once
  86. MockVimModule()
  87. @patch( 'vim.eval', return_value='test' )
  88. @patch( 'vim.command', side_effect=ValueError )
  89. def test( vim_command, vim_eval ):
  90. # use vim.command via vim_command, e.g.:
  91. vim_command.assert_has_calls( ... )
  92. Failure to use this approach may lead to unexpected failures in other
  93. tests."""
  94. VIM_MOCK.buffers = {}
  95. VIM_MOCK.eval = MagicMock( side_effect = MockVimEval )
  96. sys.modules[ 'vim' ] = VIM_MOCK
  97. return VIM_MOCK
  98. class ExtendedMock( MagicMock ):
  99. def assert_has_exact_calls( self, calls, any_order = False ):
  100. self.assert_has_calls( calls, any_order )
  101. assert_that( self.call_count, equal_to( len( calls ) ) )