This commit is contained in:
Ivan
2022-04-05 11:42:28 +03:00
commit 6dc0eb0fcf
5565 changed files with 1200500 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
# Software License Agreement (BSD License)
#
# Copyright (c) 2011, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Willow Garage, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import sys
def test_myargv():
orig_argv = sys.argv
try:
from rosgraph import myargv
args = myargv()
assert args == sys.argv
assert ['foo', 'bar', 'baz'] == myargv(['foo','bar', 'baz'])
assert ['-foo', 'bar', '-baz'] == myargv(['-foo','bar', '-baz'])
assert ['foo'] == myargv(['foo','bar:=baz'])
assert ['foo'] == myargv(['foo','-bar:=baz'])
finally:
sys.argv = orig_argv

View File

@@ -0,0 +1,327 @@
# Software License Agreement (BSD License)
#
# Copyright (c) 2009, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Willow Garage, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import os
import sys
def test_get_ros_namespace():
if 'ROS_NAMESPACE' in os.environ:
rosns = os.environ['ROS_NAMESPACE']
del os.environ['ROS_NAMESPACE']
else:
rosns = None
sysargv = sys.argv
from rosgraph.names import get_ros_namespace
try:
sys.argv = []
assert '/' == get_ros_namespace()
assert '/' == get_ros_namespace(argv=[])
assert '/' == get_ros_namespace(env={})
assert '/' == get_ros_namespace(env={}, argv=[])
os.environ['ROS_NAMESPACE'] = 'unresolved'
assert '/unresolved/' == get_ros_namespace()
assert '/unresolved/' == get_ros_namespace(env={'ROS_NAMESPACE': 'unresolved'})
sys.argv = ['foo', '__ns:=unresolved_override']
assert '/unresolved_override/' == get_ros_namespace(env={'ROS_NAMESPACE': 'unresolved'})
assert '/override2/' == get_ros_namespace(env={'ROS_NAMESPACE': 'unresolved'}, argv=['foo', '__ns:=override2'])
sys.argv = []
os.environ['ROS_NAMESPACE'] = '/resolved/'
assert '/resolved/' == get_ros_namespace()
assert '/resolved/' == get_ros_namespace(env={'ROS_NAMESPACE': '/resolved'})
del os.environ['ROS_NAMESPACE']
sys.argv = ['foo', '__ns:=unresolved_ns']
assert '/unresolved_ns/' == get_ros_namespace()
assert '/unresolved_ns2/' == get_ros_namespace(argv=['foo', '__ns:=unresolved_ns2'])
sys.argv = ['foo', '__ns:=/resolved_ns/']
assert '/resolved_ns/' == get_ros_namespace()
assert '/resolved_ns2/' == get_ros_namespace(argv=['foo', '__ns:=resolved_ns2'])
finally:
sys.argv = sysargv
# restore
if rosns:
os.environ['ROS_NAMESPACE'] = rosns
def test_make_global_ns():
from rosgraph.names import make_global_ns
for n in ['~foo']:
try:
make_global_ns(n)
assert False, "make_global_ns should fail on %s"%n
except ValueError: pass
assert '/foo/' == make_global_ns('foo')
assert '/' == make_global_ns('')
assert '/foo/' == make_global_ns('/foo')
assert '/foo/' == make_global_ns('/foo/')
assert '/foo/bar/' == make_global_ns('/foo/bar')
assert '/foo/bar/' == make_global_ns('/foo/bar/')
def test_make_caller_id():
from rosgraph.names import make_caller_id
if 'ROS_NAMESPACE' is os.environ:
rosns = os.environ['ROS_NAMESPACE']
del os.environ['ROS_NAMESPACE']
else:
rosns = None
for n in ['~name']:
try:
make_caller_id('~name') # illegal
assert False, "make_caller_id should fail on %s"%n
except ValueError:
pass
assert '/node/' == make_caller_id('node')
assert '/bar/node/' == make_caller_id('bar/node')
assert '/bar/node/' == make_caller_id('/bar/node')
os.environ['ROS_NAMESPACE'] = '/test/'
assert '/test/node/' == make_caller_id('node')
assert '/test/bar/node/' == make_caller_id('bar/node')
assert '/bar/node/' == make_caller_id('/bar/node')
# restore
if rosns:
os.environ['ROS_NAMESPACE'] = rosns
def test_is_global():
from rosgraph.names import is_global
try:
is_global(None)
assert False, "is_global should raise exception on invalid param"
except: pass
tests = ['/', '/global', '/global2']
for t in tests:
assert is_global(t)
fails = ['', 'not_global', 'not/global']
for t in fails:
assert not is_global(t)
def test_is_private():
from rosgraph.names import is_private
try:
is_private(None)
assert False, "is_private should raise exception on invalid param"
except: pass
tests = ['~name', '~name/sub']
for t in tests:
assert is_private(t)
fails = ['', 'not_private', 'not/private', 'not/~private', '/not/~private']
for t in fails:
assert not is_private(t)
def test_namespace():
from rosgraph.names import namespace
try:
namespace(1)
assert False, "1"
except TypeError: pass
try:
namespace(None)
assert False, "None"
except ValueError: pass
assert '/'== namespace('')
assert '/'== namespace('/')
assert '/'== namespace('/foo')
assert '/'== namespace('/foo/')
assert '/foo/'== namespace('/foo/bar')
assert '/foo/'== namespace('/foo/bar/')
assert '/foo/bar/'== namespace('/foo/bar/baz')
assert '/foo/bar/'== namespace('/foo/bar/baz/')
# unicode tests
assert u'/'== namespace(u'')
assert u'/'== namespace(u'/')
assert u'/foo/bar/'== namespace(u'/foo/bar/baz/')
def test_nsjoin():
from rosgraph.names import ns_join
# private and global names cannot be joined
assert '~name' == ns_join('/foo', '~name')
assert '/name' == ns_join('/foo', '/name')
assert '~name' == ns_join('~', '~name')
assert '/name' == ns_join('/', '/name')
# ns can be '~' or '/'
assert '~name' == ns_join('~', 'name')
assert '/name' == ns_join('/', 'name')
assert '/ns/name' == ns_join('/ns', 'name')
assert '/ns/name' == ns_join('/ns/', 'name')
assert '/ns/ns2/name' == ns_join('/ns', 'ns2/name')
assert '/ns/ns2/name' == ns_join('/ns/', 'ns2/name')
# allow ns to be empty
assert 'name' == ns_join('', 'name')
def test_load_mappings():
from rosgraph.names import load_mappings
assert {} == load_mappings([])
assert {} == load_mappings(['foo'])
assert {} == load_mappings([':='])
assert {} == load_mappings([':=:='])
assert {} == load_mappings(['f:='])
assert {} == load_mappings([':=b'])
assert {} == load_mappings(['foo:=bar:=baz'])
# should ignore node param assignments
assert {} == load_mappings(['_foo:=bar'])
assert {'foo': 'bar'} == load_mappings(['foo:=bar'])
# should allow double-underscore names
assert {'__foo': 'bar'} == load_mappings(['__foo:=bar'])
assert {'foo': 'bar'} == load_mappings(['./f', '-x', '--blah', 'foo:=bar'])
assert {'a': '1', 'b': '2', 'c': '3'} == load_mappings(['c:=3', 'c:=', ':=3', 'a:=1', 'b:=2'])
def test_is_legal_name():
from rosgraph.names import is_legal_name
failures = [None,
'foo++', 'foo-bar', '#foo',
'hello\n', '\t', ' name', 'name ',
'f//b',
'1name', 'foo\\']
for f in failures:
assert not is_legal_name(f), f
tests = ['',
'f', 'f1', 'f_', 'f/', 'foo', 'foo_bar', 'foo/bar', 'foo/bar/baz',
'~f', '~a/b/c',
'~/f',
'/a/b/c/d', '/']
for t in tests:
assert is_legal_name(t), "[%s]"%t
def test_is_legal_base_name():
from rosgraph.names import is_legal_base_name
failures = [None, '', 'hello\n', '\t', 'foo++', 'foo-bar', '#foo',
'f/', 'foo/bar', '/', '/a',
'f//b',
'~f', '~a/b/c',
' name', 'name ',
'1name', 'foo\\']
for f in failures:
assert not is_legal_base_name(f), f
tests = ['f', 'f1', 'f_', 'foo', 'foo_bar']
for t in tests:
assert is_legal_base_name(t), "[%s]"%t
def test_resolve_name():
from rosgraph.names import resolve_name
# TODO: test with remappings
tests = [
('', '/', '/'),
('', '/node', '/'),
('', '/ns1/node', '/ns1/'),
('foo', '', '/foo'),
('foo/', '', '/foo'),
('/foo', '', '/foo'),
('/foo/', '', '/foo'),
('/foo', '/', '/foo'),
('/foo/', '/', '/foo'),
('/foo', '/bar', '/foo'),
('/foo/', '/bar', '/foo'),
('foo', '/ns1/ns2', '/ns1/foo'),
('foo', '/ns1/ns2/', '/ns1/foo'),
('foo', '/ns1/ns2/ns3/', '/ns1/ns2/foo'),
('foo/', '/ns1/ns2', '/ns1/foo'),
('/foo', '/ns1/ns2', '/foo'),
('foo/bar', '/ns1/ns2', '/ns1/foo/bar'),
('foo//bar', '/ns1/ns2', '/ns1/foo/bar'),
('foo/bar', '/ns1/ns2/ns3', '/ns1/ns2/foo/bar'),
('foo//bar//', '/ns1/ns2/ns3', '/ns1/ns2/foo/bar'),
('~foo', '/', '/foo'),
('~foo', '/node', '/node/foo'),
('~foo', '/ns1/ns2', '/ns1/ns2/foo'),
('~foo/', '/ns1/ns2', '/ns1/ns2/foo'),
('~foo/bar', '/ns1/ns2', '/ns1/ns2/foo/bar'),
# #3044
('~/foo', '/', '/foo'),
('~/foo', '/node', '/node/foo'),
('~/foo', '/ns1/ns2', '/ns1/ns2/foo'),
('~/foo/', '/ns1/ns2', '/ns1/ns2/foo'),
('~/foo/bar', '/ns1/ns2', '/ns1/ns2/foo/bar'),
]
for name, node_name, v in tests:
assert v == resolve_name(name, node_name)
def test_anonymous_name():
from rosgraph.names import anonymous_name, is_legal_name
val = anonymous_name('foo')
assert 'foo' in val
assert 'foo' != val
assert val != anonymous_name('foo')
assert not '/' in val
assert is_legal_name(val)
def test_script_resolve_name():
from rosgraph.names import script_resolve_name, get_ros_namespace, ns_join
assert '/global' == script_resolve_name('/myscript', '/global')
val = script_resolve_name('/myscript', '')
assert get_ros_namespace() == val, val
val = script_resolve_name('/myscript', 'foo')
assert ns_join(get_ros_namespace(), 'foo') == val, val
assert '/myscript/private' == script_resolve_name('/myscript', '~private')
def test_canonicalize_name():
from rosgraph.names import canonicalize_name
tests = [
('', ''),
('/', '/'),
('foo', 'foo'),
('/foo', '/foo'),
('/foo/', '/foo'),
('/foo/bar', '/foo/bar'),
('/foo/bar/', '/foo/bar'),
('/foo/bar//', '/foo/bar'),
('/foo//bar', '/foo/bar'),
('//foo/bar', '/foo/bar'),
('foo/bar', 'foo/bar'),
('foo//bar', 'foo/bar'),
('foo/bar/', 'foo/bar'),
('/foo/bar', '/foo/bar'),
]
for t, v in tests:
assert v == canonicalize_name(t)

