Skip to content

Commit

Permalink
Eliminate use of mox in favor of mock.
Browse files Browse the repository at this point in the history
Testing Done:
Locally green:
```
./pants test \
    tests/python/pants_test/{base:hash_utils,process,util:dirutil}
```

CI went green here:
  https://travis-ci.org/pantsbuild/pants/builds/151082843

Bugs closed: 3760

Reviewed at https://rbcommons.com/s/twitter/r/4143/
  • Loading branch information
jsirois committed Aug 10, 2016
1 parent 5052753 commit db053de
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 79 deletions.
1 change: 0 additions & 1 deletion 3rdparty/python/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ futures==3.0.5
lmdb==0.89
Markdown==2.1.1
mock==1.3.0
mox==0.5.3
pathspec==0.3.4
pep8==1.6.2
pex==1.1.13
Expand Down
2 changes: 1 addition & 1 deletion examples/src/python/example/3rdparty_py.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ E.g, your `3rdparty/python/BUILD` file might look like:

...with `3rdparty/python/requirements.txt` like:

!inc[end-before=mox](../../../../3rdparty/python/requirements.txt)
!inc[end-before=pathspec](../../../../3rdparty/python/requirements.txt)

`python_requirements` defines a named target for each line in the
`requirements.txt` line. For example, a line like `ansicolors==1.0.2` in
Expand Down
2 changes: 0 additions & 2 deletions tests/python/pants_test/base/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,8 @@ python_tests(
name = 'hash_utils',
sources = ['test_hash_utils.py'],
dependencies = [
'3rdparty/python:mox',
'src/python/pants/base:hash_utils',
'src/python/pants/util:contextutil',
'tests/python/pants_test:base_test',
]
)

Expand Down
26 changes: 9 additions & 17 deletions tests/python/pants_test/base/test_hash_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,30 @@
from __future__ import (absolute_import, division, generators, nested_scopes, print_function,
unicode_literals, with_statement)

import hashlib
import math

import mox
import unittest

from pants.base.hash_utils import Sharder, hash_all, hash_file
from pants.util.contextutil import temporary_file


class TestHashUtils(mox.MoxTestBase):

def setUp(self):
super(TestHashUtils, self).setUp()
self.digest = self.mox.CreateMockAnything()
class TestHashUtils(unittest.TestCase):

def test_hash_all(self):
self.digest.update('jake')
self.digest.update('jones')
self.digest.hexdigest().AndReturn('42')
self.mox.ReplayAll()

self.assertEqual('42', hash_all(['jake', 'jones'], digest=self.digest))
expected_hash = hashlib.md5()
expected_hash.update('jakejones')
self.assertEqual(expected_hash.hexdigest(), hash_all(['jake', 'jones'], digest=hashlib.md5()))

def test_hash_file(self):
self.digest.update('jake jones')
self.digest.hexdigest().AndReturn('1137')
self.mox.ReplayAll()
expected_hash = hashlib.md5()
expected_hash.update('jake jones')

with temporary_file() as fd:
fd.write('jake jones')
fd.close()

self.assertEqual('1137', hash_file(fd.name, digest=self.digest))
self.assertEqual(expected_hash.hexdigest(), hash_file(fd.name, digest=hashlib.md5()))

