You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_model.py 29 kB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859
  1. # Copyright 2019 Huawei Technologies Co., Ltd
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. # ============================================================================
  15. """
  16. Function:
  17. Test the query module about lineage information.
  18. Usage:
  19. The query module test should be run after lineagemgr/collection/model/test_model_lineage.py
  20. pytest lineagemgr
  21. """
  22. import os
  23. from unittest import TestCase
  24. import pytest
  25. from mindinsight.lineagemgr.model import filter_summary_lineage, get_summary_lineage
  26. from mindinsight.lineagemgr.common.exceptions.exceptions import (LineageFileNotFoundError, LineageParamSummaryPathError,
  27. LineageParamTypeError, LineageParamValueError,
  28. LineageSearchConditionParamError)
  29. from .conftest import BASE_SUMMARY_DIR, DATASET_GRAPH, SUMMARY_DIR, SUMMARY_DIR_2
  30. from ....ut.lineagemgr.querier import event_data
  31. from ....utils.tools import assert_equal_lineages
  32. LINEAGE_INFO_RUN1 = {
  33. 'summary_dir': os.path.join(BASE_SUMMARY_DIR, 'run1'),
  34. 'metric': {
  35. 'accuracy': 0.78
  36. },
  37. 'hyper_parameters': {
  38. 'optimizer': 'Momentum',
  39. 'learning_rate': 0.12,
  40. 'loss_function': 'SoftmaxCrossEntropyWithLogits',
  41. 'epoch': 14,
  42. 'parallel_mode': 'stand_alone',
  43. 'device_num': 2,
  44. 'batch_size': 32
  45. },
  46. 'algorithm': {
  47. 'network': 'ResNet'
  48. },
  49. 'train_dataset': {
  50. 'train_dataset_size': 1024
  51. },
  52. 'valid_dataset': {
  53. 'valid_dataset_size': 1024
  54. },
  55. 'model': {
  56. 'path': '{"ckpt": "'
  57. + BASE_SUMMARY_DIR + '/run1/CKPtest_model.ckpt"}',
  58. 'size': 64
  59. },
  60. 'dataset_graph': DATASET_GRAPH
  61. }
  62. LINEAGE_FILTRATION_EXCEPT_RUN = {
  63. 'summary_dir': os.path.join(BASE_SUMMARY_DIR, 'except_run'),
  64. 'model_lineage': {
  65. 'loss_function': 'SoftmaxCrossEntropyWithLogits',
  66. 'train_dataset_path': None,
  67. 'train_dataset_count': 1024,
  68. 'test_dataset_path': None,
  69. 'test_dataset_count': None,
  70. 'user_defined': {},
  71. 'network': 'ResNet',
  72. 'optimizer': 'Momentum',
  73. 'learning_rate': 0.12,
  74. 'epoch': 10,
  75. 'batch_size': 32,
  76. 'device_num': 2,
  77. 'loss': 0.03,
  78. 'model_size': 64,
  79. 'metric': {},
  80. 'dataset_mark': 2
  81. },
  82. 'dataset_graph': DATASET_GRAPH
  83. }
  84. LINEAGE_FILTRATION_RUN1 = {
  85. 'summary_dir': os.path.join(BASE_SUMMARY_DIR, 'run1'),
  86. 'model_lineage': {
  87. 'loss_function': 'SoftmaxCrossEntropyWithLogits',
  88. 'train_dataset_path': None,
  89. 'train_dataset_count': 1024,
  90. 'test_dataset_path': None,
  91. 'test_dataset_count': 1024,
  92. 'user_defined': {
  93. 'info': 'info1',
  94. 'version': 'v1',
  95. 'eval_version': 'version2'
  96. },
  97. 'network': 'ResNet',
  98. 'optimizer': 'Momentum',
  99. 'learning_rate': 0.12,
  100. 'epoch': 14,
  101. 'batch_size': 32,
  102. 'device_num': 2,
  103. 'loss': None,
  104. 'model_size': 64,
  105. 'metric': {
  106. 'accuracy': 0.78
  107. },
  108. 'dataset_mark': 2
  109. },
  110. 'dataset_graph': DATASET_GRAPH
  111. }
  112. LINEAGE_FILTRATION_RUN2 = {
  113. 'summary_dir': os.path.join(BASE_SUMMARY_DIR, 'run2'),
  114. 'model_lineage': {
  115. 'loss_function': "SoftmaxCrossEntropyWithLogits",
  116. 'train_dataset_path': None,
  117. 'train_dataset_count': 1024,
  118. 'test_dataset_path': None,
  119. 'test_dataset_count': 1024,
  120. 'user_defined': {},
  121. 'network': "ResNet",
  122. 'optimizer': "Momentum",
  123. 'learning_rate': 0.12,
  124. 'epoch': 10,
  125. 'batch_size': 32,
  126. 'device_num': 2,
  127. 'loss': 0.03,
  128. 'model_size': 10,
  129. 'metric': {
  130. 'accuracy': 2.78
  131. },
  132. 'dataset_mark': 3
  133. },
  134. 'dataset_graph': DATASET_GRAPH
  135. }
  136. @pytest.mark.usefixtures("create_summary_dir")
  137. class TestModelApi(TestCase):
  138. """Test lineage information query interface."""
  139. @classmethod
  140. def setup_class(cls):
  141. """The initial process."""
  142. cls.dir_with_empty_lineage = os.path.join(
  143. BASE_SUMMARY_DIR, 'dir_with_empty_lineage'
  144. )
  145. os.makedirs(cls.dir_with_empty_lineage)
  146. ms_file = os.path.join(
  147. cls.dir_with_empty_lineage, 'empty.summary.1581499502.bms_MS'
  148. )
  149. lineage_file = ms_file + '_lineage'
  150. with open(ms_file, mode='w'):
  151. pass
  152. with open(lineage_file, mode='w'):
  153. pass
  154. cls.empty_dir = os.path.join(BASE_SUMMARY_DIR, 'empty_dir')
  155. os.makedirs(cls.empty_dir)
  156. @pytest.mark.level0
  157. @pytest.mark.platform_arm_ascend_training
  158. @pytest.mark.platform_x86_gpu_training
  159. @pytest.mark.platform_x86_ascend_training
  160. @pytest.mark.platform_x86_cpu
  161. @pytest.mark.env_single
  162. def test_get_summary_lineage(self):
  163. """Test the interface of get_summary_lineage."""
  164. total_res = get_summary_lineage(None, SUMMARY_DIR)
  165. partial_res1 = get_summary_lineage(None, SUMMARY_DIR, ['hyper_parameters'])
  166. partial_res2 = get_summary_lineage(None, SUMMARY_DIR, ['metric', 'algorithm'])
  167. expect_total_res = LINEAGE_INFO_RUN1
  168. expect_partial_res1 = {
  169. 'summary_dir': os.path.join(BASE_SUMMARY_DIR, 'run1'),
  170. 'hyper_parameters': {
  171. 'optimizer': 'Momentum',
  172. 'learning_rate': 0.12,
  173. 'loss_function': 'SoftmaxCrossEntropyWithLogits',
  174. 'epoch': 14,
  175. 'parallel_mode': 'stand_alone',
  176. 'device_num': 2,
  177. 'batch_size': 32
  178. }
  179. }
  180. expect_partial_res2 = {
  181. 'summary_dir': os.path.join(BASE_SUMMARY_DIR, 'run1'),
  182. 'metric': {
  183. 'accuracy': 0.78
  184. },
  185. 'algorithm': {
  186. 'network': 'ResNet'
  187. }
  188. }
  189. assert_equal_lineages(expect_total_res, total_res, self.assertDictEqual)
  190. assert_equal_lineages(expect_partial_res1, partial_res1, self.assertDictEqual)
  191. assert_equal_lineages(expect_partial_res2, partial_res2, self.assertDictEqual)
  192. # the lineage summary file is empty
  193. result = get_summary_lineage(None, self.dir_with_empty_lineage)
  194. assert {} == result
  195. # keys is empty list
  196. expect_result = {
  197. 'summary_dir': SUMMARY_DIR
  198. }
  199. result = get_summary_lineage(None, SUMMARY_DIR, [])
  200. assert expect_result == result
  201. @pytest.mark.level0
  202. @pytest.mark.platform_arm_ascend_training
  203. @pytest.mark.platform_x86_gpu_training
  204. @pytest.mark.platform_x86_ascend_training
  205. @pytest.mark.platform_x86_cpu
  206. @pytest.mark.env_single
  207. def test_get_summary_lineage_exception_1(self):
  208. """Test the interface of get_summary_lineage with exception."""
  209. # summary path does not exist
  210. self.assertRaisesRegex(
  211. LineageParamSummaryPathError,
  212. 'The summary path does not exist or is not a dir.',
  213. get_summary_lineage,
  214. None,
  215. '/tmp/fake/dir'
  216. )
  217. # summary path is relative path
  218. self.assertRaisesRegex(
  219. LineageParamSummaryPathError,
  220. 'The summary path is invalid.',
  221. get_summary_lineage,
  222. None,
  223. 'tmp'
  224. )
  225. # the type of input param is invalid
  226. self.assertRaisesRegex(
  227. LineageParamSummaryPathError,
  228. 'The summary path is invalid.',
  229. get_summary_lineage,
  230. None,
  231. ['/root/linage1', '/root/lineage2']
  232. )
  233. # summary path is empty str
  234. self.assertRaisesRegex(
  235. LineageParamSummaryPathError,
  236. 'The summary path is invalid.',
  237. get_summary_lineage,
  238. None,
  239. '',
  240. keys=None
  241. )
  242. # summary path invalid
  243. self.assertRaisesRegex(
  244. LineageParamSummaryPathError,
  245. 'The summary path is invalid.',
  246. get_summary_lineage,
  247. None,
  248. '\\',
  249. keys=None
  250. )
  251. @pytest.mark.level0
  252. @pytest.mark.platform_arm_ascend_training
  253. @pytest.mark.platform_x86_gpu_training
  254. @pytest.mark.platform_x86_ascend_training
  255. @pytest.mark.platform_x86_cpu
  256. @pytest.mark.env_single
  257. def test_get_summary_lineage_exception_2(self):
  258. """Test the interface of get_summary_lineage with exception."""
  259. # keys is invalid
  260. self.assertRaisesRegex(
  261. LineageParamValueError,
  262. 'Keys must be in',
  263. get_summary_lineage,
  264. None,
  265. SUMMARY_DIR,
  266. ['metric', 'fake_name']
  267. )
  268. self.assertRaisesRegex(
  269. LineageParamTypeError,
  270. 'Keys must be list.',
  271. get_summary_lineage,
  272. None,
  273. SUMMARY_DIR,
  274. 0
  275. )
  276. self.assertRaisesRegex(
  277. LineageParamTypeError,
  278. 'Keys must be list.',
  279. get_summary_lineage,
  280. None,
  281. SUMMARY_DIR,
  282. 0.1
  283. )
  284. self.assertRaisesRegex(
  285. LineageParamTypeError,
  286. 'Keys must be list.',
  287. get_summary_lineage,
  288. None,
  289. SUMMARY_DIR,
  290. True
  291. )
  292. self.assertRaisesRegex(
  293. LineageParamTypeError,
  294. 'Element of keys must be str.',
  295. get_summary_lineage,
  296. None,
  297. SUMMARY_DIR,
  298. [1, 2, 3]
  299. )
  300. self.assertRaisesRegex(
  301. LineageParamTypeError,
  302. 'Keys must be list.',
  303. get_summary_lineage,
  304. None,
  305. SUMMARY_DIR,
  306. (3, 4)
  307. )
  308. self.assertRaisesRegex(
  309. LineageParamTypeError,
  310. 'Keys must be list.',
  311. get_summary_lineage,
  312. None,
  313. SUMMARY_DIR,
  314. {'a': 'b'}
  315. )
  316. @pytest.mark.level0
  317. @pytest.mark.platform_arm_ascend_training
  318. @pytest.mark.platform_x86_gpu_training
  319. @pytest.mark.platform_x86_ascend_training
  320. @pytest.mark.platform_x86_cpu
  321. @pytest.mark.env_single
  322. def test_filter_summary_lineage(self):
  323. """Test the interface of filter_summary_lineage."""
  324. expect_result = {
  325. 'customized': event_data.CUSTOMIZED__1,
  326. 'object': [
  327. LINEAGE_FILTRATION_EXCEPT_RUN,
  328. LINEAGE_FILTRATION_RUN1,
  329. LINEAGE_FILTRATION_RUN2
  330. ],
  331. 'count': 3
  332. }
  333. search_condition = {
  334. 'sorted_name': 'summary_dir'
  335. }
  336. res = filter_summary_lineage(None, BASE_SUMMARY_DIR, search_condition)
  337. expect_objects = expect_result.get('object')
  338. for idx, res_object in enumerate(res.get('object')):
  339. expect_objects[idx]['model_lineage']['dataset_mark'] = res_object['model_lineage'].get('dataset_mark')
  340. assert_equal_lineages(expect_result, res, self.assertDictEqual)
  341. expect_result = {
  342. 'customized': {},
  343. 'object': [],
  344. 'count': 0
  345. }
  346. res = filter_summary_lineage(None, self.dir_with_empty_lineage)
  347. expect_objects = expect_result.get('object')
  348. for idx, res_object in enumerate(res.get('object')):
  349. expect_objects[idx]['model_lineage']['dataset_mark'] = res_object['model_lineage'].get('dataset_mark')
  350. assert_equal_lineages(expect_result, res, self.assertDictEqual)
  351. @pytest.mark.level0
  352. @pytest.mark.platform_arm_ascend_training
  353. @pytest.mark.platform_x86_gpu_training
  354. @pytest.mark.platform_x86_ascend_training
  355. @pytest.mark.platform_x86_cpu
  356. @pytest.mark.env_single
  357. def test_filter_summary_lineage_with_condition_1(self):
  358. """Test the interface of filter_summary_lineage with condition."""
  359. search_condition = {
  360. 'summary_dir': {
  361. 'in': [
  362. SUMMARY_DIR,
  363. SUMMARY_DIR_2
  364. ]
  365. },
  366. 'metric/accuracy': {
  367. 'lt': 3.0,
  368. 'gt': 0.5
  369. },
  370. 'sorted_name': 'metric/accuracy',
  371. 'sorted_type': 'descending',
  372. 'limit': 3,
  373. 'offset': 0
  374. }
  375. expect_result = {
  376. 'customized': event_data.CUSTOMIZED__1,
  377. 'object': [
  378. LINEAGE_FILTRATION_RUN2,
  379. LINEAGE_FILTRATION_RUN1
  380. ],
  381. 'count': 2
  382. }
  383. partial_res = filter_summary_lineage(None, BASE_SUMMARY_DIR, search_condition)
  384. expect_objects = expect_result.get('object')
  385. for idx, res_object in enumerate(partial_res.get('object')):
  386. expect_objects[idx]['model_lineage']['dataset_mark'] = res_object['model_lineage'].get('dataset_mark')
  387. assert_equal_lineages(expect_result, partial_res, self.assertDictEqual)
  388. @pytest.mark.level0
  389. @pytest.mark.platform_arm_ascend_training
  390. @pytest.mark.platform_x86_gpu_training
  391. @pytest.mark.platform_x86_ascend_training
  392. @pytest.mark.platform_x86_cpu
  393. @pytest.mark.env_single
  394. def test_filter_summary_lineage_with_condition_2(self):
  395. """Test the interface of filter_summary_lineage with condition."""
  396. search_condition = {
  397. 'summary_dir': {
  398. 'in': [
  399. './run1',
  400. './run2'
  401. ]
  402. },
  403. 'metric/accuracy': {
  404. 'lt': 3.0,
  405. 'gt': 0.5
  406. },
  407. 'sorted_name': 'metric/accuracy',
  408. 'sorted_type': 'descending',
  409. 'limit': 3,
  410. 'offset': 0
  411. }
  412. expect_result = {
  413. 'customized': event_data.CUSTOMIZED__1,
  414. 'object': [
  415. LINEAGE_FILTRATION_RUN2,
  416. LINEAGE_FILTRATION_RUN1
  417. ],
  418. 'count': 2
  419. }
  420. partial_res = filter_summary_lineage(None, BASE_SUMMARY_DIR, search_condition)
  421. expect_objects = expect_result.get('object')
  422. for idx, res_object in enumerate(partial_res.get('object')):
  423. expect_objects[idx]['model_lineage']['dataset_mark'] = res_object['model_lineage'].get('dataset_mark')
  424. assert_equal_lineages(expect_result, partial_res, self.assertDictEqual)
  425. @pytest.mark.level0
  426. @pytest.mark.platform_arm_ascend_training
  427. @pytest.mark.platform_x86_gpu_training
  428. @pytest.mark.platform_x86_ascend_training
  429. @pytest.mark.platform_x86_cpu
  430. @pytest.mark.env_single
  431. def test_filter_summary_lineage_with_condition_3(self):
  432. """Test the interface of filter_summary_lineage with condition."""
  433. search_condition1 = {
  434. 'batch_size': {
  435. 'ge': 30
  436. },
  437. 'sorted_name': 'metric/accuracy',
  438. }
  439. expect_result = {
  440. 'customized': event_data.CUSTOMIZED__1,
  441. 'object': [
  442. LINEAGE_FILTRATION_EXCEPT_RUN,
  443. LINEAGE_FILTRATION_RUN1,
  444. LINEAGE_FILTRATION_RUN2
  445. ],
  446. 'count': 3
  447. }
  448. partial_res1 = filter_summary_lineage(None, BASE_SUMMARY_DIR, search_condition1)
  449. expect_objects = expect_result.get('object')
  450. for idx, res_object in enumerate(partial_res1.get('object')):
  451. expect_objects[idx]['model_lineage']['dataset_mark'] = res_object['model_lineage'].get('dataset_mark')
  452. assert_equal_lineages(expect_result, partial_res1, self.assertDictEqual)
  453. search_condition2 = {
  454. 'batch_size': {
  455. 'lt': 30
  456. },
  457. 'lineage_type': {
  458. 'eq': 'model'
  459. },
  460. }
  461. expect_result = {
  462. 'customized': {},
  463. 'object': [],
  464. 'count': 0
  465. }
  466. partial_res2 = filter_summary_lineage(None, BASE_SUMMARY_DIR, search_condition2)
  467. assert expect_result == partial_res2
  468. @pytest.mark.level0
  469. @pytest.mark.platform_arm_ascend_training
  470. @pytest.mark.platform_x86_gpu_training
  471. @pytest.mark.platform_x86_ascend_training
  472. @pytest.mark.platform_x86_cpu
  473. @pytest.mark.env_single
  474. def test_filter_summary_lineage_with_lineage_type(self):
  475. """Test the interface of filter_summary_lineage with lineage_type."""
  476. summary_dir = os.path.join(BASE_SUMMARY_DIR, 'except_run')
  477. search_condition = {
  478. 'summary_dir': {
  479. 'in': [summary_dir]
  480. },
  481. 'lineage_type': {
  482. 'eq': 'dataset'
  483. },
  484. }
  485. expect_result = {
  486. 'customized': {},
  487. 'object': [
  488. {
  489. 'summary_dir': summary_dir,
  490. 'dataset_graph': DATASET_GRAPH
  491. }
  492. ],
  493. 'count': 1
  494. }
  495. res = filter_summary_lineage(None, BASE_SUMMARY_DIR, search_condition)
  496. assert expect_result == res
  497. @pytest.mark.level0
  498. @pytest.mark.platform_arm_ascend_training
  499. @pytest.mark.platform_x86_gpu_training
  500. @pytest.mark.platform_x86_ascend_training
  501. @pytest.mark.platform_x86_cpu
  502. @pytest.mark.env_single
  503. def test_filter_summary_lineage_exception_1(self):
  504. """Test the abnormal execution of the filter_summary_lineage interface."""
  505. # summary base dir is relative path
  506. self.assertRaisesRegex(
  507. LineageParamSummaryPathError,
  508. 'The summary path is invalid.',
  509. filter_summary_lineage,
  510. None,
  511. 'relative_path'
  512. )
  513. # summary base dir does not exist
  514. self.assertRaisesRegex(
  515. LineageParamSummaryPathError,
  516. 'The summary path does not exist or is not a dir.',
  517. filter_summary_lineage,
  518. None,
  519. '/path/does/not/exist'
  520. )
  521. # no summary log file under summary_base_dir
  522. self.assertRaisesRegex(
  523. LineageFileNotFoundError,
  524. 'There is no summary log file under summary_base_dir.',
  525. filter_summary_lineage,
  526. None,
  527. self.empty_dir
  528. )
  529. @pytest.mark.level0
  530. @pytest.mark.platform_arm_ascend_training
  531. @pytest.mark.platform_x86_gpu_training
  532. @pytest.mark.platform_x86_ascend_training
  533. @pytest.mark.platform_x86_cpu
  534. @pytest.mark.env_single
  535. def test_filter_summary_lineage_exception_2(self):
  536. """Test the abnormal execution of the filter_summary_lineage interface."""
  537. # search_condition type error
  538. search_condition = {
  539. 'summary_dir': 1.0
  540. }
  541. self.assertRaisesRegex(
  542. LineageSearchConditionParamError,
  543. 'The search_condition element summary_dir should be dict.',
  544. filter_summary_lineage,
  545. None,
  546. BASE_SUMMARY_DIR,
  547. search_condition
  548. )
  549. # only sorted_type (no sorted_name)
  550. search_condition = {
  551. 'sorted_type': 'descending'
  552. }
  553. self.assertRaisesRegex(
  554. LineageSearchConditionParamError,
  555. 'The sorted_name have to exist when sorted_type exists.',
  556. filter_summary_lineage,
  557. None,
  558. BASE_SUMMARY_DIR,
  559. search_condition
  560. )
  561. # search condition is not dict or None
  562. search_condition = []
  563. self.assertRaisesRegex(
  564. LineageSearchConditionParamError,
  565. 'Invalid search_condition type, it should be dict.',
  566. filter_summary_lineage,
  567. None,
  568. BASE_SUMMARY_DIR,
  569. search_condition
  570. )
  571. # the condition of limit is invalid
  572. search_condition = {
  573. 'limit': True
  574. }
  575. self.assertRaisesRegex(
  576. LineageSearchConditionParamError,
  577. 'The limit must be int.',
  578. filter_summary_lineage,
  579. None,
  580. BASE_SUMMARY_DIR,
  581. search_condition
  582. )
  583. @pytest.mark.level0
  584. @pytest.mark.platform_arm_ascend_training
  585. @pytest.mark.platform_x86_gpu_training
  586. @pytest.mark.platform_x86_ascend_training
  587. @pytest.mark.platform_x86_cpu
  588. @pytest.mark.env_single
  589. def test_filter_summary_lineage_exception_3(self):
  590. """Test the abnormal execution of the filter_summary_lineage interface."""
  591. # the condition of offset is invalid
  592. search_condition = {
  593. 'offset': 1.0
  594. }
  595. self.assertRaisesRegex(
  596. LineageSearchConditionParamError,
  597. 'The offset must be int.',
  598. filter_summary_lineage,
  599. None,
  600. BASE_SUMMARY_DIR,
  601. search_condition
  602. )
  603. # the search attribute not supported
  604. search_condition = {
  605. 'dataset_graph': {
  606. 'le': 1
  607. }
  608. }
  609. self.assertRaisesRegex(
  610. LineageSearchConditionParamError,
  611. 'The search attribute not supported.',
  612. filter_summary_lineage,
  613. None,
  614. BASE_SUMMARY_DIR,
  615. search_condition
  616. )
  617. @pytest.mark.level0
  618. @pytest.mark.platform_arm_ascend_training
  619. @pytest.mark.platform_x86_gpu_training
  620. @pytest.mark.platform_x86_ascend_training
  621. @pytest.mark.platform_x86_cpu
  622. @pytest.mark.env_single
  623. def test_filter_summary_lineage_exception_4(self):
  624. """Test the abnormal execution of the filter_summary_lineage interface."""
  625. # the sorted_type not supported
  626. search_condition = {
  627. 'sorted_name': 'summary_dir',
  628. 'sorted_type': 'xxx'
  629. }
  630. self.assertRaisesRegex(
  631. LineageSearchConditionParamError,
  632. 'The sorted_type must be ascending or descending',
  633. filter_summary_lineage,
  634. None,
  635. BASE_SUMMARY_DIR,
  636. search_condition
  637. )
  638. # the search condition not supported
  639. search_condition = {
  640. 'batch_size': {
  641. 'dd': 30
  642. }
  643. }
  644. self.assertRaisesRegex(
  645. LineageSearchConditionParamError,
  646. 'The compare condition should be in',
  647. filter_summary_lineage,
  648. None,
  649. BASE_SUMMARY_DIR,
  650. search_condition
  651. )
  652. # the search condition type error
  653. search_condition = {
  654. 'metric/accuracy': {
  655. 'lt': 'xxx'
  656. }
  657. }
  658. self.assertRaisesRegex(
  659. LineageSearchConditionParamError,
  660. 'The parameter metric/accuracy is invalid.',
  661. filter_summary_lineage,
  662. None,
  663. BASE_SUMMARY_DIR,
  664. search_condition
  665. )
  666. @pytest.mark.level0
  667. @pytest.mark.platform_arm_ascend_training
  668. @pytest.mark.platform_x86_gpu_training
  669. @pytest.mark.platform_x86_ascend_training
  670. @pytest.mark.platform_x86_cpu
  671. @pytest.mark.env_single
  672. def test_filter_summary_lineage_exception_5(self):
  673. """Test the abnormal execution of the filter_summary_lineage interface."""
  674. # the summary dir is invalid in search condition
  675. search_condition = {
  676. 'summary_dir': {
  677. 'in': [
  678. 'xxx'
  679. ]
  680. }
  681. }
  682. self.assertRaisesRegex(
  683. LineageParamSummaryPathError,
  684. 'The summary path is invalid.',
  685. filter_summary_lineage,
  686. None,
  687. BASE_SUMMARY_DIR,
  688. search_condition
  689. )
  690. @pytest.mark.level0
  691. @pytest.mark.platform_arm_ascend_training
  692. @pytest.mark.platform_x86_gpu_training
  693. @pytest.mark.platform_x86_ascend_training
  694. @pytest.mark.platform_x86_cpu
  695. @pytest.mark.env_single
  696. def test_filter_summary_lineage_exception_6(self):
  697. """Test the abnormal execution of the filter_summary_lineage interface."""
  698. # gt > lt
  699. search_condition1 = {
  700. 'metric/accuracy': {
  701. 'gt': 1,
  702. 'lt': 0.5
  703. }
  704. }
  705. expect_result = {
  706. 'customized': {},
  707. 'object': [],
  708. 'count': 0
  709. }
  710. partial_res1 = filter_summary_lineage(None, BASE_SUMMARY_DIR, search_condition1)
  711. assert expect_result == partial_res1
  712. # the (offset + 1) * limit > count
  713. search_condition2 = {
  714. 'loss': {
  715. 'lt': 1
  716. },
  717. 'limit': 1,
  718. 'offset': 4
  719. }
  720. expect_result = {
  721. 'customized': {},
  722. 'object': [],
  723. 'count': 2
  724. }
  725. partial_res2 = filter_summary_lineage(None, BASE_SUMMARY_DIR, search_condition2)
  726. assert expect_result == partial_res2
  727. @pytest.mark.level0
  728. @pytest.mark.platform_arm_ascend_training
  729. @pytest.mark.platform_x86_gpu_training
  730. @pytest.mark.platform_x86_ascend_training
  731. @pytest.mark.platform_x86_cpu
  732. @pytest.mark.env_single
  733. def test_filter_summary_lineage_exception_7(self):
  734. """Test the abnormal execution of the filter_summary_lineage interface."""
  735. condition_keys = ["summary_dir", "lineage_type", "loss_function", "optimizer", "network", "dataset_mark"]
  736. for condition_key in condition_keys:
  737. # the condition type not supported in summary_dir and lineage_type
  738. search_condition = {
  739. condition_key: {
  740. 'lt': '/xxx'
  741. }
  742. }
  743. self.assertRaisesRegex(
  744. LineageSearchConditionParamError,
  745. f'The parameter {condition_key} is invalid. Its operation should be `in` or `eq`.',
  746. filter_summary_lineage,
  747. None,
  748. BASE_SUMMARY_DIR,
  749. search_condition
  750. )
  751. # more than one operation in summary_dir and lineage_type
  752. search_condition = {
  753. condition_key: {
  754. 'in': ['/xxx', '/yyy'],
  755. 'eq': '/zzz',
  756. }
  757. }
  758. self.assertRaisesRegex(
  759. LineageSearchConditionParamError,
  760. f'The parameter {condition_key} is invalid. More than one operation.',
  761. filter_summary_lineage,
  762. None,
  763. BASE_SUMMARY_DIR,
  764. search_condition
  765. )
  766. @pytest.mark.level0
  767. @pytest.mark.platform_arm_ascend_training
  768. @pytest.mark.platform_x86_gpu_training
  769. @pytest.mark.platform_x86_ascend_training
  770. @pytest.mark.platform_x86_cpu
  771. @pytest.mark.env_single
  772. def test_filter_summary_lineage_exception_8(self):
  773. """Test the abnormal execution of the filter_summary_lineage interface."""
  774. invalid_lineage_types = ['xxx', None]
  775. for lineage_type in invalid_lineage_types:
  776. search_condition = {
  777. 'lineage_type': {
  778. 'eq': lineage_type
  779. }
  780. }
  781. self.assertRaisesRegex(
  782. LineageSearchConditionParamError,
  783. "The parameter lineage_type is invalid. It should be 'dataset' or 'model'.",
  784. filter_summary_lineage,
  785. None,
  786. BASE_SUMMARY_DIR,
  787. search_condition
  788. )
  789. @pytest.mark.level0
  790. @pytest.mark.platform_arm_ascend_training
  791. @pytest.mark.platform_x86_gpu_training
  792. @pytest.mark.platform_x86_ascend_training
  793. @pytest.mark.platform_x86_cpu
  794. @pytest.mark.env_single
  795. def test_filter_summary_lineage_exception_9(self):
  796. """Test the abnormal execution of the filter_summary_lineage interface."""
  797. invalid_sorted_names = ['xxx', 'metric_', 1]
  798. for sorted_name in invalid_sorted_names:
  799. search_condition = {
  800. 'sorted_name': sorted_name
  801. }
  802. self.assertRaisesRegex(
  803. LineageSearchConditionParamError,
  804. 'The sorted_name must be in',
  805. filter_summary_lineage,
  806. None,
  807. BASE_SUMMARY_DIR,
  808. search_condition
  809. )