View File

@@ -0,0 +1,250 @@
# Software License Agreement (BSD License)
#
# Copyright (c) 2009, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Willow Garage, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import os
import struct
import sys
import unittest
class MockSock(object):
def __init__(self, data=''):
self.data = data
def recv(self):
d = self.data
self.data = ''
return d
def sendall(self, d):
self.data = self.data + d
def send(self, d):
self.data = self.data + d
return len(d)
class NetworkTest(unittest.TestCase):
def test_encode_ros_handshake_header(self):
from rosgraph.network import encode_ros_handshake_header
d = {}
assert struct.pack('<I', 0) == encode_ros_handshake_header(d)
s = b"a=b"
d['a'] = 'b'
encoded = struct.pack('<I', len(s))+s
assert struct.pack('<I', len(encoded))+encoded == \
encode_ros_handshake_header({'a': 'b'})
d['c'] = 'd'
s = b"c=d"
encoded = encoded+struct.pack('<I', len(s))+s
assert struct.pack('<I', len(encoded))+encoded == \
encode_ros_handshake_header(d)
d['rawtype'] = '#line 1\nline 2\nline 3\nline\t4\r\r\n'
s = b"rawtype=#line 1\nline 2\nline 3\nline\t4\r\r\n"
encoded = encoded+struct.pack('<I', len(s))+s
assert struct.pack('<I', len(encoded))+encoded == \
encode_ros_handshake_header(d)
if sys.version_info > (3, 0):
assert \
encode_ros_handshake_header(
{'a': 'b', 'c': 'd', 'e': 'f'}) == \
encode_ros_handshake_header(
{b'a': 'b', 'c': b'd', b'e': b'f'})
else:
assert \
encode_ros_handshake_header(
{'a': 'b', 'c': 'd', 'e': 'f'}) == \
encode_ros_handshake_header(
{u'a': 'b', 'c': u'd', u'e': u'f'})
def test_decode_ros_handshake_header(self):
from rosgraph.network import decode_ros_handshake_header, ROSHandshakeException
invalids = [b"field1",b"",]
# prepend field length
invalids = [(struct.pack('<I', len(s)) + s) for s in invalids]
# prepend message length
invalids = [(struct.pack('<I', len(s)) + s) for s in invalids]
# invalid message length prefix
valid = b"a=b"
valid = struct.pack('<I', len(valid)) + valid
invalids.append(struct.pack('<I', 123)+valid)
# invalid field length prefix
invalid = struct.pack('<I', 123) + b'a=b'
invalids.append(struct.pack("<I", len(invalid)) + invalid)
for i in invalids:
try:
decode_ros_handshake_header(i)
assert False, "should have failed: %s"%i
except ROSHandshakeException: pass
assert {} == decode_ros_handshake_header(struct.pack('<I', 0))
# single-field tests
tests = [
(b"a=b", {'a': 'b'}),
# whitespace in keys is ignored
(b" a =b", {'a': 'b'}),
(b'newlines=\n\n\n\n', {'newlines': '\n\n\n\n'}),
(b'equals=foo=bar=car', {'equals': 'foo=bar=car'}),
(b"spaces=one two three four",{'spaces': 'one two three four'}),
]
for s, d in tests:
# add in length fields
s = struct.pack('<I', len(s)+4) + struct.pack('<I', len(s)) + s
assert d == decode_ros_handshake_header(s)
# multi-field tests
tests = [ {'a': 'b', 'c': 'd'},
{'spaces': ' ', 'tabs': '\t\t\t\t', 'equals': '====='},
]
for t in tests:
s = b''
for k, v in t.items():
f = "%s=%s"%(k, v)
f = f.encode()
s += struct.pack('<I', len(f)) + f
s = struct.pack('<I', len(s)) + s
assert t == decode_ros_handshake_header(s)
# make sure that decode ignores extra past header len
assert t == decode_ros_handshake_header(s+s)
def test_parse_http_host_and_port(self):
from rosgraph.network import parse_http_host_and_port
invalid = ['', 'http://', 'http://localhost:bar', None]
for t in invalid:
try:
parse_http_host_and_port(t)
assert False, "should have failed: %s"%t
except ValueError:
pass
assert ('localhost', 80) == parse_http_host_and_port('http://localhost')
assert ('localhost', 1234) == parse_http_host_and_port('http://localhost:1234')
assert ('localhost', 1) == parse_http_host_and_port('http://localhost:1')
assert ('willowgarage.com', 1) == parse_http_host_and_port('http://willowgarage.com:1')
def test_get_local_address(self):
# mostly a tripwire test
from rosgraph.network import get_local_address
a = get_local_address()
assert a
# now test address override
os.environ['ROS_IP'] = 'bar'
assert 'bar' == get_local_address()
os.environ['ROS_HOSTNAME'] = 'foo'
assert 'foo' == get_local_address()
try:
real_argv = sys.argv[:]
sys.argv = real_argv[:] + ['__ip:=1.2.3.4']
assert '1.2.3.4' == get_local_address()
sys.argv = real_argv[:] + ['__hostname:=bar']
assert 'bar' == get_local_address()
finally:
sys.argv = real_argv
def test_get_local_addresses(self):
# mostly a tripwire test
from rosgraph.network import get_local_addresses
addrs = get_local_addresses()
assert type(addrs) == list
assert len(addrs)
# should be unaffected
os.environ['ROS_IP'] = 'bar'
assert addrs == get_local_addresses()
os.environ['ROS_HOSTNAME'] = 'foo'
assert addrs == get_local_addresses()
def test_get_bind_address(self):
from rosgraph.network import get_bind_address
assert '0.0.0.0' == get_bind_address('foo')
assert '127.0.0.1' == get_bind_address('localhost')
assert '127.0.1.1' == get_bind_address('127.0.1.1')
# now test address override
os.environ['ROS_IP'] = 'bar'
assert '0.0.0.0' == get_bind_address()
assert '0.0.0.0' == get_bind_address('foo')
os.environ['ROS_IP'] = 'localhost'
assert '127.0.0.1' == get_bind_address()
assert '0.0.0.0' == get_bind_address('foo')
os.environ['ROS_HOSTNAME'] = 'bar'
assert '0.0.0.0' == get_bind_address()
assert '0.0.0.0' == get_bind_address('foo')
os.environ['ROS_HOSTNAME'] = 'localhost'
assert '127.0.0.1' == get_bind_address()
assert '0.0.0.0' == get_bind_address('foo')
def test_get_host_name(self):
from rosgraph.network import get_host_name
os.environ['ROS_IP'] = 'foo'
assert 'foo' == get_host_name()
os.environ['ROS_HOSTNAME'] = 'bar'
assert 'bar' == get_host_name()
try:
real_argv = sys.argv[:]
sys.argv = real_argv[:] + ['__ip:=1.2.3.4']
assert '1.2.3.4' == get_host_name()
sys.argv = real_argv[:] + ['__hostname:=baz']
assert 'baz' == get_host_name()
finally:
sys.argv = real_argv
def test_create_local_xmlrpc_uri(self):
from rosgraph.network import parse_http_host_and_port, create_local_xmlrpc_uri
os.environ['ROS_HOSTNAME'] = 'localhost'
assert ('localhost', 1234) == parse_http_host_and_port(create_local_xmlrpc_uri(1234))
def setUp(self):
self._ros_hostname = self._ros_ip = None
if 'ROS_HOSTNAME' in os.environ:
self._ros_hostname = os.environ['ROS_HOSTNAME']
del os.environ['ROS_HOSTNAME']
if 'ROS_IP' in os.environ:
self._ros_ip = os.environ['ROS_IP']
del os.environ['ROS_IP']
def tearDown(self):
if 'ROS_HOSTNAME' in os.environ:
del os.environ['ROS_HOSTNAME']
if 'ROS_IP' in os.environ:
del os.environ['ROS_IP']
if self._ros_hostname:
os.environ['ROS_HOSTNAME'] = self._ros_hostname
if self._ros_ip:
os.environ['ROS_IP'] = self._ros_ip

