Skip to content

Commit 391e5ef

Browse files
authored
Attach request to response in client (#163)
* Fix #162 Attach original request to response in client * fix #161 - Bad static type in send_request
1 parent 5c8a66b commit 391e5ef

File tree

5 files changed

+52
-42
lines changed

5 files changed

+52
-42
lines changed

test/client/test_client.py

+37-28
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from test.ClientServerTest import ClientServerTest
66
import time
77

8+
89
class TestClient(ClientServerTest):
910
def __init__(self, *args, **kwargs):
1011
ClientServerTest.__init__(self, *args, **kwargs)
@@ -13,7 +14,7 @@ def test_timeout_override(self):
1314
pass
1415

1516
def _test_timeout_override(self):
16-
req = Request(service = services.TesterPresent, subfunction=0)
17+
req = Request(service=services.TesterPresent, subfunction=0)
1718
timeout = 0.5
1819
try:
1920
t1 = time.time()
@@ -22,43 +23,43 @@ def _test_timeout_override(self):
2223
except TimeoutException as e:
2324
diff = time.time() - t1
2425
self.assertGreater(diff, timeout, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
25-
self.assertLess(diff, timeout+0.5, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
26+
self.assertLess(diff, timeout + 0.5, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
2627

2728
# Server does not respond. Overall timeout is set smaller than P2 timeout. Overall timeout should trig
2829
def test_no_response_overall_timeout(self):
2930
pass
3031

3132
def _test_no_response_overall_timeout(self):
32-
req = Request(service = services.TesterPresent, subfunction=0)
33+
req = Request(service=services.TesterPresent, subfunction=0)
3334
timeout = 0.5
34-
self.udsclient.set_configs({'request_timeout': timeout, 'p2_timeout' : 2, 'p2_star_timeout':2})
35+
self.udsclient.set_configs({'request_timeout': timeout, 'p2_timeout': 2, 'p2_star_timeout': 2})
3536
try:
3637
t1 = time.time()
3738
response = self.udsclient.send_request(req)
3839
raise Exception('Request did not raise a TimeoutException')
3940
except TimeoutException as e:
4041
diff = time.time() - t1
4142
self.assertGreater(diff, timeout, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
42-
self.assertLess(diff, timeout+0.5, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
43+
self.assertLess(diff, timeout + 0.5, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
4344

4445
# Server does not respond. P2 timeout is smaller than overall timeout. P2 timeout should trig
4546
def test_no_response_p2_timeout(self):
4647
pass
4748

4849
def _test_no_response_p2_timeout(self):
49-
req = Request(service = services.TesterPresent, subfunction=0)
50+
req = Request(service=services.TesterPresent, subfunction=0)
5051
timeout = 0.5
51-
self.udsclient.set_configs({'request_timeout': 2, 'p2_timeout' : timeout, 'p2_star_timeout':2})
52+
self.udsclient.set_configs({'request_timeout': 2, 'p2_timeout': timeout, 'p2_star_timeout': 2})
5253
try:
5354
t1 = time.time()
5455
response = self.udsclient.send_request(req)
5556
raise Exception('Request did not raise a TimeoutException')
5657
except TimeoutException as e:
5758
diff = time.time() - t1
5859
self.assertGreater(diff, timeout, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
59-
self.assertLess(diff, timeout+0.5, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
60+
self.assertLess(diff, timeout + 0.5, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
6061

61-
# Overall timeout is set to 0.5. Server respond "pendingResponse" for 1 sec.
62+
# Overall timeout is set to 0.5. Server respond "pendingResponse" for 1 sec.
6263
# Client should timeout first as we are setting respect_overall_timeout True.
6364
def test_overall_timeout_pending_response(self):
6465
if not hasattr(self, 'completed'):
@@ -71,9 +72,9 @@ def test_overall_timeout_pending_response(self):
7172
time.sleep(0.1)
7273

7374
def _test_overall_timeout_pending_response(self):
74-
req = Request(service = services.TesterPresent, subfunction=0)
75+
req = Request(service=services.TesterPresent, subfunction=0)
7576
timeout = 0.5
76-
self.udsclient.set_configs({'request_timeout': timeout, 'p2_timeout' : 2, 'p2_star_timeout':2})
77+
self.udsclient.set_configs({'request_timeout': timeout, 'p2_timeout': 2, 'p2_star_timeout': 2})
7778
try:
7879
t1 = time.time()
7980
response = self.udsclient.send_request(req)
@@ -83,7 +84,7 @@ def _test_overall_timeout_pending_response(self):
8384
self.completed = True
8485
diff = time.time() - t1
8586
self.assertGreater(diff, timeout, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
86-
self.assertLess(diff, timeout+0.5, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
87+
self.assertLess(diff, timeout + 0.5, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
8788

8889
# Sends 2 "pending response" response to switch to P2* timeout.
8990
def test_p2_star_timeout(self):
@@ -94,9 +95,9 @@ def test_p2_star_timeout(self):
9495
self.conn.fromuserqueue.put(response.get_payload())
9596

9697
def _test_p2_star_timeout(self):
97-
req = Request(service = services.TesterPresent, subfunction=0)
98+
req = Request(service=services.TesterPresent, subfunction=0)
9899
timeout = 2
99-
self.udsclient.set_configs({'request_timeout': 5, 'p2_timeout' : 0.5, 'p2_star_timeout':timeout})
100+
self.udsclient.set_configs({'request_timeout': 5, 'p2_timeout': 0.5, 'p2_star_timeout': timeout})
100101
try:
101102
t1 = time.time()
102103
response = self.udsclient.send_request(req)
@@ -106,12 +107,12 @@ def _test_p2_star_timeout(self):
106107
self.completed = True
107108
diff = time.time() - t1
108109
self.assertGreater(diff, timeout, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
109-
self.assertLess(diff, timeout+0.5, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
110+
self.assertLess(diff, timeout + 0.5, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
110111

111112
# send RequestCorrectlyReceived_ResponsePending responses until well beyond overall_timeout to check response
112113
# This function is used in 2 tests:
113114
# * checking there is a timeout when the overall_timeout is repected
114-
# * checking that the full transaction is allowed to complete with the overall_timeout is ignored
115+
# * checking that the full transaction is allowed to complete with the overall_timeout is ignored
115116
def RCRRP_responses(self):
116117
self.conn.touserqueue.get(timeout=0.2)
117118
response = Response(service=services.TesterPresent, code=Response.Code.RequestCorrectlyReceived_ResponsePending)
@@ -121,15 +122,15 @@ def RCRRP_responses(self):
121122
time.sleep(0.1)
122123
response = Response(service=services.TesterPresent, code=Response.Code.PositiveResponse, data=bytes(2))
123124
self.conn.fromuserqueue.put(response.get_payload())
124-
125+
125126
def RCRRP_responses_check(self, respect_overall_timeout):
126-
req = Request(service = services.TesterPresent, subfunction=0)
127+
req = Request(service=services.TesterPresent, subfunction=0)
127128
overall_timeout = 2.0
128129
if not respect_overall_timeout:
129130
overall_timeout = None
130131
p2_star_timeout = 1.0
131132

132-
self.udsclient.set_configs({'request_timeout': overall_timeout, 'p2_timeout' : 0.5, 'p2_star_timeout':p2_star_timeout})
133+
self.udsclient.set_configs({'request_timeout': overall_timeout, 'p2_timeout': 0.5, 'p2_star_timeout': p2_star_timeout})
133134

134135
# Record our expectation on how long the timeout wlil be
135136
if respect_overall_timeout:
@@ -145,7 +146,7 @@ def RCRRP_responses_check(self, respect_overall_timeout):
145146
if respect_overall_timeout:
146147
diff = time.time() - t1
147148
self.assertGreater(diff, timeout, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
148-
self.assertLess(diff, timeout+0.5, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
149+
self.assertLess(diff, timeout + 0.5, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
149150
self.assertIsNotNone(self.udsclient.last_response, 'Client never received the PendingResponse message')
150151
else:
151152
raise Exception('Request raised a TimeoutException')
@@ -170,15 +171,15 @@ def _test_RCRRP_no_overall_timeout(self):
170171
def test_p2_star_timeout_overrided_by_diagnostic_session_control(self):
171172
self.conn.touserqueue.get(timeout=0.2)
172173
self.conn.fromuserqueue.put(b"\x50\x01\x03\xE8\x00\xC8") # Respond to diagnostic session control with timeout of 2 sec
173-
174+
174175
response = Response(service=services.TesterPresent, code=Response.Code.RequestCorrectlyReceived_ResponsePending)
175176
self.conn.fromuserqueue.put(response.get_payload())
176177
time.sleep(0.1)
177178
self.conn.fromuserqueue.put(response.get_payload())
178179

179180
def _test_p2_star_timeout_overrided_by_diagnostic_session_control(self):
180-
req = Request(service = services.TesterPresent, subfunction=0)
181-
self.udsclient.set_configs({'request_timeout': 5, 'p2_timeout' : 0.5, 'p2_star_timeout':1})
181+
req = Request(service=services.TesterPresent, subfunction=0)
182+
self.udsclient.set_configs({'request_timeout': 5, 'p2_timeout': 0.5, 'p2_star_timeout': 1})
182183
self.udsclient.change_session(1)
183184
timeout = 2
184185
try:
@@ -190,20 +191,19 @@ def _test_p2_star_timeout_overrided_by_diagnostic_session_control(self):
190191
self.completed = True
191192
diff = time.time() - t1
192193
self.assertGreater(diff, timeout, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
193-
self.assertLess(diff, timeout+0.5, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
194+
self.assertLess(diff, timeout + 0.5, 'Timeout raised after %.3f seconds when it should be %.3f sec' % (diff, timeout))
194195

195196
def test_payload_override_literal(self):
196197
request = self.conn.touserqueue.get(timeout=0.2)
197198
self.assertEqual(request, b'\x12\x34\x56\x78')
198199
self.conn.fromuserqueue.put(b"\x7E\x00")
199200

200201
def _test_payload_override_literal(self):
201-
req = Request(service = services.TesterPresent, subfunction=0)
202+
req = Request(service=services.TesterPresent, subfunction=0)
202203
with self.udsclient.payload_override(b'\x12\x34\x56\x78'):
203204
response = self.udsclient.send_request(req)
204205
self.assertEqual(response.original_payload, b'\x7E\x00')
205206

206-
207207
def test_payload_override_func(self):
208208
request = self.conn.touserqueue.get(timeout=0.2)
209209
self.assertEqual(request, b'\x99\x88\x77\x66')
@@ -213,7 +213,16 @@ def _test_payload_override_func(self):
213213
def func(payload):
214214
return b'\x99\x88\x77\x66'
215215

216-
req = Request(service = services.TesterPresent, subfunction=0)
216+
req = Request(service=services.TesterPresent, subfunction=0)
217217
with self.udsclient.payload_override(func):
218218
response = self.udsclient.send_request(req)
219-
self.assertEqual(response.original_payload, b'\x7E\x00')
219+
self.assertEqual(response.original_payload, b'\x7E\x00')
220+
221+
def test_request_in_response(self):
222+
self.conn.touserqueue.get(timeout=0.2)
223+
self.conn.fromuserqueue.put(b"\x7E\x00")
224+
225+
def _test_request_in_response(self):
226+
req = Request(service=services.TesterPresent, subfunction=0)
227+
response = self.udsclient.send_request(req)
228+
self.assertIs(response.original_request, req)

udsoncan/Request.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from udsoncan.BaseService import BaseService
2-
import udsoncan.tools as tools
32
import inspect
43
import struct
54

@@ -121,7 +120,7 @@ def from_payload(cls, payload: bytes) -> "Request":
121120
req = cls()
122121

123122
if len(payload) >= 1:
124-
req.service = tools.cls_from_request_id(payload[0])
123+
req.service = BaseService.from_request_id(payload[0])
125124
if req.service is not None: # Invalid service ID will make service None
126125
offset = 0
127126
if req.service.use_subfunction():

udsoncan/Response.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import inspect
44
import struct
55

6+
from udsoncan.Request import Request
7+
68
from typing import Type, Optional, Union
79

810

@@ -35,6 +37,10 @@ class Response:
3537
3638
(boolean) True if the response code is 0 (PositiveResponse), False otherwise
3739
40+
.. data:: unexpected
41+
42+
(boolean) Indicates that the response was unexpected. Set by an external source such as the :ref:`Client<Client>` object
43+
3844
.. data:: code
3945
4046
(int) The response code.
@@ -58,11 +64,10 @@ class Response:
5864
5965
(bytes) When the response is built with `Response.from_payload`, this property contains a copy of the payload used. None otherwise.
6066
61-
.. data:: unexpected
67+
.. data:: original_request
6268
63-
(boolean) Indicates that the response was unexpected. Set by an external source such as the :ref:`Client<Client>` object
69+
(Request) Optional reference to the request object that generated this response. """
6470

65-
"""
6671
Code = ResponseCode
6772

6873
service: Optional[Type[BaseService]]
@@ -71,6 +76,7 @@ class Response:
7176
suppress_positive_response: bool
7277
original_payload: Optional[bytes]
7378
service_data: Optional[BaseResponseData]
79+
original_request: Optional[Request]
7480

7581
def __init__(self,
7682
service: Optional[Union[BaseService, Type[BaseService]]] = None,
@@ -93,6 +99,7 @@ def __init__(self,
9399
self.service_data = None
94100
self.original_payload = None
95101
self.unexpected = False
102+
self.original_request = None
96103

97104
if data is not None:
98105
if not isinstance(data, bytes):

udsoncan/client.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def get_overrided_payload(self, original_payload: bytes) -> bytes:
100100
session_timing: SessionTiming
101101
logger: logging.Logger
102102

103-
def __init__(self, conn: BaseConnection, config: ClientConfig = default_client_config, request_timeout: Optional[bool] = None):
103+
def __init__(self, conn: BaseConnection, config: ClientConfig = default_client_config, request_timeout: Optional[float] = None):
104104
self.conn = conn
105105
self.config = cast(ClientConfig, dict(config)) # Makes a copy of given configuration
106106

@@ -2207,4 +2207,7 @@ def send_request(self, request: Request, timeout: int = -1) -> Optional[Response
22072207
assert response.service is not None
22082208
self.logger.info('Received positive response for service %s (0x%02x) from server.' %
22092209
(response.service.get_name(), response.service.request_id()))
2210+
2211+
response.original_request = request
2212+
22102213
return response

udsoncan/tools.py

-8
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,3 @@ def check_io_config(didlist: Union[int, List[int]], ioconfig: Dict[Any, Any]) ->
6060
}
6161

6262
return ioconfig
63-
64-
65-
def cls_from_request_id(given_id: int) -> Optional[Type[BaseService]]:
66-
return BaseService.from_request_id(given_id)
67-
68-
69-
def is_valid_service(service_cls: Type) -> bool:
70-
return issubclass(service_cls, BaseService)

0 commit comments

Comments
 (0)