提交 665f2d68 编写于 作者: L luopengting

modify lineage parsing for multi lineage files, modify ut/st

上级 f3b621a9
......@@ -72,7 +72,7 @@ class _BasicTrainJob:
self._update_time = update_time
@property
def summary_dir(self):
def abs_summary_dir(self):
"""Get summary directory path."""
return self._abs_summary_dir
......@@ -131,9 +131,9 @@ class CachedTrainJob:
return self._last_access_time
@property
def summary_dir(self):
def abs_summary_dir(self):
"""Get summary directory path."""
return self._basic_info.summary_dir
return self._basic_info.abs_summary_dir
@property
def summary_base_dir(self):
......@@ -144,12 +144,33 @@ class CachedTrainJob:
"""Set value to cache."""
self._content[key] = value
def get(self, key):
"""Get value from cache."""
def delete(self, key):
"""Delete key in cache."""
if key in self._content:
self._content.pop(key)
def get(self, key, raise_exception=True):
"""
Get value from cache.
Args:
key (str): Key of content.
raise_exception (bool): If the key does not exist and
raise_exception is True, it will raise an Exception.
Returns:
Union[Object, None], Return value if key in content,
return False else if raise_exception is False.
Raises:
ParamValueError, if the key does not exist and raise_exception is True.
"""
try:
return self._content[key]
except KeyError:
raise ParamValueError("Invalid cache key({}).".format(key))
if raise_exception:
raise ParamValueError("Invalid cache key({}).".format(key))
return None
@property
def basic_info(self):
......@@ -163,9 +184,7 @@ class CachedTrainJob:
def lock_key(self, key):
"""Threading lock with given key."""
if key not in self._key_locks:
self._key_locks[key] = threading.Lock()
return self._key_locks[key]
return self._key_locks.setdefault(key, threading.Lock())
class TrainJob:
......
......@@ -96,11 +96,8 @@ def general_get_summary_lineage(data_manager=None, summary_dir=None, keys=None):
if data_manager is None:
normalize_summary_dir(summary_dir)
super_lineage_obj = None
if os.path.isabs(summary_dir):
super_lineage_obj = LineageParser(summary_dir).super_lineage_obj
elif data_manager is not None:
else:
validate_train_id(summary_dir)
super_lineage_obj = LineageOrganizer(data_manager=data_manager).get_super_lineage_obj(summary_dir)
......
......@@ -27,15 +27,19 @@ def update_lineage_object(data_manager, train_id, added_info: dict):
"""Update lineage objects about tag and remark."""
validate_train_id(train_id)
cache_item = data_manager.get_brief_train_job(train_id)
cached_added_info = cache_item.get(key=LINEAGE).added_info
lineage_item = cache_item.get(key=LINEAGE, raise_exception=False)
if lineage_item is None:
logger.warning("Cannot update the lineage for tran job %s, because it does not exist.", train_id)
raise ParamValueError("Cannot update the lineage for tran job %s, because it does not exist." % train_id)
cached_added_info = lineage_item.super_lineage_obj.added_info
new_added_info = dict(cached_added_info)
for key, value in added_info.items():
if key in ["tag", "remark"]:
new_added_info.update({key: value})
new_added_info.update({key: value})
with cache_item.lock_key(LINEAGE):
cache_item.get(key=LINEAGE).added_info = new_added_info
cache_item.get(key=LINEAGE).super_lineage_obj.added_info = new_added_info
class LineageCacheItemUpdater(BaseCacheItemUpdater):
......@@ -44,8 +48,7 @@ class LineageCacheItemUpdater(BaseCacheItemUpdater):
def update_item(self, cache_item: CachedTrainJob):
"""Update cache item in place."""
summary_base_dir = cache_item.summary_base_dir
summary_dir = cache_item.summary_dir
update_time = cache_item.basic_info.update_time
summary_dir = cache_item.abs_summary_dir
# The summary_base_dir and summary_dir have been normalized in data_manager.
if summary_base_dir == summary_dir:
......@@ -54,17 +57,31 @@ class LineageCacheItemUpdater(BaseCacheItemUpdater):
relative_path = f'./{os.path.basename(summary_dir)}'
try:
cached_added_info = cache_item.get(key=LINEAGE).added_info
except ParamValueError:
cached_added_info = None
try:
lineage_parser = LineageParser(summary_dir, update_time, cached_added_info)
super_lineage_obj = lineage_parser.super_lineage_obj
lineage_parser = self._lineage_parsing(cache_item)
except LineageFileNotFoundError:
super_lineage_obj = None
with cache_item.lock_key(LINEAGE):
cache_item.delete(key=LINEAGE)
return
super_lineage_obj = lineage_parser.super_lineage_obj
if super_lineage_obj is None:
logger.warning("There is no lineage to update in tran job %s.", relative_path)
return
with cache_item.lock_key(LINEAGE):
cache_item.set(key=LINEAGE, value=super_lineage_obj)
cache_item.set(key=LINEAGE, value=lineage_parser)
def _lineage_parsing(self, cache_item):
"""Parse summaries and return lineage parser."""
summary_dir = cache_item.abs_summary_dir
update_time = cache_item.basic_info.update_time
cached_lineage_item = cache_item.get(key=LINEAGE, raise_exception=False)
if cached_lineage_item is None:
lineage_parser = LineageParser(summary_dir, update_time)
else:
lineage_parser = cached_lineage_item
with cache_item.lock_key(LINEAGE):
lineage_parser.update_time = update_time
lineage_parser.load()
return lineage_parser
......@@ -13,9 +13,10 @@
# limitations under the License.
# ============================================================================
"""This file provides path resolution."""
import os
from mindinsight.datavisual.data_transform.summary_watcher import SummaryWatcher
from mindinsight.lineagemgr.common.log import logger
from mindinsight.lineagemgr.common.utils import get_timestamp
from mindinsight.utils.exceptions import MindInsightException
class SummaryPathParser:
......@@ -29,121 +30,36 @@ class SummaryPathParser:
_LINEAGE_SUMMARY_SUFFIX_LEN = len(LINEAGE_SUMMARY_SUFFIX)
@staticmethod
def get_summary_dirs(summary_base_dir):
"""
Get summary dirs according to summary base dir.
Args:
summary_base_dir (str): Summary base dir.
Returns:
list[str], all summary dirs in summary base dir. The summary dir is
absolute path.
"""
summary_watcher = SummaryWatcher()
relative_dirs = summary_watcher.list_summary_directories(
summary_base_dir=summary_base_dir
)
summary_dirs = list(
map(
lambda item: os.path.realpath(
os.path.join(summary_base_dir, item.get('relative_path'))
),
relative_dirs
)
)
return summary_dirs
@staticmethod
def get_latest_lineage_summary(summary_dir):
def get_lineage_summaries(summary_dir, is_sorted=False, reverse=True):
"""
Get latest lineage summary log path according to summary dir.
Get lineage summaries according to summary dir.
Args:
summary_dir (str): Summary dir.
is_sorted (bool): If it is True, files will be sorted.
reverse (bool): If it is True, sort by timestamp increments and filename decrement.
Returns:
Union[str, None], if the lineage summary log exist, return the path,
else return None. The lineage summary log path is absolute path.
"""
summary_watcher = SummaryWatcher()
summaries = summary_watcher.list_summaries(summary_base_dir=summary_dir)
latest_file_name = SummaryPathParser._get_latest_lineage_file(summaries)
return os.path.join(summary_dir, latest_file_name) \
if latest_file_name is not None else None
@staticmethod
def get_latest_lineage_summaries(summary_base_dir):
"""
Get all latest lineage summary logs in summary base dir.
Args:
summary_base_dir (str): Summary base dir.
Returns:
list[str], all latest lineage summary logs in summary base dir. The
lineage summary log is absolute path.
"""
summary_watcher = SummaryWatcher()
relative_dirs = summary_watcher.list_summary_directories(
summary_base_dir=summary_base_dir
)
latest_summaries = []
for item in relative_dirs:
relative_dir = item.get('relative_path')
summaries = summary_watcher.list_summaries(
summary_base_dir=summary_base_dir,
relative_path=relative_dir
)
latest_file_name = SummaryPathParser._get_latest_lineage_file(
summaries
)
if latest_file_name is None:
continue
latest_file = os.path.realpath(
os.path.join(
summary_base_dir,
relative_dir,
latest_file_name
)
)
latest_summaries.append(latest_file)
return latest_summaries
@staticmethod
def _get_latest_lineage_file(summaries):
"""
Get latest lineage summary file.
If there is a file with the suffix `LINEAGE_SUMMARY_SUFFIX`, check
whether there is a file with the same name that does not include the
suffix `LINEAGE_SUMMARY_SUFFIX`. When both exist, the file is considered
to be a lineage summary log.
Args:
summaries (list[dict]): All summary logs info in summary dir.
Returns:
str, the latest lineage summary file name.
list, if the lineage summary log exist, return the file names, else return [].
"""
try:
latest_summary = max(
summaries,
key=lambda summary: summary.get('create_time')
)
except ValueError:
return None
max_create_time = latest_summary.get('create_time')
summary_file_names = []
for summary in summaries:
if summary.get('create_time') == max_create_time:
summary_file_names.append(summary.get('file_name'))
summary_watcher = SummaryWatcher()
summaries = summary_watcher.list_summaries(summary_base_dir=summary_dir)
except MindInsightException as err:
logger.warning(str(err))
return []
summary_files = [summary.get('file_name') for summary in summaries]
lineage_files_name = list(filter(
lambda filename: (filename.endswith(SummaryPathParser.LINEAGE_SUMMARY_SUFFIX)), summary_files))
if is_sorted:
lineage_files_name = SummaryPathParser._sorted_summary_files(lineage_files_name, reverse)
return lineage_files_name
latest_lineage_name = None
for name in summary_file_names:
if not name.endswith(SummaryPathParser.LINEAGE_SUMMARY_SUFFIX):
continue
ms_name = name[:-SummaryPathParser._LINEAGE_SUMMARY_SUFFIX_LEN]
if ms_name in summary_file_names:
latest_lineage_name = name
return latest_lineage_name
@staticmethod
def _sorted_summary_files(summary_files, reverse):
"""Sort by timestamp increments and filename decrement."""
sorted_files = sorted(summary_files,
key=lambda filename: (-get_timestamp(filename), filename),
reverse=reverse)
return sorted_files
......@@ -14,7 +14,9 @@
# ============================================================================
"""Lineage utils."""
from functools import wraps
import re
from mindinsight.datavisual.data_transform.summary_watcher import SummaryWatcher
from mindinsight.lineagemgr.common.log import logger as log
from mindinsight.lineagemgr.common.exceptions.exceptions import LineageParamRunContextError, \
LineageGetModelFileError, LineageLogError, LineageParamValueError, LineageDirNotExistError, \
......@@ -68,3 +70,9 @@ def normalize_summary_dir(summary_dir):
log.exception(error)
raise LineageParamSummaryPathError(str(error.message))
return summary_dir
def get_timestamp(filename):
"""Get timestamp from filename."""
timestamp = int(re.search(SummaryWatcher().SUMMARY_FILENAME_REGEX, filename)[1])
return timestamp
......@@ -21,6 +21,7 @@ from mindinsight.lineagemgr.common.exceptions.exceptions import LineageSummaryAn
MindInsightException
from mindinsight.lineagemgr.common.log import logger
from mindinsight.lineagemgr.common.path_parser import SummaryPathParser
from mindinsight.lineagemgr.summary.file_handler import FileHandler
from mindinsight.lineagemgr.summary.lineage_summary_analyzer import LineageSummaryAnalyzer
from mindinsight.lineagemgr.querier.query_model import LineageObj
from mindinsight.utils.exceptions import ParamValueError
......@@ -30,7 +31,7 @@ LINEAGE = "lineage"
class SuperLineageObj:
"""This is an object for LineageObj and its additional info."""
def __init__(self, lineage_obj, update_time, added_info=None):
def __init__(self, lineage_obj: LineageObj, update_time, added_info=None):
self._lineage_obj = lineage_obj
self._update_time = update_time
self._added_info = added_info if added_info is not None else dict()
......@@ -59,11 +60,60 @@ class SuperLineageObj:
class LineageParser:
"""Lineage parser."""
def __init__(self, summary_dir, update_time=None, added_info=None):
self._super_lineage_obj = None
self._summary_dir = summary_dir
self._update_time = update_time
self.update_time = update_time
self._added_info = added_info
self._parse_summary_log()
self._init_variables()
self.load()
def _init_variables(self):
"""Init variables."""
self._super_lineage_obj = None
self._latest_filename = None
self._latest_file_size = None
self._cached_file_list = None
def load(self):
"""Find and load summaries."""
# get sorted lineage files
lineage_files = SummaryPathParser.get_lineage_summaries(self._summary_dir, is_sorted=True)
if not lineage_files:
logger.warning('There is no summary log file under summary_dir %s.', self._summary_dir)
raise LineageFileNotFoundError(
'There is no summary log file under summary_dir.'
)
self._init_if_files_deleted(lineage_files)
index = 0
if self._latest_filename is not None:
index = lineage_files.index(self._latest_filename)
for filename in lineage_files[index:]:
if filename != self._latest_filename:
self._latest_filename = filename
self._latest_file_size = 0
file_path = os.path.join(self._summary_dir, filename)
new_size = FileHandler(file_path).size
if new_size == self._latest_file_size:
continue
self._latest_file_size = new_size
self._parse_summary_log()
def _init_if_files_deleted(self, file_list):
"""Init variables if files deleted."""
cached_file_list = self._cached_file_list
self._cached_file_list = file_list
if cached_file_list is None:
return
deleted_files = set(cached_file_list) - set(file_list)
if deleted_files:
logger.warning("There are some files has been deleted, "
"all files will be reloaded in path %s.", self._summary_dir)
self._init_variables()
def _parse_summary_log(self):
"""
......@@ -72,15 +122,22 @@ class LineageParser:
Returns:
bool, `True` if parse summary log success, else `False`.
"""
file_path = SummaryPathParser.get_latest_lineage_summary(self._summary_dir)
if file_path is None:
logger.warning('There is no summary log file under summary_dir %s.', self._summary_dir)
raise LineageFileNotFoundError(
'There is no summary log file under summary_dir.'
)
file_path = os.path.realpath(os.path.join(self._summary_dir, self._latest_filename))
try:
lineage_info = LineageSummaryAnalyzer.get_summary_infos(file_path)
user_defined_info = LineageSummaryAnalyzer.get_user_defined_info(file_path)
self._update_lineage_obj(lineage_info, user_defined_info)
except LineageSummaryAnalyzeException:
logger.warning("Parse file failed under summary_dir %s.", file_path)
except (LineageEventNotExistException, LineageEventFieldNotExistException) as error:
logger.warning("Parse file failed under summary_dir %s. Detail: %s.", file_path, str(error))
except MindInsightException as error:
logger.exception(error)
logger.warning("Parse file failed under summary_dir %s.", file_path)
def _update_lineage_obj(self, lineage_info, user_defined_info):
"""Update lineage object."""
if self._super_lineage_obj is None:
lineage_obj = LineageObj(
self._summary_dir,
train_lineage=lineage_info.train_lineage,
......@@ -88,15 +145,14 @@ class LineageParser:
dataset_graph=lineage_info.dataset_graph,
user_defined_info=user_defined_info
)
self._super_lineage_obj = SuperLineageObj(lineage_obj, self._update_time, self._added_info)
except (LineageSummaryAnalyzeException,
LineageEventNotExistException,
LineageEventFieldNotExistException):
logger.warning("Parse file failed under summary_dir %s.", self._summary_dir)
except MindInsightException as error:
logger.error(str(error))
logger.exception(error)
logger.warning("Parse file failed under summary_dir %s.", self._summary_dir)
self._super_lineage_obj = SuperLineageObj(lineage_obj, self.update_time, self._added_info)
else:
self._super_lineage_obj.lineage_obj.parse_and_update_lineage(
train_lineage=lineage_info.train_lineage,
evaluation_lineage=lineage_info.eval_lineage,
dataset_graph=lineage_info.dataset_graph,
user_defined_info=user_defined_info
)
@property
def super_lineage_obj(self):
......@@ -156,7 +212,7 @@ class LineageOrganizer:
cache_items = brief_cache.cache_items
for relative_dir, cache_train_job in cache_items.items():
try:
super_lineage_obj = cache_train_job.get("lineage")
super_lineage_obj = cache_train_job.get("lineage").super_lineage_obj
self._super_lineage_objs.update({relative_dir: super_lineage_obj})
except ParamValueError:
logger.info("This is no lineage info in train job %s.", relative_dir)
......
......@@ -82,6 +82,30 @@ class LineageObj:
self._lineage_info = {
self._name_summary_dir: summary_dir
}
self._filtration_result = None
self._init_lineage()
self.parse_and_update_lineage(**kwargs)
def _init_lineage(self):
"""Init lineage info."""
# train
self._lineage_info[self._name_model] = {}
self._lineage_info[self._name_algorithm] = {}
self._lineage_info[self._name_hyper_parameters] = {}
self._lineage_info[self._name_train_dataset] = {}
# eval
self._lineage_info[self._name_metric] = {}
self._lineage_info[self._name_valid_dataset] = {}
# dataset graph
self._lineage_info[self._name_dataset_graph] = {}
# user defined
self._lineage_info[self._name_user_defined] = {}
def parse_and_update_lineage(self, **kwargs):
"""Parse and update lineage."""
user_defined_info_list = kwargs.get('user_defined_info', [])
train_lineage = kwargs.get('train_lineage')
evaluation_lineage = kwargs.get('evaluation_lineage')
......@@ -92,6 +116,7 @@ class LineageObj:
self._parse_train_lineage(train_lineage)
self._parse_evaluation_lineage(evaluation_lineage)
self._parse_dataset_graph(dataset_graph)
self._filtration_result = self._organize_filtration_result()
@property
......@@ -309,10 +334,6 @@ class LineageObj:
train_lineage (Event): Train lineage.
"""
if train_lineage is None:
self._lineage_info[self._name_model] = {}
self._lineage_info[self._name_algorithm] = {}
self._lineage_info[self._name_hyper_parameters] = {}
self._lineage_info[self._name_train_dataset] = {}
return
event_dict = MessageToDict(
......@@ -341,8 +362,6 @@ class LineageObj:
evaluation_lineage (Event): Evaluation lineage.
"""
if evaluation_lineage is None:
self._lineage_info[self._name_metric] = {}
self._lineage_info[self._name_valid_dataset] = {}
return
event_dict = MessageToDict(
......@@ -364,9 +383,7 @@ class LineageObj:
Args:
dataset_graph (Event): Dataset graph.
"""
if dataset_graph is None:
self._lineage_info[self._name_dataset_graph] = {}
else:
if dataset_graph is not None:
# convert message to dict
event_dict = organize_graph(dataset_graph.dataset_graph)
if event_dict is None:
......@@ -380,6 +397,8 @@ class LineageObj:
Args:
user_defined_info_list (list): user defined info list.
"""
if not user_defined_info_list:
return
user_defined_infos = dict()
for user_defined_info in user_defined_info_list:
user_defined_infos.update(user_defined_info)
......
......@@ -204,11 +204,9 @@ class LineageSummaryAnalyzer(SummaryAnalyzer):
try:
lineage_info = analyzer.get_latest_info()
except (MindInsightException, IOError, DecodeError) as err:
log.error("Failed to get lineage information.")
log.exception(err)
raise LineageSummaryAnalyzeException()
except Exception as err:
log.error("Failed to get lineage information.")
log.exception(err)
raise LineageSummaryAnalyzeException()
......
......@@ -111,26 +111,26 @@ LINEAGE_FILTRATION_RUN1 = {
LINEAGE_FILTRATION_RUN2 = {
'summary_dir': os.path.join(BASE_SUMMARY_DIR, 'run2'),
'model_lineage': {
'loss_function': None,
'loss_function': "SoftmaxCrossEntropyWithLogits",
'train_dataset_path': None,
'train_dataset_count': None,
'train_dataset_count': 1024,
'test_dataset_path': None,
'test_dataset_count': 10240,
'user_defined': {},
'network': None,
'optimizer': None,
'learning_rate': None,
'epoch': None,
'batch_size': None,
'device_num': None,
'loss': None,
'model_size': None,
'network': "ResNet",
'optimizer': "Momentum",
'learning_rate': 0.11999999731779099,
'epoch': 10,
'batch_size': 32,
'device_num': 2,
'loss': 0.029999999329447746,
'model_size': 10,
'metric': {
'accuracy': 2.7800000000000002
},
'dataset_mark': 3
},
'dataset_graph': {}
'dataset_graph': DATASET_GRAPH
}
......@@ -460,9 +460,10 @@ class TestModelApi(TestCase):
'customized': event_data.CUSTOMIZED__0,
'object': [
LINEAGE_FILTRATION_EXCEPT_RUN,
LINEAGE_FILTRATION_RUN1
LINEAGE_FILTRATION_RUN1,
LINEAGE_FILTRATION_RUN2
],
'count': 2
'count': 3
}
partial_res1 = filter_summary_lineage(BASE_SUMMARY_DIR, search_condition1)
expect_objects = expect_result.get('object')
......@@ -746,7 +747,7 @@ class TestModelApi(TestCase):
expect_result = {
'customized': {},
'object': [],
'count': 1
'count': 2
}
partial_res2 = filter_summary_lineage(BASE_SUMMARY_DIR, search_condition2)
assert expect_result == partial_res2
......
......@@ -32,8 +32,7 @@ from mindinsight.lineagemgr import get_summary_lineage
from mindinsight.lineagemgr.collection.model.model_lineage import TrainLineage, EvalLineage, \
AnalyzeObject
from mindinsight.lineagemgr.common.exceptions.error_code import LineageErrors
from mindinsight.lineagemgr.common.exceptions.exceptions import LineageParamRunContextError, \
LineageFileNotFoundError
from mindinsight.lineagemgr.common.exceptions.exceptions import LineageParamRunContextError
from mindinsight.utils.exceptions import MindInsightException
from mindspore.application.model_zoo.resnet import ResNet
from mindspore.common.tensor import Tensor
......@@ -343,5 +342,3 @@ class TestModelLineage(TestCase):
full_file_name = summary_record.full_file_name
assert full_file_name.endswith('_lineage')
assert os.path.isfile(full_file_name)
with self.assertRaisesRegex(LineageFileNotFoundError, 'no summary log file'):
get_summary_lineage(summary_dir)
......@@ -54,10 +54,10 @@ class TestModel(TestCase):
)
@mock.patch('mindinsight.lineagemgr.common.utils.validate_path')
@mock.patch.object(SummaryPathParser, 'get_latest_lineage_summary')
@mock.patch.object(SummaryPathParser, 'get_lineage_summaries')
def test_get_summary_lineage_failed2(self, mock_summary, mock_valid):
"""Test get_summary_lineage failed."""
mock_summary.return_value = None
mock_summary.return_value = []
mock_valid.return_value = '/path/to/summary/dir'
self.assertRaisesRegex(
LineageFileNotFoundError,
......@@ -66,17 +66,21 @@ class TestModel(TestCase):
'/path/to/summary_dir'
)
@mock.patch('mindinsight.lineagemgr.lineage_parser.FileHandler')
@mock.patch('mindinsight.lineagemgr.lineage_parser.LineageParser._parse_summary_log')
@mock.patch('mindinsight.lineagemgr.common.utils.validate_path')
@mock.patch.object(SummaryPathParser, 'get_latest_lineage_summary')
@mock.patch.object(SummaryPathParser, 'get_lineage_summaries')
def test_get_summary_lineage_failed3(self,
mock_summary,
mock_valid,
mock_paser):
mock_parser,
mock_file_handler):
"""Test get_summary_lineage failed."""
mock_summary.return_value = '/path/to/summary/file'
mock_summary.return_value = ['/path/to/summary/file']
mock_valid.return_value = '/path/to/summary_dir'
mock_paser.return_value = None
mock_parser.return_value = None
mock_file_handler = MagicMock()
mock_file_handler.size = 1
result = get_summary_lineage('/path/to/summary_dir')
assert {} == result
......@@ -127,7 +131,7 @@ class TestFilterAPI(TestCase):
"""Test the function of filter_summary_lineage."""
@mock.patch('mindinsight.lineagemgr.api.model.LineageOrganizer')
@mock.patch('mindinsight.lineagemgr.api.model.Querier')
@mock.patch('mindinsight.lineagemgr.lineage_parser.SummaryPathParser.get_latest_lineage_summary')
@mock.patch('mindinsight.lineagemgr.lineage_parser.SummaryPathParser.get_lineage_summaries')
@mock.patch('mindinsight.lineagemgr.api.model._convert_relative_path_to_abspath')
@mock.patch('mindinsight.lineagemgr.api.model.normalize_summary_dir')
def test_filter_summary_lineage(self, validate_path_mock, convert_path_mock,
......@@ -198,11 +202,11 @@ class TestFilterAPI(TestCase):
@mock.patch('mindinsight.lineagemgr.api.model.validate_search_model_condition')
@mock.patch('mindinsight.lineagemgr.api.model.validate_condition')
@mock.patch('mindinsight.lineagemgr.api.model.normalize_summary_dir')
@mock.patch.object(SummaryPathParser, 'get_latest_lineage_summary')
@mock.patch.object(SummaryPathParser, 'get_lineage_summaries')
def test_failed_to_get_summary_filesh(self, mock_parse, *args):
"""Test filter_summary_lineage with invalid invalid param."""
path = '/path/to/summary/dir'
mock_parse.return_value = None
mock_parse.return_value = []
args[0].return_value = path
self.assertRaisesRegex(
LineageFileNotFoundError,
......@@ -215,7 +219,7 @@ class TestFilterAPI(TestCase):
@mock.patch('mindinsight.lineagemgr.api.model.validate_search_model_condition')
@mock.patch('mindinsight.lineagemgr.api.model.validate_condition')
@mock.patch('mindinsight.lineagemgr.api.model.normalize_summary_dir')
@mock.patch.object(SummaryPathParser, 'get_latest_lineage_summaries')
@mock.patch.object(SummaryPathParser, 'get_lineage_summaries')
@mock.patch('mindinsight.lineagemgr.api.model.Querier')
def test_failed_to_querier(self, mock_query, mock_parse, *args):
"""Test filter_summary_lineage with invalid invalid param."""
......
......@@ -33,19 +33,19 @@ MOCK_SUMMARY_DIRS = [
]
MOCK_SUMMARIES = [
{
'file_name': 'file0',
'file_name': 'file0.summary.1',
'create_time': datetime.fromtimestamp(1582031970)
},
{
'file_name': 'file0_lineage',
'file_name': 'file0.summary.1_lineage',
'create_time': datetime.fromtimestamp(1582031970)
},
{
'file_name': 'file1',
'file_name': 'file1.summary.2',
'create_time': datetime.fromtimestamp(1582031971)
},
{
'file_name': 'file1_lineage',
'file_name': 'file1.summary.2_lineage',
'create_time': datetime.fromtimestamp(1582031971)
}
]
......@@ -54,92 +54,54 @@ MOCK_SUMMARIES = [
class TestSummaryPathParser(TestCase):
"""Test the class of SummaryPathParser."""
@mock.patch.object(SummaryWatcher, 'list_summary_directories')
def test_get_summary_dirs(self, *args):
"""Test the function of get_summary_dirs."""
args[0].return_value = MOCK_SUMMARY_DIRS
expected_result = [
'/path/to/base/relative_path0',
'/path/to/base',
'/path/to/base/relative_path1'
]
base_dir = '/path/to/base'
result = SummaryPathParser.get_summary_dirs(base_dir)
self.assertListEqual(expected_result, result)
args[0].return_value = []
result = SummaryPathParser.get_summary_dirs(base_dir)
self.assertListEqual([], result)
@mock.patch.object(SummaryWatcher, 'list_summaries')
def test_get_latest_lineage_summary(self, *args):
"""Test the function of get_latest_lineage_summary."""
def test_get_lineage_summaries(self, *args):
"""Test the function of get_lineage_summaries."""
args[0].return_value = MOCK_SUMMARIES
exp_result = ['file0.summary.1_lineage', 'file1.summary.2_lineage']
summary_dir = '/path/to/summary_dir'
result = SummaryPathParser.get_latest_lineage_summary(summary_dir)
self.assertEqual('/path/to/summary_dir/file1_lineage', result)
result = SummaryPathParser.get_lineage_summaries(summary_dir)
self.assertEqual(exp_result, result)
args[0].return_value = [
{
'file_name': 'file0',
'file_name': 'file0.summary.1',
'create_time': datetime.fromtimestamp(1582031970)
}
]
result = SummaryPathParser.get_latest_lineage_summary(summary_dir)
self.assertEqual(None, result)
result = SummaryPathParser.get_lineage_summaries(summary_dir)
self.assertEqual([], result)
args[0].return_value = [
{
'file_name': 'file0_lineage',
'file_name': 'file0.summary.1_lineage',
'create_time': datetime.fromtimestamp(1582031970)
}
]
result = SummaryPathParser.get_latest_lineage_summary(summary_dir)
self.assertEqual(None, result)
result = SummaryPathParser.get_lineage_summaries(summary_dir)
self.assertEqual(['file0.summary.1_lineage'], result)
args[0].return_value = [
{
'file_name': 'file0_lineage',
'file_name': 'file0.summary.3_lineage',
'create_time': datetime.fromtimestamp(1582031970)
},
{
'file_name': 'file0_lineage_lineage',
'file_name': 'file0.summary.2_lineage_lineage',
'create_time': datetime.fromtimestamp(1582031970)
},
{
'file_name': 'file1_lineage',
'file_name': 'file1.summary.1_lineage',
'create_time': datetime.fromtimestamp(1582031971)
},
{
'file_name': 'file1_lineage_lineage',
'file_name': 'file1.summary.7_lineage_lineage',
'create_time': datetime.fromtimestamp(1582031971)
}
]
result = SummaryPathParser.get_latest_lineage_summary(summary_dir)
self.assertEqual('/path/to/summary_dir/file1_lineage_lineage', result)
@mock.patch.object(SummaryWatcher, 'list_summaries')
@mock.patch.object(SummaryWatcher, 'list_summary_directories')
def test_get_latest_lineage_summaries(self, *args):
"""Test the function of get_latest_lineage_summaries."""
args[0].return_value = MOCK_SUMMARY_DIRS
args[1].return_value = MOCK_SUMMARIES
expected_result = [
'/path/to/base/relative_path0/file1_lineage',
'/path/to/base/file1_lineage',
'/path/to/base/relative_path1/file1_lineage'
]
base_dir = '/path/to/base'
result = SummaryPathParser.get_latest_lineage_summaries(base_dir)
self.assertListEqual(expected_result, result)
args[1].return_value = [
{
'file_name': 'file0_lineage',
'create_time': datetime.fromtimestamp(1582031970)
}
]
result = SummaryPathParser.get_latest_lineage_summaries(base_dir)
self.assertListEqual([], result)
exp_result = ['file1.summary.1_lineage',
'file0.summary.2_lineage_lineage',
'file0.summary.3_lineage',
'file1.summary.7_lineage_lineage']
result = SummaryPathParser.get_lineage_summaries(summary_dir, is_sorted=True)
self.assertEqual(exp_result, result)
......@@ -16,6 +16,7 @@
import time
from unittest import TestCase, mock
from unittest.mock import MagicMock
from google.protobuf.json_format import ParseDict
......@@ -248,11 +249,12 @@ LINEAGE_FILTRATION_6 = {
class TestQuerier(TestCase):
"""Test the class of `Querier`."""
@mock.patch('mindinsight.lineagemgr.lineage_parser.SummaryPathParser.get_latest_lineage_summary')
@mock.patch('mindinsight.lineagemgr.lineage_parser.SummaryPathParser.get_lineage_summaries')
@mock.patch('mindinsight.lineagemgr.lineage_parser.SummaryWatcher.list_summary_directories')
@mock.patch('mindinsight.lineagemgr.lineage_parser.LineageSummaryAnalyzer.get_user_defined_info')
@mock.patch('mindinsight.lineagemgr.lineage_parser.LineageSummaryAnalyzer.get_summary_infos')
def setUp(self, *args):
@mock.patch('mindinsight.lineagemgr.lineage_parser.FileHandler')
def setUp(self, mock_file_handler, *args):
"""Initialization before test case execution."""
args[0].return_value = create_lineage_info(
event_data.EVENT_TRAIN_DICT_0,
......@@ -260,7 +262,10 @@ class TestQuerier(TestCase):
event_data.EVENT_DATASET_DICT_0
)
args[1].return_value = []
args[3].return_value = 'path'
args[3].return_value = ['path']
mock_file_handler = MagicMock()
mock_file_handler.size = 1
args[2].return_value = [{'relative_path': './', 'update_time': 1}]
single_summary_path = '/path/to/summary0'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册