View File

@@ -0,0 +1,77 @@
# Software License Agreement (BSD License)
#
# Copyright (c) 2011, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Willow Garage, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import os
import sys
def test_vars():
import rosgraph.rosenv
assert 'ROS_MASTER_URI' == rosgraph.rosenv.ROS_MASTER_URI
assert rosgraph.rosenv.ROS_IP == 'ROS_IP'
assert rosgraph.rosenv.ROS_HOSTNAME == 'ROS_HOSTNAME'
assert rosgraph.rosenv.ROS_NAMESPACE == 'ROS_NAMESPACE'
def test_get_master_uri():
from rosgraph.rosenv import get_master_uri
val = get_master_uri()
if 'ROS_MASTER_URI' in os.environ:
assert val == os.environ['ROS_MASTER_URI']
# environment override
val = get_master_uri(env=dict(ROS_MASTER_URI='foo'))
assert val == 'foo'
# argv override precedence, first arg wins
val = get_master_uri(env=dict(ROS_MASTER_URI='foo'), argv=['__master:=bar', '__master:=bar2'])
assert val == 'bar'
# empty env
assert None == get_master_uri(env={})
# invalid argv
try:
val = get_master_uri(argv=['__master:='])
assert False, "should have failed"
except ValueError:
pass
# invalid argv
try:
val = get_master_uri(argv=['__master:=foo:=bar'])
assert False, "should have failed"
except ValueError:
pass