def test_compute_shard(self):
# Spot-check a couple of values, to make sure compute_shard doesn't do something
Expand Down
2 changes: 1 addition & 1 deletion tests/python/pants_test/process/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ python_tests(
name = 'process',
sources = globs('*.py'),
dependencies = [
'3rdparty/python:mox',
'3rdparty/python:mock',
'3rdparty/python:six',
'src/python/pants/process',
]
Expand Down
81 changes: 46 additions & 35 deletions tests/python/pants_test/process/test_xargs.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,82 +7,93 @@

import errno
import os
import unittest

import mox
import mock

from pants.process.xargs import Xargs


class XargsTest(mox.MoxTestBase):
class XargsTest(unittest.TestCase):
def setUp(self):
super(XargsTest, self).setUp()
self.call = self.mox.CreateMockAnything()
self.call = mock.Mock()
self.xargs = Xargs(self.call)

def test_execute_nosplit_success(self):
self.call(['one', 'two', 'three', 'four']).AndReturn(0)
self.mox.ReplayAll()
self.call.return_value = 0

self.assertEqual(0, self.xargs.execute(['one', 'two', 'three', 'four']))

self.call.assert_called_once_with(['one', 'two', 'three', 'four'])

def test_execute_nosplit_raise(self):
exception = Exception()

self.call(['one', 'two', 'three', 'four']).AndRaise(exception)
self.mox.ReplayAll()
self.call.side_effect = exception

with self.assertRaises(Exception) as raised:
self.xargs.execute(['one', 'two', 'three', 'four'])

self.call.assert_called_once_with(['one', 'two', 'three', 'four'])
self.assertIs(exception, raised.exception)

def test_execute_nosplit_fail(self):
self.call(['one', 'two', 'three', 'four']).AndReturn(42)
self.mox.ReplayAll()
self.call.return_value = 42

self.assertEqual(42, self.xargs.execute(['one', 'two', 'three', 'four']))

self.call.assert_called_once_with(['one', 'two', 'three', 'four'])

TOO_BIG = OSError(errno.E2BIG, os.strerror(errno.E2BIG))

def test_execute_split(self):
self.call(['one', 'two', 'three', 'four']).AndRaise(self.TOO_BIG)
self.call(['one', 'two']).AndReturn(0)
self.call(['three', 'four']).AndReturn(0)
self.mox.ReplayAll()
self.call.side_effect = (self.TOO_BIG, 0, 0)

self.assertEqual(0, self.xargs.execute(['one', 'two', 'three', 'four']))

self.assertEqual([mock.call(['one', 'two', 'three', 'four']),
mock.call(['one', 'two']),
mock.call(['three', 'four'])],
self.call.mock_calls)

def test_execute_uneven(self):
self.call(['one', 'two', 'three']).AndRaise(self.TOO_BIG)
# TODO(John Sirois): We really don't care if the 1st call gets 1 argument or 2, we just
# care that all arguments get passed just once via exactly 2 rounds of call - consider making
# this test less brittle to changes in the chunking logic.
self.call(['one']).AndReturn(0)
self.call(['two', 'three']).AndReturn(0)
self.mox.ReplayAll()
self.call.side_effect = (self.TOO_BIG, 0, 0)

self.assertEqual(0, self.xargs.execute(['one', 'two', 'three']))

self.assertEqual(3, self.call.call_count)
self.assertEqual(mock.call(['one', 'two', 'three']),
self.call.mock_calls[0])

self.assertEqual(sorted((mock.call(['one']), mock.call(['two', 'three']))),
sorted(self.call.mock_calls[1:]))

def test_execute_split_multirecurse(self):
self.call(['one', 'two', 'three', 'four']).AndRaise(self.TOO_BIG)
self.call(['one', 'two']).AndRaise(self.TOO_BIG)
self.call(['one']).AndReturn(0)
self.call(['two']).AndReturn(0)
self.call(['three', 'four']).AndReturn(0)
self.mox.ReplayAll()
self.call.side_effect = (self.TOO_BIG, self.TOO_BIG, 0, 0, 0)

self.assertEqual(0, self.xargs.execute(['one', 'two', 'three', 'four']))

self.assertEqual([mock.call(['one', 'two', 'three', 'four']),
mock.call(['one', 'two']),
mock.call(['one']),
mock.call(['two']),
mock.call(['three', 'four'])],
self.call.mock_calls)

def test_execute_split_fail_fast(self):
self.call(['one', 'two', 'three', 'four']).AndRaise(self.TOO_BIG)
self.call(['one', 'two']).AndReturn(42)
self.mox.ReplayAll()
self.call.side_effect = (self.TOO_BIG, 42)

self.assertEqual(42, self.xargs.execute(['one', 'two', 'three', 'four']))

self.assertEqual([mock.call(['one', 'two', 'three', 'four']),
mock.call(['one', 'two'])],
self.call.mock_calls)

def test_execute_split_fail_slow(self):
self.call(['one', 'two', 'three', 'four']).AndRaise(self.TOO_BIG)
self.call(['one', 'two']).AndReturn(0)
self.call(['three', 'four']).AndReturn(42)
self.mox.ReplayAll()
self.call.side_effect = (self.TOO_BIG, 0, 42)

self.assertEqual(42, self.xargs.execute(['one', 'two', 'three', 'four']))

self.assertEqual([mock.call(['one', 'two', 'three', 'four']),
mock.call(['one', 'two']),
mock.call(['three', 'four'])],
self.call.mock_calls)
3 changes: 1 addition & 2 deletions tests/python/pants_test/util/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ python_tests(
sources = ['test_dirutil.py'],
coverage = ['pants.util.dirutil'],
dependencies = [
'3rdparty/python:mox',
'3rdparty/python:mock',
'3rdparty/python:pytest',
'3rdparty/python:six',
'src/python/pants/util:dirutil',
'src/python/pants/util:contextutil',
]
Expand Down
40 changes: 20 additions & 20 deletions tests/python/pants_test/util/test_dirutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@
from __future__ import (absolute_import, division, generators, nested_scopes, print_function,
unicode_literals, with_statement)

import atexit
import errno
import os
import tempfile
import time
import unittest

import mock
import mox
import six

from pants.util import dirutil
Expand All @@ -24,16 +21,16 @@
safe_rm_oldest_items_in_dir, safe_rmtree, touch)


def strict_patch(target, **kwargs):
return mock.patch(target, autospec=True, spec_set=True, **kwargs)


class DirutilTest(unittest.TestCase):

def setUp(self):
self._mox = mox.Mox()
# Ensure we start in a clean state.
_mkdtemp_unregister_cleaner()

def tearDown(self):
self._mox.UnsetStubs()

def test_fast_relpath(self):
def assertRelpath(expected, path, start):
self.assertEquals(expected, fast_relpath(path, start))
Expand All @@ -54,26 +51,26 @@ def test_fast_relpath_invalid(self):
with self.assertRaises(ValueError):
fast_relpath('/a/baseball', '/a/b')

def test_mkdtemp_setup_teardown(self):
@strict_patch('atexit.register')
@strict_patch('os.getpid')
@strict_patch('pants.util.dirutil.safe_rmtree')
@strict_patch('tempfile.mkdtemp')
def test_mkdtemp_setup_teardown(self,
tempfile_mkdtemp,
dirutil_safe_rmtree,
os_getpid,
atexit_register):
def faux_cleaner():
pass

DIR1, DIR2 = 'fake_dir1__does_not_exist', 'fake_dir2__does_not_exist'
self._mox.StubOutWithMock(atexit, 'register')
self._mox.StubOutWithMock(os, 'getpid')
self._mox.StubOutWithMock(tempfile, 'mkdtemp')
self._mox.StubOutWithMock(dirutil, 'safe_rmtree')
atexit.register(faux_cleaner) # Ensure only called once.
tempfile.mkdtemp(dir='1').AndReturn(DIR1)
tempfile.mkdtemp(dir='2').AndReturn(DIR2)
os.getpid().MultipleTimes().AndReturn('unicorn')
dirutil.safe_rmtree(DIR1)
dirutil.safe_rmtree(DIR2)

# Make sure other "pids" are not cleaned.
dirutil._MKDTEMP_DIRS['fluffypants'].add('yoyo')

tempfile_mkdtemp.side_effect = (DIR1, DIR2)
os_getpid.return_value = 'unicorn'
try:
self._mox.ReplayAll()
self.assertEquals(DIR1, dirutil.safe_mkdtemp(dir='1', cleaner=faux_cleaner))
self.assertEquals(DIR2, dirutil.safe_mkdtemp(dir='2', cleaner=faux_cleaner))
self.assertIn('unicorn', dirutil._MKDTEMP_DIRS)
Expand All @@ -86,7 +83,10 @@ def faux_cleaner():
dirutil._MKDTEMP_DIRS.pop('fluffypants', None)
dirutil._mkdtemp_unregister_cleaner()

self._mox.VerifyAll()
atexit_register.assert_called_once_with(faux_cleaner)
self.assertTrue(os_getpid.called)
self.assertEqual([mock.call(dir='1'), mock.call(dir='2')], tempfile_mkdtemp.mock_calls)
self.assertEqual([mock.call(DIR1), mock.call(DIR2)], dirutil_safe_rmtree.mock_calls)

def test_safe_walk(self):
"""Test that directory names are correctly represented as unicode strings"""
Expand Down

0 comments on commit db053de

Please sign in to comment.