Commit d5d36028 authored by Luke Macken's avatar Luke Macken

Merge branch 'develop' of ssh://github.com/lmacken/pyrasite into develop

parents a57b1736 9204781a
[run]
source = pyrasite
omit =
pyrasite/payloads/*
pyrasite/tools/*
[report]
exclude_lines =
pragma: no cover
def __repr__
if __name__ == .__main__.:
language: python
python:
- 2.5
- 2.6
- 2.7
- 3.2
- 3.3
install: python setup.py install
install:
- sudo apt-get install -qq gdb python${TRAVIS_PYTHON_VERSION}-dbg
- python setup.py install
- if [[ $TRAVIS_PYTHON_VERSION != '2.5' ]]; then pip install coveralls --use-mirrors && export HAS_COVERALLS=1; fi
script:
- pip install --use-mirrors unittest2
- sudo apt-get install gdb
- sudo unit2 discover
- nosetests -q --with-coverage --cover-erase --cover-package=pyrasite
after_success:
- if [[ $HAS_COVERALLS ]]; then coveralls; fi
notifications:
irc: "chat.freenode.net#pyrasite"
pyrasite
========
.. image:: https://api.travis-ci.org/lmacken/pyrasite.png?branch=develop
:target: http://travis-ci.org/lmacken/pyrasite
.. image:: https://coveralls.io/repos/lmacken/pyrasite/badge.png?branch=develop
:target: https://coveralls.io/r/lmacken/pyrasite
.. image:: https://pypip.in/v/pyrasite/badge.png
:target: https://crate.io/packages/pyrasite
.. image:: https://pypip.in/d/pyrasite/badge.png
:target: https://crate.io/packages/pyrasite
.. split here
Tools for injecting arbitrary code into running Python processes.
......
......@@ -15,8 +15,12 @@
#
# Copyright (C) 2011-2013 Red Hat, Inc., Luke Macken <lmacken@redhat.com>
import sys
import subprocess
encoding = sys.getdefaultencoding()
def inspect(pid, address):
"Return the value of an object in a given process at the specified address"
cmd = ' '.join([
......@@ -24,6 +28,6 @@ def inspect(pid, address):
'-eval-command="print (PyObject *)%s"' % address,
])
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
for line in p.communicate()[0].split('\n'):
for line in p.communicate()[0].decode(encoding).split('\n'):
if line.startswith('$1 = '):
return line[5:]
# This file is part of pyrasite.
#
# pyrasite is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyrasite is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyrasite. If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2013 Red Hat, Inc., Luke Macken <lmacken@redhat.com>
import os
import sys
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
from pyrasite.main import main
class TestCLI(object):
def test_usage(self):
sys.argv = ['pyrasite']
try:
main()
except SystemExit:
exit_code = sys.exc_info()[1].code
assert exit_code == 1, exit_code
def test_list_payloads(self):
sys.argv = ['pyrasite', '-l']
stdout = sys.stdout
sys.stdout = StringIO()
try:
main()
except SystemExit:
pass
value = sys.stdout.getvalue()
sys.stdout = stdout
assert 'Available payloads:' in value, repr(value)
assert 'helloworld.py' in value, repr(value)
def test_invalid_pid(self):
sys.argv = ['pyrasite', 'foo', 'bar']
stdout = sys.stdout
sys.stdout = StringIO()
try:
main()
except SystemExit:
exit_code = sys.exc_info()[1].code
assert exit_code == 2, exit_code
value = sys.stdout.getvalue()
sys.stdout = stdout
assert 'Error: The first argument must be a pid' in value, repr(value)
def test_invalid_payload(self):
sys.argv = ['pyrasite', str(os.getpid()), 'foo']
stdout = sys.stdout
sys.stdout = StringIO()
try:
main()
except SystemExit:
exit_code = sys.exc_info()[1].code
assert exit_code == 3, exit_code
value = sys.stdout.getvalue()
sys.stdout = stdout
assert "Error: Invalid path or file doesn't exist" in value, repr(value)
def test_injection(self):
sys.argv = ['pyrasite', str(os.getpid()), 'helloworld.py']
stdout = sys.stdout
sys.stdout = StringIO()
main()
value = sys.stdout.getvalue()
sys.stdout = stdout
assert "Hello World!" in value, repr(value)
......@@ -22,10 +22,10 @@ import subprocess
import pyrasite
from pyrasite.tests.utils import generate_program, run_program, stop_program, \
interpreters, unittest
interpreters
class TestCodeInjection(unittest.TestCase):
class TestCodeInjection(object):
def assert_output_contains(self, stdout, stderr, text):
assert text in str(stdout), \
......@@ -81,5 +81,3 @@ class TestCodeInjection(unittest.TestCase):
finally:
os.unlink(program)
if __name__ == '__main__':
unittest.main()
......@@ -18,11 +18,13 @@
import os
import sys
from nose.plugins.skip import SkipTest
import pyrasite
from pyrasite.tests.utils import run_program, generate_program, stop_program, unittest
from pyrasite.tests.utils import run_program, generate_program, stop_program
class TestIPCContextManager(unittest.TestCase):
class TestIPCContextManager(object):
def setUp(self):
self.prog = generate_program()
......@@ -37,7 +39,7 @@ class TestIPCContextManager(unittest.TestCase):
info = sys.version_info
major, minor = info[0], info[1]
if major <= 2 and minor <= 5:
self.skipTest("Context Managers not supported on Python<=2.5")
raise SkipTest("Context Managers not supported on Python<=2.5")
# Otherwise import a module which contains modern syntax.
# It really contains our test case, but we have pushed it out into
......@@ -46,7 +48,7 @@ class TestIPCContextManager(unittest.TestCase):
pyrasite.tests.context_manager_case.context_manager_business(self)
class TestIPC(unittest.TestCase):
class TestIPC(object):
def setUp(self):
self.prog = generate_program()
......@@ -91,6 +93,5 @@ class TestIPC(unittest.TestCase):
def test_repr(self):
assert repr(self.ipc)
if __name__ == '__main__':
unittest.main()
def test_title(self):
assert self.ipc.title
......@@ -22,11 +22,6 @@ import time
import textwrap
import tempfile
import subprocess
import unittest
if sys.version_info[0] == 2:
if sys.version_info[1] < 7:
import unittest2 as unittest
def generate_program(threads=1):
......
......@@ -24,6 +24,8 @@ the value of the object itself.
__version__ = '1.0'
import os
import re
import sys
import urwid
import urwid.raw_display
......@@ -147,6 +149,15 @@ def main():
pyrasite.inject(pid, payload)
filename = '/tmp/pyrasite-%d-objects.json' % pid
# Work around bug caused by meliae dumping unicode strings:
# https://bugs.launchpad.net/meliae/+bug/876810
with open(filename) as sample_file, open(filename + '.tmp', 'w') as output_file:
pattern = re.compile(r"(?<!\\)\\u([dD][0-9a-fA-F]{3,3})")
for line in sample_file:
output_file.write(pattern.sub("#S\g<1>", line))
os.rename(filename + '.tmp', filename)
objects = loader.load(filename)
objects.compute_referrers()
......
......@@ -26,9 +26,6 @@ elif sys.version_info[0] == 2:
requirements.append('argparse')
tests_require = ['nose']
if sys.version_info[0] == 2:
if sys.version_info[1] < 7:
tests_require.append('unittest2')
class build_py(_build_py):
def run(self):
......
......@@ -4,8 +4,8 @@
# and then run "tox" from this directory.
[tox]
envlist = py26, py27
envlist = py26, py27, py33
[testenv]
commands = sudo {envbindir}/unit2 discover
deps = unittest2
commands = nosetests
deps = nose
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment