1
0

test_state.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. # -*- coding: utf-8 -*-
  2. '''
  3. Unit Tests for functions located in salt.utils.state.py.
  4. '''
  5. # Import python libs
  6. from __future__ import absolute_import, print_function, unicode_literals
  7. import copy
  8. import textwrap
  9. # Import Salt libs
  10. from salt.ext import six
  11. import salt.utils.odict
  12. import salt.utils.state
  13. # Import Salt Testing libs
  14. from tests.support.unit import TestCase
  15. class StateUtilTestCase(TestCase):
  16. '''
  17. Test case for state util.
  18. '''
  19. def test_check_result(self):
  20. self.assertFalse(salt.utils.state.check_result(None),
  21. 'Failed to handle None as an invalid data type.')
  22. self.assertFalse(salt.utils.state.check_result([]),
  23. 'Failed to handle an invalid data type.')
  24. self.assertFalse(salt.utils.state.check_result({}),
  25. 'Failed to handle an empty dictionary.')
  26. self.assertFalse(salt.utils.state.check_result({'host1': []}),
  27. 'Failed to handle an invalid host data structure.')
  28. test_valid_state = {'host1': {'test_state': {'result': 'We have liftoff!'}}}
  29. self.assertTrue(salt.utils.state.check_result(test_valid_state))
  30. test_valid_false_states = {
  31. 'test1': salt.utils.odict.OrderedDict([
  32. ('host1',
  33. salt.utils.odict.OrderedDict([
  34. ('test_state0', {'result': True}),
  35. ('test_state', {'result': False}),
  36. ])),
  37. ]),
  38. 'test2': salt.utils.odict.OrderedDict([
  39. ('host1',
  40. salt.utils.odict.OrderedDict([
  41. ('test_state0', {'result': True}),
  42. ('test_state', {'result': True}),
  43. ])),
  44. ('host2',
  45. salt.utils.odict.OrderedDict([
  46. ('test_state0', {'result': True}),
  47. ('test_state', {'result': False}),
  48. ])),
  49. ]),
  50. 'test3': ['a'],
  51. 'test4': salt.utils.odict.OrderedDict([
  52. ('asup', salt.utils.odict.OrderedDict([
  53. ('host1',
  54. salt.utils.odict.OrderedDict([
  55. ('test_state0', {'result': True}),
  56. ('test_state', {'result': True}),
  57. ])),
  58. ('host2',
  59. salt.utils.odict.OrderedDict([
  60. ('test_state0', {'result': True}),
  61. ('test_state', {'result': False}),
  62. ]))
  63. ]))
  64. ]),
  65. 'test5': salt.utils.odict.OrderedDict([
  66. ('asup', salt.utils.odict.OrderedDict([
  67. ('host1',
  68. salt.utils.odict.OrderedDict([
  69. ('test_state0', {'result': True}),
  70. ('test_state', {'result': True}),
  71. ])),
  72. ('host2', salt.utils.odict.OrderedDict([]))
  73. ]))
  74. ])
  75. }
  76. for test, data in six.iteritems(test_valid_false_states):
  77. self.assertFalse(
  78. salt.utils.state.check_result(data),
  79. msg='{0} failed'.format(test))
  80. test_valid_true_states = {
  81. 'test1': salt.utils.odict.OrderedDict([
  82. ('host1',
  83. salt.utils.odict.OrderedDict([
  84. ('test_state0', {'result': True}),
  85. ('test_state', {'result': True}),
  86. ])),
  87. ]),
  88. 'test3': salt.utils.odict.OrderedDict([
  89. ('host1',
  90. salt.utils.odict.OrderedDict([
  91. ('test_state0', {'result': True}),
  92. ('test_state', {'result': True}),
  93. ])),
  94. ('host2',
  95. salt.utils.odict.OrderedDict([
  96. ('test_state0', {'result': True}),
  97. ('test_state', {'result': True}),
  98. ])),
  99. ]),
  100. 'test4': salt.utils.odict.OrderedDict([
  101. ('asup', salt.utils.odict.OrderedDict([
  102. ('host1',
  103. salt.utils.odict.OrderedDict([
  104. ('test_state0', {'result': True}),
  105. ('test_state', {'result': True}),
  106. ])),
  107. ('host2',
  108. salt.utils.odict.OrderedDict([
  109. ('test_state0', {'result': True}),
  110. ('test_state', {'result': True}),
  111. ]))
  112. ]))
  113. ]),
  114. 'test2': salt.utils.odict.OrderedDict([
  115. ('host1',
  116. salt.utils.odict.OrderedDict([
  117. ('test_state0', {'result': None}),
  118. ('test_state', {'result': True}),
  119. ])),
  120. ('host2',
  121. salt.utils.odict.OrderedDict([
  122. ('test_state0', {'result': True}),
  123. ('test_state', {'result': 'abc'}),
  124. ]))
  125. ])
  126. }
  127. for test, data in six.iteritems(test_valid_true_states):
  128. self.assertTrue(
  129. salt.utils.state.check_result(data),
  130. msg='{0} failed'.format(test))
  131. test_invalid_true_ht_states = {
  132. 'test_onfail_simple2': (
  133. salt.utils.odict.OrderedDict([
  134. ('host1',
  135. salt.utils.odict.OrderedDict([
  136. ('test_vstate0', {'result': False}),
  137. ('test_vstate1', {'result': True}),
  138. ])),
  139. ]),
  140. {
  141. 'test_vstate0': {
  142. '__env__': 'base',
  143. '__sls__': 'a',
  144. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  145. 'run',
  146. {'order': 10002}]},
  147. 'test_vstate1': {
  148. '__env__': 'base',
  149. '__sls__': 'a',
  150. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  151. salt.utils.odict.OrderedDict([
  152. ('onfail_stop', True),
  153. ('onfail',
  154. [salt.utils.odict.OrderedDict([('cmd', 'test_vstate0')])])
  155. ]),
  156. 'run',
  157. {'order': 10004}]},
  158. }
  159. ),
  160. 'test_onfail_integ2': (
  161. salt.utils.odict.OrderedDict([
  162. ('host1',
  163. salt.utils.odict.OrderedDict([
  164. ('t_|-test_ivstate0_|-echo_|-run', {
  165. 'result': False}),
  166. ('cmd_|-test_ivstate0_|-echo_|-run', {
  167. 'result': False}),
  168. ('cmd_|-test_ivstate1_|-echo_|-run', {
  169. 'result': False}),
  170. ])),
  171. ]),
  172. {
  173. 'test_ivstate0': {
  174. '__env__': 'base',
  175. '__sls__': 'a',
  176. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  177. 'run',
  178. {'order': 10002}],
  179. 't': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  180. 'run',
  181. {'order': 10002}]},
  182. 'test_ivstate1': {
  183. '__env__': 'base',
  184. '__sls__': 'a',
  185. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  186. salt.utils.odict.OrderedDict([
  187. ('onfail_stop', False),
  188. ('onfail',
  189. [salt.utils.odict.OrderedDict([('cmd', 'test_ivstate0')])])
  190. ]),
  191. 'run',
  192. {'order': 10004}]},
  193. }
  194. ),
  195. 'test_onfail_integ3': (
  196. salt.utils.odict.OrderedDict([
  197. ('host1',
  198. salt.utils.odict.OrderedDict([
  199. ('t_|-test_ivstate0_|-echo_|-run', {
  200. 'result': True}),
  201. ('cmd_|-test_ivstate0_|-echo_|-run', {
  202. 'result': False}),
  203. ('cmd_|-test_ivstate1_|-echo_|-run', {
  204. 'result': False}),
  205. ])),
  206. ]),
  207. {
  208. 'test_ivstate0': {
  209. '__env__': 'base',
  210. '__sls__': 'a',
  211. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  212. 'run',
  213. {'order': 10002}],
  214. 't': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  215. 'run',
  216. {'order': 10002}]},
  217. 'test_ivstate1': {
  218. '__env__': 'base',
  219. '__sls__': 'a',
  220. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  221. salt.utils.odict.OrderedDict([
  222. ('onfail_stop', False),
  223. ('onfail',
  224. [salt.utils.odict.OrderedDict([('cmd', 'test_ivstate0')])])
  225. ]),
  226. 'run',
  227. {'order': 10004}]},
  228. }
  229. ),
  230. 'test_onfail_integ4': (
  231. salt.utils.odict.OrderedDict([
  232. ('host1',
  233. salt.utils.odict.OrderedDict([
  234. ('t_|-test_ivstate0_|-echo_|-run', {
  235. 'result': False}),
  236. ('cmd_|-test_ivstate0_|-echo_|-run', {
  237. 'result': False}),
  238. ('cmd_|-test_ivstate1_|-echo_|-run', {
  239. 'result': True}),
  240. ])),
  241. ]),
  242. {
  243. 'test_ivstate0': {
  244. '__env__': 'base',
  245. '__sls__': 'a',
  246. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  247. 'run',
  248. {'order': 10002}],
  249. 't': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  250. 'run',
  251. {'order': 10002}]},
  252. 'test_ivstate1': {
  253. '__env__': 'base',
  254. '__sls__': 'a',
  255. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  256. salt.utils.odict.OrderedDict([
  257. ('onfail_stop', False),
  258. ('onfail',
  259. [salt.utils.odict.OrderedDict([('cmd', 'test_ivstate0')])])
  260. ]),
  261. 'run',
  262. {'order': 10004}]},
  263. 'test_ivstate2': {
  264. '__env__': 'base',
  265. '__sls__': 'a',
  266. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  267. salt.utils.odict.OrderedDict([
  268. ('onfail_stop', True),
  269. ('onfail',
  270. [salt.utils.odict.OrderedDict([('cmd', 'test_ivstate0')])])
  271. ]),
  272. 'run',
  273. {'order': 10004}]},
  274. }
  275. ),
  276. 'test_onfail': (
  277. salt.utils.odict.OrderedDict([
  278. ('host1',
  279. salt.utils.odict.OrderedDict([
  280. ('test_state0', {'result': False}),
  281. ('test_state', {'result': True}),
  282. ])),
  283. ]),
  284. None
  285. ),
  286. 'test_onfail_d': (
  287. salt.utils.odict.OrderedDict([
  288. ('host1',
  289. salt.utils.odict.OrderedDict([
  290. ('test_state0', {'result': False}),
  291. ('test_state', {'result': True}),
  292. ])),
  293. ]),
  294. {}
  295. )
  296. }
  297. for test, testdata in six.iteritems(test_invalid_true_ht_states):
  298. data, ht = testdata
  299. for t_ in [a for a in data['host1']]:
  300. tdata = data['host1'][t_]
  301. if '_|-' in t_:
  302. t_ = t_.split('_|-')[1]
  303. tdata['__id__'] = t_
  304. self.assertFalse(
  305. salt.utils.state.check_result(data, highstate=ht),
  306. msg='{0} failed'.format(test))
  307. test_valid_true_ht_states = {
  308. 'test_onfail_integ': (
  309. salt.utils.odict.OrderedDict([
  310. ('host1',
  311. salt.utils.odict.OrderedDict([
  312. ('cmd_|-test_ivstate0_|-echo_|-run', {
  313. 'result': False}),
  314. ('cmd_|-test_ivstate1_|-echo_|-run', {
  315. 'result': True}),
  316. ])),
  317. ]),
  318. {
  319. 'test_ivstate0': {
  320. '__env__': 'base',
  321. '__sls__': 'a',
  322. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  323. 'run',
  324. {'order': 10002}]},
  325. 'test_ivstate1': {
  326. '__env__': 'base',
  327. '__sls__': 'a',
  328. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  329. salt.utils.odict.OrderedDict([
  330. ('onfail_stop', False),
  331. ('onfail',
  332. [salt.utils.odict.OrderedDict([('cmd', 'test_ivstate0')])])
  333. ]),
  334. 'run',
  335. {'order': 10004}]},
  336. }
  337. ),
  338. 'test_onfail_intega3': (
  339. salt.utils.odict.OrderedDict([
  340. ('host1',
  341. salt.utils.odict.OrderedDict([
  342. ('t_|-test_ivstate0_|-echo_|-run', {
  343. 'result': True}),
  344. ('cmd_|-test_ivstate0_|-echo_|-run', {
  345. 'result': False}),
  346. ('cmd_|-test_ivstate1_|-echo_|-run', {
  347. 'result': True}),
  348. ])),
  349. ]),
  350. {
  351. 'test_ivstate0': {
  352. '__env__': 'base',
  353. '__sls__': 'a',
  354. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  355. 'run',
  356. {'order': 10002}],
  357. 't': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  358. 'run',
  359. {'order': 10002}]},
  360. 'test_ivstate1': {
  361. '__env__': 'base',
  362. '__sls__': 'a',
  363. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  364. salt.utils.odict.OrderedDict([
  365. ('onfail_stop', False),
  366. ('onfail',
  367. [salt.utils.odict.OrderedDict([('cmd', 'test_ivstate0')])])
  368. ]),
  369. 'run',
  370. {'order': 10004}]},
  371. }
  372. ),
  373. 'test_onfail_simple': (
  374. salt.utils.odict.OrderedDict([
  375. ('host1',
  376. salt.utils.odict.OrderedDict([
  377. ('test_vstate0', {'result': False}),
  378. ('test_vstate1', {'result': True}),
  379. ])),
  380. ]),
  381. {
  382. 'test_vstate0': {
  383. '__env__': 'base',
  384. '__sls__': 'a',
  385. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  386. 'run',
  387. {'order': 10002}]},
  388. 'test_vstate1': {
  389. '__env__': 'base',
  390. '__sls__': 'a',
  391. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  392. salt.utils.odict.OrderedDict([
  393. ('onfail_stop', False),
  394. ('onfail',
  395. [salt.utils.odict.OrderedDict([('cmd', 'test_vstate0')])])
  396. ]),
  397. 'run',
  398. {'order': 10004}]},
  399. }
  400. ), # order is different
  401. 'test_onfail_simple_rev': (
  402. salt.utils.odict.OrderedDict([
  403. ('host1',
  404. salt.utils.odict.OrderedDict([
  405. ('test_vstate0', {'result': False}),
  406. ('test_vstate1', {'result': True}),
  407. ])),
  408. ]),
  409. {
  410. 'test_vstate0': {
  411. '__env__': 'base',
  412. '__sls__': 'a',
  413. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  414. 'run',
  415. {'order': 10002}]},
  416. 'test_vstate1': {
  417. '__env__': 'base',
  418. '__sls__': 'a',
  419. 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
  420. salt.utils.odict.OrderedDict([
  421. ('onfail',
  422. [salt.utils.odict.OrderedDict([('cmd', 'test_vstate0')])])
  423. ]),
  424. salt.utils.odict.OrderedDict([('onfail_stop', False)]),
  425. 'run',
  426. {'order': 10004}]},
  427. }
  428. )
  429. }
  430. for test, testdata in six.iteritems(test_valid_true_ht_states):
  431. data, ht = testdata
  432. for t_ in [a for a in data['host1']]:
  433. tdata = data['host1'][t_]
  434. if '_|-' in t_:
  435. t_ = t_.split('_|-')[1]
  436. tdata['__id__'] = t_
  437. self.assertTrue(
  438. salt.utils.state.check_result(data, highstate=ht),
  439. msg='{0} failed'.format(test))
  440. test_valid_false_state = {'host1': {'test_state': {'result': False}}}
  441. self.assertFalse(salt.utils.state.check_result(test_valid_false_state))
  442. class UtilStateMergeSubreturnTestcase(TestCase):
  443. '''
  444. Test cases for salt.utils.state.merge_subreturn function.
  445. '''
  446. main_ret = {
  447. 'name': 'primary',
  448. # result may be missing, as primarysalt.utils.state is still in progress
  449. 'comment': '',
  450. 'changes': {},
  451. }
  452. sub_ret = {
  453. 'name': 'secondary',
  454. 'result': True,
  455. 'comment': '',
  456. 'changes': {},
  457. }
  458. def test_merge_result(self):
  459. # result not created if not needed
  460. for no_effect_result in [True, None]:
  461. m = copy.deepcopy(self.main_ret)
  462. s = copy.deepcopy(self.sub_ret)
  463. s['result'] = no_effect_result
  464. res = salt.utils.state.merge_subreturn(m, s)
  465. self.assertNotIn('result', res)
  466. # False subresult is propagated to existing result
  467. for original_result in [True, None, False]:
  468. m = copy.deepcopy(self.main_ret)
  469. m['result'] = original_result
  470. s = copy.deepcopy(self.sub_ret)
  471. s['result'] = False
  472. res = salt.utils.state.merge_subreturn(m, s)
  473. self.assertFalse(res['result'])
  474. # False result cannot be overridden
  475. for any_result in [True, None, False]:
  476. m = copy.deepcopy(self.main_ret)
  477. m['result'] = False
  478. s = copy.deepcopy(self.sub_ret)
  479. s['result'] = any_result
  480. res = salt.utils.state.merge_subreturn(m, s)
  481. self.assertFalse(res['result'])
  482. def test_merge_changes(self):
  483. # The main changes dict should always already exist,
  484. # and there should always be a changes dict in the secondary.
  485. primary_changes = {'old': None, 'new': 'my_resource'}
  486. secondary_changes = {'old': None, 'new': ['alarm-1', 'alarm-2']}
  487. # No changes case
  488. m = copy.deepcopy(self.main_ret)
  489. s = copy.deepcopy(self.sub_ret)
  490. res = salt.utils.state.merge_subreturn(m, s)
  491. self.assertDictEqual(res['changes'], {})
  492. # New changes don't get rid of existing changes
  493. m = copy.deepcopy(self.main_ret)
  494. m['changes'] = copy.deepcopy(primary_changes)
  495. s = copy.deepcopy(self.sub_ret)
  496. s['changes'] = copy.deepcopy(secondary_changes)
  497. res = salt.utils.state.merge_subreturn(m, s)
  498. self.assertDictEqual(res['changes'], {
  499. 'old': None,
  500. 'new': 'my_resource',
  501. 'secondary': secondary_changes,
  502. })
  503. # The subkey parameter is respected
  504. m = copy.deepcopy(self.main_ret)
  505. m['changes'] = copy.deepcopy(primary_changes)
  506. s = copy.deepcopy(self.sub_ret)
  507. s['changes'] = copy.deepcopy(secondary_changes)
  508. res = salt.utils.state.merge_subreturn(m, s, subkey='alarms')
  509. self.assertDictEqual(res['changes'], {
  510. 'old': None,
  511. 'new': 'my_resource',
  512. 'alarms': secondary_changes,
  513. })
  514. def test_merge_comments(self):
  515. main_comment_1 = 'First primary comment.'
  516. main_comment_2 = 'Second primary comment.'
  517. sub_comment_1 = 'First secondary comment,\nwhich spans two lines.'
  518. sub_comment_2 = 'Second secondary comment: {0}'.format(
  519. 'some error\n And a traceback',
  520. )
  521. final_comment = textwrap.dedent('''\
  522. First primary comment.
  523. Second primary comment.
  524. First secondary comment,
  525. which spans two lines.
  526. Second secondary comment: some error
  527. And a traceback
  528. '''.rstrip())
  529. # Joining two strings
  530. m = copy.deepcopy(self.main_ret)
  531. m['comment'] = main_comment_1 + '\n' + main_comment_2
  532. s = copy.deepcopy(self.sub_ret)
  533. s['comment'] = sub_comment_1 + '\n' + sub_comment_2
  534. res = salt.utils.state.merge_subreturn(m, s)
  535. self.assertMultiLineEqual(res['comment'], final_comment)
  536. # Joining string and a list
  537. m = copy.deepcopy(self.main_ret)
  538. m['comment'] = main_comment_1 + '\n' + main_comment_2
  539. s = copy.deepcopy(self.sub_ret)
  540. s['comment'] = [sub_comment_1, sub_comment_2]
  541. res = salt.utils.state.merge_subreturn(m, s)
  542. self.assertMultiLineEqual(res['comment'], final_comment)
  543. # For tests where output is a list,
  544. # also test that final joined output will match
  545. # Joining list and a string
  546. m = copy.deepcopy(self.main_ret)
  547. m['comment'] = [main_comment_1, main_comment_2]
  548. s = copy.deepcopy(self.sub_ret)
  549. s['comment'] = sub_comment_1 + '\n' + sub_comment_2
  550. res = salt.utils.state.merge_subreturn(m, s)
  551. self.assertEqual(res['comment'], [
  552. main_comment_1,
  553. main_comment_2,
  554. sub_comment_1 + '\n' + sub_comment_2,
  555. ])
  556. self.assertMultiLineEqual('\n'.join(res['comment']), final_comment)
  557. # Joining two lists
  558. m = copy.deepcopy(self.main_ret)
  559. m['comment'] = [main_comment_1, main_comment_2]
  560. s = copy.deepcopy(self.sub_ret)
  561. s['comment'] = [sub_comment_1, sub_comment_2]
  562. res = salt.utils.state.merge_subreturn(m, s)
  563. self.assertEqual(res['comment'], [
  564. main_comment_1,
  565. main_comment_2,
  566. sub_comment_1,
  567. sub_comment_2,
  568. ])
  569. self.assertMultiLineEqual('\n'.join(res['comment']), final_comment)
  570. def test_merge_empty_comments(self):
  571. # Since the primarysalt.utils.state is in progress,
  572. # the main comment may be empty, either '' or [].
  573. # Note that [''] is a degenerate case and should never happen,
  574. # hence the behavior is left unspecified in that case.
  575. # The secondary comment should never be empty,
  576. # because thatsalt.utils.state has already returned,
  577. # so we leave the behavior unspecified in that case.
  578. sub_comment_1 = 'Secondary comment about changes:'
  579. sub_comment_2 = 'A diff that goes with the previous comment'
  580. # No contributions from primary
  581. final_comment = sub_comment_1 + '\n' + sub_comment_2
  582. # Joining empty string and a string
  583. m = copy.deepcopy(self.main_ret)
  584. m['comment'] = ''
  585. s = copy.deepcopy(self.sub_ret)
  586. s['comment'] = sub_comment_1 + '\n' + sub_comment_2
  587. res = salt.utils.state.merge_subreturn(m, s)
  588. self.assertEqual(res['comment'], final_comment)
  589. # Joining empty string and a list
  590. m = copy.deepcopy(self.main_ret)
  591. m['comment'] = ''
  592. s = copy.deepcopy(self.sub_ret)
  593. s['comment'] = [sub_comment_1, sub_comment_2]
  594. res = salt.utils.state.merge_subreturn(m, s)
  595. self.assertEqual(res['comment'], final_comment)
  596. # For tests where output is a list,
  597. # also test that final joined output will match
  598. # Joining empty list and a string
  599. m = copy.deepcopy(self.main_ret)
  600. m['comment'] = []
  601. s = copy.deepcopy(self.sub_ret)
  602. s['comment'] = sub_comment_1 + '\n' + sub_comment_2
  603. res = salt.utils.state.merge_subreturn(m, s)
  604. self.assertEqual(res['comment'], [final_comment])
  605. self.assertEqual('\n'.join(res['comment']), final_comment)
  606. # Joining empty list and a list
  607. m = copy.deepcopy(self.main_ret)
  608. m['comment'] = []
  609. s = copy.deepcopy(self.sub_ret)
  610. s['comment'] = [sub_comment_1, sub_comment_2]
  611. res = salt.utils.state.merge_subreturn(m, s)
  612. self.assertEqual(res['comment'], [sub_comment_1, sub_comment_2])
  613. self.assertEqual('\n'.join(res['comment']), final_comment)