diff --git a/tests/st/func/datavisual/histogram/__init__.py b/tests/st/func/datavisual/histogram/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e30774307ca2107b3a81c071ad33c042ef924790 --- /dev/null +++ b/tests/st/func/datavisual/histogram/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2020 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ diff --git a/tests/st/func/datavisual/histogram/test_histogram_restful_api.py b/tests/st/func/datavisual/histogram/test_histogram_restful_api.py new file mode 100644 index 0000000000000000000000000000000000000000..f693d499a5082d202f7918972f94cc7018761add --- /dev/null +++ b/tests/st/func/datavisual/histogram/test_histogram_restful_api.py @@ -0,0 +1,55 @@ +# Copyright 2020 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +""" +Function: + Test histograms restful api. +Usage: + pytest tests/st/func/datavisual +""" +import pytest + +from mindinsight.datavisual.common.enums import PluginNameEnum + +from .....utils.tools import get_url +from .. import globals as gbl + +BASE_URL = '/v1/mindinsight/datavisual/histograms' + + +class TestHistograms: + """Test Histograms.""" + + @pytest.mark.level0 + @pytest.mark.env_single + @pytest.mark.platform_x86_cpu + @pytest.mark.platform_arm_ascend_training + @pytest.mark.platform_x86_gpu_training + @pytest.mark.platform_x86_ascend_training + @pytest.mark.usefixtures("init_summary_logs") + def test_histograms(self, client): + """Test getting histogram data.""" + plugin_name = PluginNameEnum.HISTOGRAM.value + train_id = gbl.get_train_ids()[0] + tag_name = gbl.get_tags(train_id, plugin_name)[0] + expected_histograms = gbl.get_metadata(train_id, tag_name) + + params = dict(train_id=train_id, tag=tag_name) + url = get_url(BASE_URL, params) + response = client.get(url) + histograms = response.get_json().get("histograms") + + for histograms, expected_histograms in zip(histograms, expected_histograms): + assert histograms.get("wall_time") == expected_histograms.get("wall_time") + assert histograms.get("step") == expected_histograms.get("step") diff --git a/tests/ut/backend/datavisual/conftest.py b/tests/ut/backend/datavisual/conftest.py index 431dc03e213efc5deae5a470fa1f014d5c9ea3a8..a75c248d5879eebe95e80ab4aa20d1c0870fddcf 100644 --- a/tests/ut/backend/datavisual/conftest.py +++ b/tests/ut/backend/datavisual/conftest.py @@ -54,5 +54,6 @@ TRAIN_ROUTES = dict( graph_single_node='/v1/mindinsight/datavisual/graphs/single-node', image_metadata='/v1/mindinsight/datavisual/image/metadata', image_single_image='/v1/mindinsight/datavisual/image/single-image', - scalar_metadata='/v1/mindinsight/datavisual/scalar/metadata' + scalar_metadata='/v1/mindinsight/datavisual/scalar/metadata', + histograms='/v1/mindinsight/datavisual/histograms' ) diff --git a/tests/ut/backend/datavisual/test_train_visual_api.py b/tests/ut/backend/datavisual/test_train_visual_api.py index 831edbf34c2e5175ecad42ba6e8a4fd116628c16..08d56a25a5ce2a2b914e3390ce0ed7450af9e078 100644 --- a/tests/ut/backend/datavisual/test_train_visual_api.py +++ b/tests/ut/backend/datavisual/test_train_visual_api.py @@ -26,6 +26,7 @@ from mindinsight.datavisual.data_transform.graph import NodeTypeEnum from mindinsight.datavisual.processors.graph_processor import GraphProcessor from mindinsight.datavisual.processors.images_processor import ImageProcessor from mindinsight.datavisual.processors.scalars_processor import ScalarsProcessor +from mindinsight.datavisual.processors.histogram_processor import HistogramProcessor from ....utils.tools import get_url from .conftest import TRAIN_ROUTES @@ -432,3 +433,42 @@ class TestTrainVisual: assert response.status_code == 200 results = response.get_json() assert results == test_name + + def test_histograms_with_params_miss(self, client): + """Parsing missing params to get histogram data.""" + params = dict() + url = get_url(TRAIN_ROUTES['histograms'], params) + response = client.get(url) + results = response.get_json() + assert response.status_code == 400 + assert results['error_code'] == '50540003' + assert results['error_msg'] == "Param missing. 'train_id' is required." + + train_id = "aa" + params = dict(train_id=train_id) + url = get_url(TRAIN_ROUTES['histograms'], params) + response = client.get(url) + results = response.get_json() + assert response.status_code == 400 + assert results['error_code'] == '50540003' + assert results['error_msg'] == "Param missing. 'tag' is required." + + @patch.object(HistogramProcessor, 'get_histograms') + def test_histograms_success(self, mock_histogram_processor, client): + """Parsing available params to get histogram data.""" + test_train_id = "aa" + test_tag = "bb" + expect_resp = { + 'histograms': [{'buckets': [[1, 2, 3]]}], + 'train_id': test_train_id, + 'tag': test_tag + } + get_histograms = Mock(return_value=expect_resp) + mock_histogram_processor.side_effect = get_histograms + + params = dict(train_id=test_train_id, tag=test_tag) + url = get_url(TRAIN_ROUTES['histograms'], params) + response = client.get(url) + assert response.status_code == 200 + results = response.get_json() + assert results == expect_resp diff --git a/tests/ut/datavisual/processors/test_histogram_processor.py b/tests/ut/datavisual/processors/test_histogram_processor.py new file mode 100644 index 0000000000000000000000000000000000000000..638d2115fe4c3a00fc4b2fe412c7869559cb1309 --- /dev/null +++ b/tests/ut/datavisual/processors/test_histogram_processor.py @@ -0,0 +1,117 @@ +# Copyright 2020 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +""" +Function: + Test histogram processor. +Usage: + pytest tests/ut/datavisual +""" +import tempfile +from unittest.mock import Mock + +import pytest + +from mindinsight.datavisual.common.enums import PluginNameEnum +from mindinsight.datavisual.common.exceptions import TrainJobNotExistError +from mindinsight.datavisual.common.exceptions import HistogramNotExistError +from mindinsight.datavisual.data_transform import data_manager +from mindinsight.datavisual.data_transform.loader_generators.data_loader_generator import DataLoaderGenerator +from mindinsight.datavisual.processors.histogram_processor import HistogramProcessor +from mindinsight.datavisual.utils import crc32 + +from ....utils.log_operations import LogOperations +from ....utils.tools import check_loading_done, delete_files_or_dirs +from ..mock import MockLogger + + +class TestHistogramProcessor: + """Test histogram processor api.""" + _steps_list = [1, 3, 5] + _tag_name = 'tag_name' + _plugin_name = 'histogram' + _complete_tag_name = f'{_tag_name}/{_plugin_name}' + + _temp_path = None + _histograms = None + _mock_data_manager = None + _train_id = None + + _generated_path = [] + + @classmethod + def setup_class(cls): + """Mock common environment for histograms unittest.""" + crc32.CheckValueAgainstData = Mock(return_value=True) + data_manager.logger = MockLogger + + def teardown_class(self): + """Delete temp files.""" + delete_files_or_dirs(self._generated_path) + + @pytest.fixture(scope='function') + def load_histogram_record(self): + """Load histogram record.""" + summary_base_dir = tempfile.mkdtemp() + log_dir = tempfile.mkdtemp(dir=summary_base_dir) + self._train_id = log_dir.replace(summary_base_dir, ".") + + log_operation = LogOperations() + self._temp_path, self._histograms, _ = log_operation.generate_log( + PluginNameEnum.HISTOGRAM.value, log_dir, dict(step=self._steps_list, tag=self._tag_name)) + self._generated_path.append(summary_base_dir) + + self._mock_data_manager = data_manager.DataManager([DataLoaderGenerator(summary_base_dir)]) + self._mock_data_manager.start_load_data(reload_interval=0) + + # wait for loading done + check_loading_done(self._mock_data_manager, time_limit=5) + + @pytest.mark.usefixtures('load_histogram_record') + def test_get_histograms_with_not_exist_id(self): + """Get histogram data with not exist id.""" + test_train_id = 'not_exist_id' + processor = HistogramProcessor(self._mock_data_manager) + with pytest.raises(TrainJobNotExistError) as exc_info: + processor.get_histograms(test_train_id, self._tag_name) + + assert exc_info.value.error_code == '50545005' + assert exc_info.value.message == "Train job is not exist. Detail: Can not find the given train job in cache." + + @pytest.mark.usefixtures('load_histogram_record') + def test_get_histograms_with_not_exist_tag(self): + """Get histogram data with not exist tag.""" + test_tag_name = 'not_exist_tag_name' + + processor = HistogramProcessor(self._mock_data_manager) + + with pytest.raises(HistogramNotExistError) as exc_info: + processor.get_histograms(self._train_id, test_tag_name) + + assert exc_info.value.error_code == '5054500F' + assert "Can not find any data in this train job by given tag." in exc_info.value.message + + @pytest.mark.usefixtures('load_histogram_record') + def test_get_histograms_success(self): + """Get histogram data success.""" + test_tag_name = self._complete_tag_name + + processor = HistogramProcessor(self._mock_data_manager) + results = processor.get_histograms(self._train_id, test_tag_name) + + recv_metadata = results.get('histograms') + + for recv_values, expected_values in zip(recv_metadata, self._histograms): + assert recv_values.get('wall_time') == expected_values.get('wall_time') + assert recv_values.get('step') == expected_values.get('step')