View File

@@ -0,0 +1,63 @@
#!/usr/bin/env python
# Software License Agreement (BSD License)
#
# Copyright (c) 2009, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Willow Garage, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import os
import sys
import unittest
import time
from subprocess import Popen, PIPE, check_call, call
class TestRosgraphOffline(unittest.TestCase):
def setUp(self):
pass
## test that the rosmsg command works
def test_cmd_help(self):
cmd = 'rosgraph'
output = Popen([cmd, '-h'], stdout=PIPE).communicate()[0]
self.assert_('Usage' in output.decode())
def test_offline(self):
cmd = 'rosgraph'
# point at a different 'master'
env = os.environ.copy()
env['ROS_MASTER_URI'] = 'http://localhost:11312'
kwds = { 'env': env, 'stdout': PIPE, 'stderr': PIPE}
msg = "ERROR: Unable to communicate with master!\n"
output = Popen([cmd], **kwds).communicate()
self.assertEquals(msg, output[1].decode())

View File

@@ -0,0 +1,398 @@
# Software License Agreement (BSD License)
#
# Copyright (c) 2009, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Willow Garage, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import os
import sys
import unittest
import rosgraph.masterapi
_ID = '/caller_id'
_MASTER_URI = 'http://localhost:12345'
class MasterMock(object):
"""
Mock for testing Master without using actual master
"""
def __init__(self):
self.call = None
self.return_val = None
def getMasterUri(self, caller_id):
self.call = ('getMasterUri', caller_id)
return self.return_val
def getPid(self, caller_id):
self.call = ('getPid', caller_id)
return self.return_val
def getUri(self, caller_id):
self.call = ('getUri', caller_id)
return self.return_val
def registerService(self, caller_id, service, service_api, caller_api):
self.call = ('registerService', caller_id, service, service_api, caller_api)
return self.return_val
def lookupService(self, caller_id, service):
self.call = ('lookupService', caller_id, service)
return self.return_val
def unregisterService(self, caller_id, service, service_api):
self.call = ('unregisterService', caller_id, service, service_api)
return self.return_val
def registerSubscriber(self, caller_id, topic, topic_type, caller_api):
self.call = ('registerSubscriber', caller_id, topic, topic_type, caller_api)
return self.return_val
def unregisterSubscriber(self, caller_id, topic, caller_api):
self.call = ('unregisterSubscriber', caller_id, topic, caller_api)
return self.return_val
def registerPublisher(self, caller_id, topic, topic_type, caller_api):
self.call = ('registerPublisher', caller_id, topic, topic_type, caller_api)
return self.return_val
def unregisterPublisher(self, caller_id, topic, caller_api):
self.call = ('unregisterPublisher', caller_id, topic, caller_api)
return self.return_val
def lookupNode(self, caller_id, node_name):
self.call = ('lookupNode', caller_id, node_name)
return self.return_val
def getPublishedTopics(self, caller_id, subgraph):
self.call = ('getPublishedTopics', caller_id, subgraph)
return self.return_val
def getTopicTypes(self, caller_id):
self.call = ('getTopicTypes', caller_id)
return self.return_val
def getSystemState(self, caller_id):
self.call = ('getSystemState', caller_id)
return self.return_val
def getParam(self, caller_id, p):
self.call = ('getParam', caller_id, p)
return self.return_val
def hasParam(self, caller_id, p):
self.call = ('hasParam', caller_id, p)
return self.return_val
def deleteParam(self, caller_id, p):
self.call = ('deleteParam', caller_id, p)
return self.return_val
def searchParam(self, caller_id, p):
self.call = ('searchParam', caller_id, p)
return self.return_val
def setParam(self, caller_id, p, v):
self.call = ('setParam', caller_id, p, v)
return self.return_val
def subscribeParam(self, caller_id, api, p):
self.call = ('subscribeParam', caller_id, api, p)
return self.return_val
def unsubscribeParam(self, caller_id, api, p):
self.call = ('unsubscribeParam', caller_id, api, p)
return self.return_val
def getParamNames(self, caller_id):
self.call = ('getParamNames', caller_id)
return self.return_val
class MasterApiOfflineTest(unittest.TestCase):
def setUp(self):
self.m = rosgraph.masterapi.Master(_ID, master_uri = _MASTER_URI)
# replace xmlrpclib server proxy with mock
self.m.handle = MasterMock()
def throw_failure(self, attr, args, ret_val):
self.m.handle.return_val = ret_val
f = getattr(self.m, attr)
try:
f(*args)
self.fail("[%s] should have thrown Failure with args [%s], ret_val [%s]"%(attr, str(args), str(ret_val)))
except rosgraph.masterapi.Failure:
pass
def throw_error(self, attr, args, ret_val):
self.m.handle.return_val = ret_val
f = getattr(self.m, attr)
try:
f(*args)
self.fail("[%s] should have thrown Error with args [%s], ret_val [%s]"%(attr, str(args), str(ret_val)))
except rosgraph.masterapi.Error:
pass
def test_Master(self):
# test constructor args
m = rosgraph.masterapi.Master(_ID, master_uri = 'http://localhost:12345')
self.assertEquals(_ID, m.caller_id)
self.assertEquals(_MASTER_URI, m.master_uri)
reset_uri = False
if 'ROS_MASTER_URI' not in os.environ:
os.environ['ROS_MASTER_URI'] = 'http://localhost:21311'
try:
m = rosgraph.masterapi.Master(_ID)
self.assertEquals(os.environ['ROS_MASTER_URI'], m.master_uri)
id = '/some/other/id'
m = rosgraph.masterapi.Master(id)
self.assertEquals(id, m.caller_id)
finally:
if reset_uri:
del os.environ['ROS_MASTER_URI']
def test_getPid(self):
h = self.m.handle
r = 1235
h.return_val = (1, '', r)
self.assertEquals(r, self.m.getPid())
self.assertEquals(('getPid',_ID), h.call)
self.throw_failure('getPid', (), (0, '', r))
self.throw_error('getPid', (), (-1, '', r))
def test_getPid(self):
h = self.m.handle
r = 'http://foo:1234'
h.return_val = (1, '', r)
self.assertEquals(r, self.m.getUri())
self.assertEquals(('getUri',_ID), h.call)
self.throw_failure('getUri', (), (0, '', r))
self.throw_error('getUri', (), (-1, '', r))
def test_lookupService(self):
h = self.m.handle
r = 'rosrpc://localhost:12345'
h.return_val = (1, '', r)
self.assertEquals(r, self.m.lookupService('/bar/service'))
self.assertEquals(('lookupService',_ID, '/bar/service'), h.call)
self.throw_failure('lookupService', ('/bar/service',), (0, '', r))
self.throw_error('lookupService', ('/bar/service',), (-1, '', r))
def test_registerService(self):
h = self.m.handle
r = 11
h.return_val = (1, '', r)
self.assertEquals(r, self.m.registerService('/bar/service', 'rosrpc://localhost:9812', 'http://localhost:893'))
self.assertEquals(('registerService',_ID, '/bar/service', 'rosrpc://localhost:9812', 'http://localhost:893'), h.call)
args = ('/bar/service', 'rosrpc://localhost:9812', 'http://localhost:893')
self.throw_failure('registerService', args, (0, '', r))
self.throw_error('registerService', args, (-1, '', r))
def test_unregisterService(self):
h = self.m.handle
r = 1
h.return_val = (1, '', r)
self.assertEquals(r, self.m.unregisterService('/bar/service', 'rosrpc://localhost:9812'))
self.assertEquals(('unregisterService',_ID, '/bar/service', 'rosrpc://localhost:9812'), h.call)
args = ('/bar/service', 'rosrpc://localhost:9812')
self.throw_failure('unregisterService', args, (0, '', r))
self.throw_error('unregisterService', args, (-1, '', r))
def test_registerSubscriber(self):
h = self.m.handle
r = ['http://localhost:1234', 'http://localhost:98127']
h.return_val = (1, '', r)
self.assertEquals(r, self.m.registerSubscriber('/foo/node', 'std_msgs/String', 'http://localhost:9812'))
self.assertEquals(('registerSubscriber',_ID, '/foo/node', 'std_msgs/String', 'http://localhost:9812'), h.call)
args = ('/foo/node', 'std_msgs/String', 'http://localhost:9812')
self.throw_failure('registerSubscriber', args, (0, '', r))
self.throw_error('registerSubscriber', args, (-1, '', r))
def test_unregisterSubscriber(self):
h = self.m.handle
r = 1
h.return_val = (1, '', r)
self.assertEquals(r, self.m.unregisterSubscriber('/foo/node', 'http://localhost:9812'))
self.assertEquals(('unregisterSubscriber',_ID, '/foo/node', 'http://localhost:9812'), h.call)
args = ('/foo/node', 'http://localhost:9812')
self.throw_failure('unregisterSubscriber', args, (0, '', r))
self.throw_error('unregisterSubscriber', args, (-1, '', r))
def test_registerPublisher(self):
h = self.m.handle
r = 5
h.return_val = (1, '', r)
self.assertEquals(r, self.m.registerPublisher('/foo/node', 'std_msgs/String', 'http://localhost:9812'))
self.assertEquals(('registerPublisher',_ID, '/foo/node', 'std_msgs/String', 'http://localhost:9812'), h.call)
args = ('/foo/node', 'std_msgs/String', 'http://localhost:9812')
self.throw_failure('registerPublisher', args, (0, '', r))
self.throw_error('registerPublisher', args, (-1, '', r))
def test_unregisterPublisher(self):
h = self.m.handle
r = 10
h.return_val = (1, '', r)
self.assertEquals(r, self.m.unregisterPublisher('/foo/node', 'http://localhost:9812'))
self.assertEquals(('unregisterPublisher',_ID, '/foo/node', 'http://localhost:9812'), h.call)
args = ('/foo/node', 'http://localhost:9812')
self.throw_failure('unregisterPublisher', args, (0, '', r))
self.throw_error('unregisterPublisher', args, (-1, '', r))
def test_lookupNode(self):
h = self.m.handle
r = 'http://localhost:123'
h.return_val = (1, '', r)
self.assertEquals(r, self.m.lookupNode('/foo/node'))
self.assertEquals(('lookupNode',_ID, '/foo/node'), h.call)
args = ('/foo/node',)
self.throw_failure('lookupNode', args, (0, '', r))
self.throw_error('lookupNode', args, (-1, '', r))
def test_getPublishedTopics(self):
h = self.m.handle
r = [ ['foo', 'bar'], ['baz', 'blah'] ]
h.return_val = (1, '', r)
self.assertEquals(r, self.m.getPublishedTopics('/foo'))
self.assertEquals(('getPublishedTopics',_ID, '/foo'), h.call)
args = ('/baz',)
self.throw_failure('getPublishedTopics', args, (0, '', r))
self.throw_error('getPublishedTopics', args, (-1, '', r))
def test_getTopicTypes(self):
h = self.m.handle
r = [ ['/foo', 'std_msgs/String'], ['/baz', 'std_msgs/Int32'] ]
h.return_val = (1, '', r)
self.assertEquals(r, self.m.getTopicTypes())
self.assertEquals(('getTopicTypes',_ID), h.call)
self.throw_failure('getTopicTypes', (), (0, '', r))
self.throw_error('getTopicTypes', (), (-1, '', r))
def test_getSystemState(self):
h = self.m.handle
r = [ [], [], [] ]
h.return_val = (1, '', r)
self.assertEquals(r, self.m.getSystemState())
self.assertEquals(('getSystemState', _ID), h.call)
self.throw_failure('getSystemState', (), (0, '', r))
self.throw_error('getSystemState', (), (-1, '', r))
################################################################################
# PARAM SERVER API TESTS
def test_getParam(self):
h = self.m.handle
r = 1
h.return_val = (1, '', r)
p = '/test_param'
self.assertEquals(r, self.m.getParam(p))
self.assertEquals(('getParam', _ID, p), h.call)
args = (p,)
self.throw_failure('getParam', args, (0, '', r))
self.throw_error('getParam', args, (-1, '', r))
def test_getParamNames(self):
h = self.m.handle
r = [ '/foo' ]
h.return_val = (1, '', r)
self.assertEquals(r, self.m.getParamNames())
self.assertEquals(('getParamNames', _ID), h.call)
self.throw_failure('getParamNames', (), (0, '', r))
self.throw_error('getParamNames', (), (-1, '', r))
def test_hasParam(self):
h = self.m.handle
r = True
h.return_val = (1, '', r)
p = '/test_param'
self.assertEquals(r, self.m.hasParam(p))
self.assertEquals(('hasParam', _ID, p), h.call)
self.throw_failure('hasParam', (p,), (0, '', r))
self.throw_error('hasParam', (p,), (-1, '', r))
def test_searchParam(self):
h = self.m.handle
r = '/foo'
h.return_val = (1, '', r)
p = '/test_param'
self.assertEquals(r, self.m.searchParam(p))
self.assertEquals(('searchParam', _ID, p), h.call)
self.throw_failure('searchParam', (p,), (0, '', r))
self.throw_error('searchParam', (p,), (-1, '', r))
def test_deleteParam(self):
h = self.m.handle
r = '/foo'
h.return_val = (1, '', r)
p = '/test_param'
self.assertEquals(r, self.m.deleteParam(p))
self.assertEquals(('deleteParam', _ID, p), h.call)
self.throw_failure('deleteParam', (p,), (0, '', r))
self.throw_error('deleteParam', (p,), (-1, '', r))
def test_is_online(self):
self.failIf(rosgraph.masterapi.is_online(master_uri="http://fake:12345"))
self.m.handle.return_val = (1, '', 1235)
self.assert_(self.m.is_online())
def test_subscribeParam(self):
h = self.m.handle
r = 1
h.return_val = (1, '', r)
args = ('http://bar:12345', '/test_param')
self.assertEquals(r, self.m.subscribeParam(*args))
self.assertEquals(('subscribeParam', _ID, args[0], args[1]), h.call)
self.throw_failure('subscribeParam', args, (0, '', r))
self.throw_error('subscribeParam', args, (-1, '', r))
def test_unsubscribeParam(self):
h = self.m.handle
r = 1
h.return_val = (1, '', r)
args = ('http://bar:12345', '/test_param')
self.assertEquals(r, self.m.unsubscribeParam(*args))
self.assertEquals(('unsubscribeParam', _ID, args[0], args[1]), h.call)
self.throw_failure('unsubscribeParam', args, (0, '', r))
self.throw_error('unsubscribeParam', args, (-1, '', r))
def test_setParam(self):
h = self.m.handle
r = 1
h.return_val = (1, '', r)
args = ('/test_set_param', 'foo')
self.assertEquals(r, self.m.setParam(*args))
self.assertEquals(('setParam', _ID, args[0], args[1]), h.call)
self.throw_failure('setParam', args, (0, '', r))
self.throw_error('setParam', args, (-1, '', r))

