Skip to content

Commit 6da5a09

Browse files
authored
Add Tests and Linter (#63)
* Add tests for tcp sender * Add linter and pre-commit hooks * Reformat with python black * Add tests * Add tests for server, client, publisher, subscriber, ros_service, unity_service, thread_pauser * Fix pre-commit-config file name; Add client tests * Add github workflow check * Formatting
1 parent cfc6bdd commit 6da5a09

27 files changed

+559
-103
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Provide any relevant links here.
1616

1717
## Testing and Verification
1818

19-
Please describe the tests that you ran to verify your changes. Please also provide instructions, ROS packages, and Unity project files as appropriate so we can reproduce the test environment.
19+
Please describe the tests that you ran to verify your changes. Please also provide instructions, ROS packages, and Unity project files as appropriate so we can reproduce the test environment.
2020

2121
### Test Configuration:
2222
- Unity Version: [e.g. Unity 2020.2.0f1]

.github/workflows/pre-commit.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: pre-commit
2+
3+
on:
4+
pull_request:
5+
6+
jobs:
7+
pre-commit:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v2
11+
- uses: actions/setup-python@v2
12+
with:
13+
python-version: 3.7.x
14+
- uses: pre-commit/action@v2.0.0

.pre-commit-config.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
repos:
2+
- repo: https://github.com/python/black
3+
rev: 19.3b0
4+
hooks:
5+
- id: black
6+
args: [--line-length=100]
7+
- repo: https://github.com/pre-commit/pre-commit-hooks
8+
rev: v3.4.0
9+
hooks:
10+
- id: trailing-whitespace
11+
name: trailing-whitespace-markdown
12+
types: [markdown]

CONTRIBUTING.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Contribution Guidelines
22

3-
Thank you for your interest in contributing to Unity Robotics! To facilitate your
4-
contributions, we've outlined a brief set of guidelines to ensure that your extensions
3+
Thank you for your interest in contributing to Unity Robotics! To facilitate your
4+
contributions, we've outlined a brief set of guidelines to ensure that your extensions
55
can be easily integrated.
66

77
## Communication
@@ -40,10 +40,10 @@ We run continuous integration on all PRs; all tests must be passing before the P
4040

4141
All Python code should follow the [PEP 8 style guidelines](https://pep8.org/).
4242

43-
All C# code should follow the [Microsoft C# Coding Conventions](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions).
44-
Additionally, the [Unity Coding package](https://docs.unity3d.com/Packages/com.unity.coding@0.1/manual/index.html)
45-
can be used to format, encode, and lint your code according to the standard Unity
46-
development conventions. Be aware that these Unity conventions will supersede the
43+
All C# code should follow the [Microsoft C# Coding Conventions](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions).
44+
Additionally, the [Unity Coding package](https://docs.unity3d.com/Packages/com.unity.coding@0.1/manual/index.html)
45+
can be used to format, encode, and lint your code according to the standard Unity
46+
development conventions. Be aware that these Unity conventions will supersede the
4747
Microsoft C# Coding Conventions where applicable.
4848

4949
Please note that even if the code you are changing does not adhere to these guidelines,
@@ -60,5 +60,5 @@ email us at [unity-robotics@unity3d.com](mailto:unity-robotics@unity3d.com).
6060

6161
## Contribution review
6262

63-
Once you have a change ready following the above ground rules, simply make a
63+
Once you have a change ready following the above ground rules, simply make a
6464
pull request in GitHub.

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ Instructions and examples on how to use this ROS package can be found on the [Un
1010

1111
## Community and Feedback
1212

13-
The Unity Robotics projects are open-source and we encourage and welcome contributions.
14-
If you wish to contribute, be sure to review our [contribution guidelines](CONTRIBUTING.md)
13+
The Unity Robotics projects are open-source and we encourage and welcome contributions.
14+
If you wish to contribute, be sure to review our [contribution guidelines](CONTRIBUTING.md)
1515
and [code of conduct](CODE_OF_CONDUCT.md).
1616

1717
## Support
1818
For questions or discussions about Unity Robotics package installations or how to best set up and integrate your robotics projects, please create a new thread on the [Unity Robotics forum](https://forum.unity.com/forums/robotics.623/) and make sure to include as much detail as possible.
1919

2020
For feature requests, bugs, or other issues, please file a [GitHub issue](https://github.com/Unity-Technologies/ROS-TCP-Endpoint/issues) using the provided templates and the Robotics team will investigate as soon as possible.
2121

22-
For any other questions or feedback, connect directly with the
22+
For any other questions or feedback, connect directly with the
2323
Robotics team at [unity-robotics@unity3d.com](mailto:unity-robotics@unity3d.com).
2424

2525
## License

config/params.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
ROS_IP: 127.0.0.1
1+
ROS_IP: 0.0.0.0
2+
ROS_TCP_PORT: 10000
3+

requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
black
2+
pre-commit
3+
pytest-cov

setup.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
from catkin_pkg.python_setup import generate_distutils_setup
55

66
# fetch values from package.xml
7-
setup_args = generate_distutils_setup(
8-
packages=['ros_tcp_endpoint'],
9-
package_dir={'': 'src'})
7+
setup_args = generate_distutils_setup(packages=["ros_tcp_endpoint"], package_dir={"": "src"})
108

119
setup(**setup_args)

src/ros_tcp_endpoint/client.py

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class ClientThread(threading.Thread):
2828
Thread class to read all data from a connection and pass along the data to the
2929
desired source.
3030
"""
31+
3132
def __init__(self, conn, tcp_server, incoming_ip, incoming_port):
3233
"""
3334
Set class variables
@@ -65,7 +66,7 @@ def read_int32(conn):
6566
6667
"""
6768
raw_bytes = ClientThread.recvall(conn, 4)
68-
num = struct.unpack('<I', raw_bytes)[0]
69+
num = struct.unpack("<I", raw_bytes)[0]
6970
return num
7071

7172
@staticmethod
@@ -81,7 +82,7 @@ def read_string(conn):
8182
str_len = ClientThread.read_int32(conn)
8283

8384
str_bytes = ClientThread.recvall(conn, str_len)
84-
decoded_str = str_bytes.decode('utf-8')
85+
decoded_str = str_bytes.decode("utf-8")
8586

8687
return decoded_str
8788

@@ -91,7 +92,7 @@ def read_message(conn):
9192
Decode destination and full message size from socket connection.
9293
Grab bytes in chunks until full message has been read.
9394
"""
94-
data = b''
95+
data = b""
9596

9697
destination = ClientThread.read_string(conn)
9798
full_message_size = ClientThread.read_int32(conn)
@@ -125,9 +126,9 @@ def serialize_message(destination, message):
125126
Returns:
126127
serialized destination and message as a list of bytes
127128
"""
128-
dest_bytes = destination.encode('utf-8')
129+
dest_bytes = destination.encode("utf-8")
129130
length = len(dest_bytes)
130-
dest_info = struct.pack('<I%ss' % length, length, dest_bytes)
131+
dest_info = struct.pack("<I%ss" % length, length, dest_bytes)
131132

132133
serial_response = BytesIO()
133134
message.serialize(serial_response)
@@ -139,7 +140,7 @@ def serialize_message(destination, message):
139140
# SEEK_END or 2 - end of the stream; offset is usually negative
140141
response_len = serial_response.seek(0, 2)
141142

142-
msg_length = struct.pack('<I', response_len)
143+
msg_length = struct.pack("<I", response_len)
143144
serialized_message = dest_info + msg_length + serial_response.getvalue()
144145

145146
return serialized_message
@@ -166,52 +167,62 @@ def run(self):
166167
while not halt_event.is_set():
167168
destination, data = self.read_message(self.conn)
168169

169-
if destination == '':
170-
#ignore this keepalive message, listen for more
170+
if destination == "":
171+
# ignore this keepalive message, listen for more
171172
pass
172-
elif destination == '__syscommand':
173-
#handle a system command, such as registering new topics
173+
elif destination == "__syscommand":
174+
# handle a system command, such as registering new topics
174175
self.tcp_server.handle_syscommand(data)
175-
elif destination == '__srv':
176+
elif destination == "__srv":
176177
# handle a ros service message request, or a unity service message response
177178
srv_message = RosUnitySrvMessage().deserialize(data)
178179
if not srv_message.is_request:
179-
self.tcp_server.send_unity_service_response(srv_message.srv_id, srv_message.payload)
180+
self.tcp_server.send_unity_service_response(
181+
srv_message.srv_id, srv_message.payload
182+
)
180183
continue
181-
elif srv_message.topic == '__topic_list':
184+
elif srv_message.topic == "__topic_list":
182185
response = self.tcp_server.topic_list(data)
183186
elif srv_message.topic not in self.tcp_server.source_destination_dict.keys():
184-
error_msg = "Service destination '{}' is not registered! Known topics are: {} "\
185-
.format(srv_message.topic, self.tcp_server.source_destination_dict.keys())
187+
error_msg = "Service destination '{}' is not registered! Known topics are: {} ".format(
188+
srv_message.topic, self.tcp_server.source_destination_dict.keys()
189+
)
186190
self.tcp_server.send_unity_error(error_msg)
187191
rospy.logerr(error_msg)
188192
# TODO: send a response to Unity anyway?
189-
continue
193+
continue
190194
else:
191-
ros_communicator = self.tcp_server.source_destination_dict[srv_message.topic]
195+
ros_communicator = self.tcp_server.source_destination_dict[
196+
srv_message.topic
197+
]
192198
response = ros_communicator.send(srv_message.payload)
193199
if not response:
194-
error_msg = "No response data from service '{}'!".format(srv_message.topic)
200+
error_msg = "No response data from service '{}'!".format(
201+
srv_message.topic
202+
)
195203
self.tcp_server.send_unity_error(error_msg)
196204
rospy.logerr(error_msg)
197205
# TODO: send a response to Unity anyway?
198206
continue
199-
207+
200208
serial_response = BytesIO()
201209
response.serialize(serial_response)
202-
response_message = RosUnitySrvMessage(srv_message.srv_id, False, '', serial_response.getvalue())
210+
response_message = RosUnitySrvMessage(
211+
srv_message.srv_id, False, "", serial_response.getvalue()
212+
)
203213
self.tcp_server.unity_tcp_sender.send_unity_message("__srv", response_message)
204214
elif destination in self.tcp_server.source_destination_dict:
205215
ros_communicator = self.tcp_server.source_destination_dict[destination]
206216
response = ros_communicator.send(data)
207217
else:
208-
error_msg = "Topic '{}' is not registered! Known topics are: {} "\
209-
.format(destination, self.tcp_server.source_destination_dict.keys())
218+
error_msg = "Topic '{}' is not registered! Known topics are: {} ".format(
219+
destination, self.tcp_server.source_destination_dict.keys()
220+
)
210221
self.tcp_server.send_unity_error(error_msg)
211222
rospy.logerr(error_msg)
212223
except IOError as e:
213224
rospy.logerr("Exception: {}".format(e))
214225
finally:
215226
halt_event.set()
216227
self.conn.close()
217-
rospy.loginfo("Disconnected from {}".format(self.incoming_ip));
228+
rospy.loginfo("Disconnected from {}".format(self.incoming_ip))

src/ros_tcp_endpoint/communication.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@
1515

1616
class RosSender:
1717
"""
18-
Base class for ROS communication where data is sent to the ROS network.
18+
Base class for ROS communication where data is sent to the ROS network.
1919
"""
20+
2021
def __init__(self):
2122
pass
2223

@@ -26,8 +27,9 @@ def send(self, *args):
2627

2728
class RosReceiver:
2829
"""
29-
Base class for ROS communication where data is being sent outside of the ROS network.
30+
Base class for ROS communication where data is being sent outside of the ROS network.
3031
"""
32+
3133
def __init__(self):
3234
pass
3335

0 commit comments

Comments
 (0)