From 165c2a2a4bce0e18e9c02713d2cdac2205eb92d1 Mon Sep 17 00:00:00 2001 From: mugdhadhole1 Date: Mon, 30 Sep 2024 14:31:27 +0530 Subject: [PATCH] Implemented unit tests of lobster_read function for valid data --- lobster/io.py | 3 +- test-unit/test_io.py | 280 ++++++++++++++++++++++++------------------- 2 files changed, 155 insertions(+), 128 deletions(-) diff --git a/lobster/io.py b/lobster/io.py index 3feb737b..22eb7292 100644 --- a/lobster/io.py +++ b/lobster/io.py @@ -77,8 +77,7 @@ def lobster_read(mh, filename, level, items, source_info=None): for rkey in ("schema", "version", "generator", "data"): if rkey not in data: - mh.error(loc, "required top-level key %s not present" % rkey) - return # Stop execution to avoid missing key error of next 'if' + mh.error(loc, "required top-levelkey %s not present" % rkey) if rkey == "data": if not isinstance(data[rkey], list): mh.error(loc, "data is not an array") diff --git a/test-unit/test_io.py b/test-unit/test_io.py index 331a4a11..3e7e5272 100644 --- a/test-unit/test_io.py +++ b/test-unit/test_io.py @@ -1,50 +1,34 @@ import unittest -from unittest.mock import ANY import io import json -from unittest.mock import patch, MagicMock, create_autospec, mock_open -from lobster.errors import Message_Handler +from unittest.mock import patch, create_autospec, mock_open, ANY +from lobster.errors import Message_Handler, LOBSTER_Error from lobster.location import File_Reference from lobster.items import Tracing_Tag, Requirement, Implementation, Activity from lobster.io import lobster_write, lobster_read from lobster.location import Location -class SetUp(unittest.TestCase): - mock_namespace = "mock_namespace" - mock_tag = "mock_tag" - mock_framework = "mock_framework" - mock_kind = "mock_kind" - mock_name = "mock_name" - mock_language = "mock_language" - mock_location = create_autospec(Location, instance = True) - tracing_tag = Tracing_Tag(mock_namespace, mock_tag) - requirement = Requirement(tracing_tag, mock_location, mock_framework, mock_kind, mock_name) - implementation = Implementation(tracing_tag, mock_location, mock_language, mock_kind, mock_name) - activity = Activity(tracing_tag, mock_location, mock_framework, mock_kind) - -class TestLobsterWrite(unittest.TestCase): - @patch("lobster.io.json") - @patch("lobster.items.Tracing_Tag.to_json") - @patch("lobster.items.Item.to_json") - def test_lobster_write_requirement(self, mock_item_to_json, mock_tracing_tag_to_json, mock_json): - self.generator = "mock_generator" - mock_tracing_tag_to_json.return_value = "mock_value" - mock_item_to_json.return_value = { - "tag": "mock_value", - "location": "mock_location", - "name": "mock_name", - "messages": ["message1", "message2"], - "just_up": True, - "just_down": False, - "just_global": True, - "refs": ["mock_value"], - "ref_up": ["mock_value"], - "ref_down": ["mock_value"], - "tracing_status": "mock_status" - } - - items = [SetUp.requirement] - exptected_value_req = { +class LobsterWriteReadTests(unittest.TestCase): + # unit tests for io.py file + + def setUp(self): + self.mock_namespace = "mock_namespace" + self.mock_tag = "mock_tag" + self.mock_framework = "mock_framework" + self.mock_kind = "mock_kind" + self.mock_name = "mock_name" + self.mock_language = "mock_language" + self.mock_location = create_autospec(Location, instance = True) + self.tracing_tag = Tracing_Tag(self.mock_namespace, self.mock_tag) + self.requirement = Requirement(self.tracing_tag, self.mock_location, self.mock_framework, self.mock_kind, self.mock_name) + self.implementation = Implementation(self.tracing_tag, self.mock_location, self.mock_language, self.mock_kind, self.mock_name) + self.activity = Activity(self.tracing_tag, self.mock_location, self.mock_framework, self.mock_kind) + self.mh = Message_Handler() + self.filename = "test.json" + self.level = "test_level" + self.items = {} + self.source_info = None + self.source_data = { "tag": "mock_value", "location": "mock_location", "name": "mock_name", @@ -55,21 +39,31 @@ def test_lobster_write_requirement(self, mock_item_to_json, mock_tracing_tag_to_ "refs": ["mock_value"], "ref_up": ["mock_value"], "ref_down": ["mock_value"], - "tracing_status": "mock_status", - "framework": "mock_framework", - "kind": "mock_kind", - "text": None, - "status": None } + + @patch("lobster.io.json") + @patch("lobster.items.Tracing_Tag.to_json") + @patch("lobster.items.Item.to_json") + def test_lobster_write_requirement(self, mock_item_to_json, mock_tracing_tag_to_json, mock_json): + self.generator = "mock_generator" + mock_tracing_tag_to_json.return_value = "mock_value" + self.source_data["tracing_status"] = "mock_status" + mock_item_to_json.return_value = self.source_data + items = [self.requirement] + self.source_data["tracing_status"] = "mock_status" + self.source_data["framework"] = "mock_framework" + self.source_data["kind"] = "mock_kind" + self.source_data["text"] = None + self.source_data["status"] = None fd_req = io.StringIO() mock_data = { - "data" : [exptected_value_req], + "data" : [self.source_data], "generator" : self.generator, "schema" : "lobster-req-trace", "version" : 4 } lobster_write(fd_req, Requirement, self.generator, items) - fd_req.seek(0) + fd_req.seek(0) mock_json.dump.assert_called_once_with(mock_data, fd_req, indent=2) @patch("lobster.io.json") @@ -78,40 +72,17 @@ def test_lobster_write_requirement(self, mock_item_to_json, mock_tracing_tag_to_ def test_lobster_write_implementation(self, mock_item_to_json, mock_tracing_tag_to_json, mock_json): self.generator = "mock_generator" mock_tracing_tag_to_json.return_value = "mock_value" - mock_item_to_json.return_value = { - "tag": "mock_value", - "location": "mock_location", - "name": "mock_name", - "messages": ["message1", "message2"], - "just_up": True, - "just_down": False, - "just_global": True, - "refs": ["mock_value"], - "ref_up": ["mock_value"], - "ref_down": ["mock_value"], - "tracing_status": "mock_status" - } - items = [SetUp.implementation] - exptected_value_imp = { - "tag": "mock_value", - "location": "mock_location", - "name": "mock_name", - "messages": ["message1", "message2"], - "just_up": True, - "just_down": False, - "just_global": True, - "refs": ["mock_value"], - "ref_up": ["mock_value"], - "ref_down": ["mock_value"], - "tracing_status": "mock_status", - "language": "mock_language", - "kind": "mock_kind" - } + self.source_data["tracing_status"] = "mock_status" + mock_item_to_json.return_value = self.source_data + items = [self.implementation] + self.source_data["tracing_status"] = "mock_status" + self.source_data["language"] = "mock_language" + self.source_data["kind"] = "mock_kind" fd_imp = io.StringIO() lobster_write(fd_imp, Implementation, self.generator, items) fd_imp.seek(0) mock_data = { - "data" : [exptected_value_imp], + "data" : [self.source_data], "generator" : self.generator, "schema" : "lobster-imp-trace", "version" : 3 @@ -124,73 +95,130 @@ def test_lobster_write_implementation(self, mock_item_to_json, mock_tracing_tag_ def test_lobster_write_activity(self, mock_item_to_json, mock_tracing_tag_to_json, mock_json): self.generator = "mock_generator" mock_tracing_tag_to_json.return_value = "mock_value" - mock_item_to_json.return_value = { - "tag": "mock_value", - "location": "mock_location", - "name": "mock_name", - "messages": ["message1", "message2"], - "just_up": True, - "just_down": False, - "just_global": True, - "refs": ["mock_value"], - "ref_up": ["mock_value"], - "ref_down": ["mock_value"], - "tracing_status": "mock_status" - } - items = [SetUp.activity] - exptected_value_act = { - "tag": "mock_value", - "location": "mock_location", - "name": "mock_name", - "messages": ["message1", "message2"], - "just_up": True, - "just_down": False, - "just_global": True, - "refs": ["mock_value"], - "ref_up": ["mock_value"], - "ref_down": ["mock_value"], - "tracing_status": "mock_status", - "framework": "mock_framework", - "kind": "mock_kind", - "status": None - } + self.source_data["tracing_status"] = "mock_status" + mock_item_to_json.return_value = self.source_data + items = [self.activity] + self.source_data["tracing_status"] = "mock_status" + self.source_data["framework"] = "mock_framework" + self.source_data["kind"] = "mock_kind" + self.source_data["status"] = None fd_act = io.StringIO() lobster_write(fd_act, Activity, self.generator, items) fd_act.seek(0) mock_data = { - "data" : [exptected_value_act], + "data" : [self.source_data], "generator" : self.generator, "schema" : "lobster-act-trace", "version" : 3 } mock_json.dump.assert_called_once_with(mock_data, fd_act, indent=2) - - def setUp(self): - self.mh = MagicMock(spec=Message_Handler) - self.filename = "test.json" - self.level = "test_level" - self.items = {} - self.source_info = None - @patch("os.path.isfile", return_value=True) - @patch("builtins.open", new_callable=unittest.mock.mock_open, read_data='{"schema": "lobster-req-trace", "version": 4, "generator": "mock_generator", "data": []}') - def test_lobster_read_valid(self, mock_open, mock_isfile): - lobster_read(self.mh, self.filename, self.level, self.items, self.source_info) - self.mh.error.assert_not_called() - self.assertEqual(len(self.items), 0) + @patch("lobster.items.Item.additional_data_from_json") + @patch("lobster.items.Tracing_Tag.key") + @patch("lobster.items.Tracing_Tag.from_json") + def test_lobster_read_valid_requirement(self, mock_from_json, mock_key, mock_additional_data_from_json): + mock_key.return_value = "mock_namespace mock_tag" + mock_from_json.return_value = self.tracing_tag + self.source_data.update({"location" : { + "kind": "file", + "file": "example.txt" + }}) + self.source_data["tracing_status"] = "mock_status" + self.source_data["framework"] = "mock_framework" + self.source_data["kind"] = "mock_kind" + self.source_data["text"] = None + self.source_data["status"] = None + mock_data_req = { + "schema" : "lobster-req-trace", + "version" : 4, + "generator" : "mock_generator", + "data" : [self.source_data] + } + read_data = json.dumps(mock_data_req, indent=4) + with patch("os.path.isfile", return_value=True): + with patch("builtins.open", mock_open(read_data=read_data)): + lobster_read(self.mh, self.filename, self.level, self.items, self.source_info) + self.assertEqual(len(self.items), 1) + mock_additional_data_from_json.assert_called_once_with(self.level, self.source_data, mock_data_req["version"]) + + @patch("lobster.items.Item.additional_data_from_json") + @patch("lobster.items.Tracing_Tag.key") + @patch("lobster.items.Tracing_Tag.from_json") + def test_lobster_read_valid_implementation(self, mock_from_json, mock_key, mock_additional_data_from_json): + mock_key.return_value = "mock_namespace mock_tag" + mock_from_json.return_value = self.tracing_tag + self.source_data.update({"location" : { + "kind": "file", + "file": "example.txt" + }}) + self.source_data["tracing_status"] = "mock_status" + self.source_data["language"] = "mock_language" + self.source_data["kind"] = "mock_kind" + mock_data_imp = { + "schema" : "lobster-imp-trace", + "version" : 3, + "generator" : "mock_generator", + "data" : [self.source_data] + } + read_data = json.dumps(mock_data_imp, indent=4) + with patch("os.path.isfile", return_value=True): + with patch("builtins.open", mock_open(read_data=read_data)): + lobster_read(self.mh, self.filename, self.level, self.items, self.source_info) + self.assertEqual(len(self.items), 1) + mock_additional_data_from_json.assert_called_once_with(self.level, self.source_data, mock_data_imp["version"]) + + @patch("lobster.items.Item.additional_data_from_json") + @patch("lobster.items.Tracing_Tag.key") + @patch("lobster.items.Tracing_Tag.from_json") + def test_lobster_read_valid_activity(self, mock_from_json, mock_key, mock_additional_data_from_json): + mock_key.return_value = "mock_namespace mock_tag" + mock_from_json.return_value = self.tracing_tag + self.source_data.update({"location" : { + "kind": "file", + "file": "example.txt" + }}) + self.source_data["tracing_status"] = "mock_status" + self.source_data["framework"] = "mock_framework" + self.source_data["kind"] = "mock_kind" + self.source_data["status"] = None + mock_data_act = { + "schema" : "lobster-act-trace", + "version" : 3, + "generator" : "mock_generator", + "data" : [self.source_data] + } + read_data = json.dumps(mock_data_act, indent=4) + with patch("os.path.isfile", return_value=True): + with patch("builtins.open", mock_open(read_data=read_data)): + lobster_read(self.mh, self.filename, self.level, self.items, self.source_info) + self.assertEqual(len(self.items), 1) + mock_additional_data_from_json.assert_called_once_with(self.level, self.source_data, mock_data_act["version"]) @patch("os.path.isfile", return_value=True) @patch("builtins.open", new_callable=unittest.mock.mock_open, read_data='{"schema": "lobster-req-trace", "version": 4, "generator": "mock_generator"}') - def test_lobster_read_missing_data_key(self, mock_open, mock_isfile): - lobster_read(self.mh, self.filename, self.level, self.items, self.source_info) - # Allow any File_Reference object, but striclty check the string of the error message - self.mh.error.assert_called_with(ANY, "required top-level key data not present") + def test_lobster_read_missing_data_key(self, mock_open, mock_isfile): + with self.assertRaises(LOBSTER_Error): + lobster_read(self.mh, self.filename, self.level, self.items, self.source_info) + self.mh.error.assert_called_with(ANY, "required top-level key data not present") + + @patch("os.path.isfile", return_value=True) + @patch("builtins.open", new_callable=unittest.mock.mock_open, read_data='{"schema": "lobster-req-trace", "version": 5, "generator": "test_gen", "data": []}') + def test_lobster_read_unsupported_version(self, mock_open, mock_isfile): + with self.assertRaises(LOBSTER_Error): + lobster_read(self.mh, self.filename, self.level, self.items, self.source_info) + self.mh.error.assert_called_with(File_Reference(self.filename), "version 5 for schema lobster-req-trace is not supported") + + @patch("os.path.isfile", return_value=True) + @patch("builtins.open", new_callable=unittest.mock.mock_open, read_data='{"schema": "unknown-schema", "version": 4, "generator": "test_gen", "data": []}') + def test_lobster_read_unknown_schema(self, mock_open, mock_isfile): + with self.assertRaises(LOBSTER_Error): + lobster_read(self.mh, self.filename, self.level, self.items, self.source_info) @patch("os.path.isfile", return_value=True) @patch("builtins.open", new_callable=mock_open, read_data='invalid') def test_lobster_read_invalid_json(self, mock_open, mock_isfile): - lobster_read(self.mh, self.filename, self.level, self.items, self.source_info) - self.mh.error.assert_called() + with self.assertRaises(LOBSTER_Error): + lobster_read(self.mh, self.filename, self.level, self.items, self.source_info) @patch("os.path.isfile", return_value=False) def test_lobster_read_file_not_found(self, mock_isfile):