View File

@@ -0,0 +1,84 @@
# Software License Agreement (BSD License)
#
# Copyright (c) 2009, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Willow Garage, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import os
import sys
import time
import mock
def test_XmlRpcHandler():
from rosgraph.xmlrpc import XmlRpcHandler
# tripwire
h = XmlRpcHandler()
# noop
h._ready('http://localhost:1234')
def test_XmlRpcNode():
from rosgraph.xmlrpc import XmlRpcNode, XmlRpcHandler
# not a very comprehensive test (yet)
#port, handler
tests = [
(None, None, None),
(8080, None, 8080),
('8080', None, 8080),
(u'8080', None, 8080),
]
for port, handler,true_port in tests:
n = XmlRpcNode(port, handler)
assert true_port == n.port
assert handler == n.handler
assert None == n.uri
assert None == n.server
n.set_uri('http://fake:1234')
assert 'http://fake:1234' == n.uri
n.start()
start = time.time()
while not n.uri and time.time() - start < 5.:
time.sleep(0.00001) #poll for XMLRPC init
assert n.uri
n.shutdown('test case')
# get coverage on run init
n = XmlRpcNode(0, XmlRpcHandler())
n._run_init()
n.shutdown('test case')
# mock in server in order to play with _run()
n.server = mock.Mock()
n.is_shutdown = False
n._run_init = mock.Mock()
n.server.serve_forever.side_effect = IOError(1, 'boom')
n._run()