Skip to content

Commit

Permalink
Fix block to handle Put requests properly
Browse files Browse the repository at this point in the history
Similar to method post requests, push a "to return" message to the
process queue so the return is received *after* update to the attribute
has been seen.
  • Loading branch information
c-mita committed Jun 22, 2016
1 parent a1e6b0a commit 18d7da0
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 26 deletions.
24 changes: 12 additions & 12 deletions malcolm/core/block.py
Expand Up @@ -3,6 +3,8 @@

from malcolm.core.monitorable import Monitorable
from malcolm.core.process import BlockRespond
from malcolm.core.request import Request
from malcolm.core.response import Response

@contextmanager
def dummy_lock():
Expand Down Expand Up @@ -59,21 +61,19 @@ def handle_request(self, request):
request(Request): Request object specifying action
"""
self.log_debug("Received request %s", request)
assert request.type_ == Request.POST or request.type_ == Request.PUT, \
"Expected Post or Put request, received %s" % request.type_
with self.lock:
if request.type_ == request.POST:
if request.type_ == Request.POST:
method_name = request.endpoint[-1]
response = self._methods[method_name].get_response(request)
response = BlockRespond(response, request.response_queue)
self.parent.q.put(response)
else:
layer = self
for next_link in request.endpoint[1:]:
layer = getattr(layer, next_link)

if hasattr(layer, "to_dict"):
request.respond_with_return(layer.to_dict())
else:
request.respond_with_return(layer)
elif request.type_ == Request.PUT:
attr_name = request.endpoint[-1]
self._attributes[attr_name].put(request.value)
self._attributes[attr_name].set_value(request.value)
response = Response.Return(request.id_, request.context)
response = BlockRespond(response, request.response_queue)
self.parent.q.put(response)

def to_dict(self):
"""Convert object attributes into a dictionary"""
Expand Down
32 changes: 18 additions & 14 deletions tests/test_core/test_block.py
Expand Up @@ -96,40 +96,44 @@ def setUp(self):
self.block.parent = MagicMock()
self.method = MagicMock()
self.method.name = "get_things"
self.attribute = MagicMock()
self.attribute.name = "test_attribute"
self.response = MagicMock()
self.block.add_method(self.method)
self.block.add_attribute(self.attribute)

def test_given_request_then_pass_to_correct_method(self):
request = MagicMock()
request.POST = "Post"
request.type_ = "Post"
request.endpoint = ["TestBlock", "device", "get_things"]

self.block.handle_request(request)

self.method.get_response.assert_called_once_with(request)
response = self.block.parent.q.put.call_args[0][0]
self.assertEqual(self.method.get_response.return_value,
response.response)

def test_given_get_then_return_attribute(self):
self.block.state = MagicMock()
self.block.state.value = "Running"
def test_given_put_then_update_attribute(self):
put_value = MagicMock()
request = MagicMock()
request.type_ = "Get"
request.endpoint = ["TestBlock", "state", "value"]
request.type_ = "Put"
request.endpoint = ["TestBlock", "test_attribute"]
request.value = put_value

self.block.handle_request(request)

request.respond_with_return.assert_called_once_with("Running")
self.attribute.put.assert_called_once_with(put_value)
self.attribute.set_value.assert_called_once_with(put_value)
response = self.block.parent.q.put.call_args[0][0]
self.assertEqual("Return", response.response.type_)
self.assertIsNone(response.response.value)

def test_given_get_block_then_return_self(self):
def test_invalid_request_fails(self):
request = MagicMock()
request.type_ = "Get"
request.endpoint = ["TestBlock"]
expected_call = self.block.to_dict()

self.block.handle_request(request)

request.respond_with_return.assert_called_once_with(expected_call)

self.assertRaises(AssertionError, self.block.handle_request, request)

if __name__ == "__main__":
unittest.main(verbosity=2)

0 comments on commit 18d7da0

Please sign in to comment.