test_dictupdate.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. # -*- coding: utf-8 -*-
  2. # Import python libs
  3. from __future__ import absolute_import, print_function, unicode_literals
  4. import copy
  5. # Import Salt Testing libs
  6. from tests.support.unit import TestCase
  7. # Import Salt libs
  8. import salt.utils.dictupdate as dictupdate
  9. class UtilDictupdateTestCase(TestCase):
  10. dict1 = {'A': 'B', 'C': {'D': 'E', 'F': {'G': 'H', 'I': 'J'}}}
  11. def test_update(self):
  12. # level 1 value changes
  13. mdict = copy.deepcopy(self.dict1)
  14. mdict['A'] = 'Z'
  15. res = dictupdate.update(copy.deepcopy(self.dict1), {'A': 'Z'})
  16. self.assertEqual(res, mdict)
  17. # level 1 value changes (list replacement)
  18. mdict = copy.deepcopy(self.dict1)
  19. mdict['A'] = [1, 2]
  20. res = dictupdate.update(copy.deepcopy(mdict), {'A': [2, 3]},
  21. merge_lists=False)
  22. mdict['A'] = [2, 3]
  23. self.assertEqual(res, mdict)
  24. # level 1 value changes (list merge)
  25. mdict = copy.deepcopy(self.dict1)
  26. mdict['A'] = [1, 2]
  27. res = dictupdate.update(copy.deepcopy(mdict), {'A': [3, 4]},
  28. merge_lists=True)
  29. mdict['A'] = [1, 2, 3, 4]
  30. self.assertEqual(res, mdict)
  31. # level 1 value changes (list merge, remove duplicates, preserve order)
  32. mdict = copy.deepcopy(self.dict1)
  33. mdict['A'] = [1, 2]
  34. res = dictupdate.update(copy.deepcopy(mdict), {'A': [4, 3, 2, 1]},
  35. merge_lists=True)
  36. mdict['A'] = [1, 2, 4, 3]
  37. self.assertEqual(res, mdict)
  38. # level 2 value changes
  39. mdict = copy.deepcopy(self.dict1)
  40. mdict['C']['D'] = 'Z'
  41. res = dictupdate.update(copy.deepcopy(self.dict1), {'C': {'D': 'Z'}})
  42. self.assertEqual(res, mdict)
  43. # level 2 value changes (list replacement)
  44. mdict = copy.deepcopy(self.dict1)
  45. mdict['C']['D'] = ['a', 'b']
  46. res = dictupdate.update(copy.deepcopy(mdict), {'C': {'D': ['c', 'd']}},
  47. merge_lists=False)
  48. mdict['C']['D'] = ['c', 'd']
  49. self.assertEqual(res, mdict)
  50. # level 2 value changes (list merge)
  51. mdict = copy.deepcopy(self.dict1)
  52. mdict['C']['D'] = ['a', 'b']
  53. res = dictupdate.update(copy.deepcopy(mdict), {'C': {'D': ['c', 'd']}},
  54. merge_lists=True)
  55. mdict['C']['D'] = ['a', 'b', 'c', 'd']
  56. self.assertEqual(res, mdict)
  57. # level 2 value changes (list merge, remove duplicates, preserve order)
  58. mdict = copy.deepcopy(self.dict1)
  59. mdict['C']['D'] = ['a', 'b']
  60. res = dictupdate.update(copy.deepcopy(mdict),
  61. {'C': {'D': ['d', 'c', 'b', 'a']}},
  62. merge_lists=True)
  63. mdict['C']['D'] = ['a', 'b', 'd', 'c']
  64. self.assertEqual(res, mdict)
  65. # level 3 value changes
  66. mdict = copy.deepcopy(self.dict1)
  67. mdict['C']['F']['G'] = 'Z'
  68. res = dictupdate.update(
  69. copy.deepcopy(self.dict1),
  70. {'C': {'F': {'G': 'Z'}}}
  71. )
  72. self.assertEqual(res, mdict)
  73. # level 3 value changes (list replacement)
  74. mdict = copy.deepcopy(self.dict1)
  75. mdict['C']['F']['G'] = ['a', 'b']
  76. res = dictupdate.update(copy.deepcopy(mdict),
  77. {'C': {'F': {'G': ['c', 'd']}}}, merge_lists=False)
  78. mdict['C']['F']['G'] = ['c', 'd']
  79. self.assertEqual(res, mdict)
  80. # level 3 value changes (list merge)
  81. mdict = copy.deepcopy(self.dict1)
  82. mdict['C']['F']['G'] = ['a', 'b']
  83. res = dictupdate.update(copy.deepcopy(mdict),
  84. {'C': {'F': {'G': ['c', 'd']}}}, merge_lists=True)
  85. mdict['C']['F']['G'] = ['a', 'b', 'c', 'd']
  86. self.assertEqual(res, mdict)
  87. # level 3 value changes (list merge, remove duplicates, preserve order)
  88. mdict = copy.deepcopy(self.dict1)
  89. mdict['C']['F']['G'] = ['a', 'b']
  90. res = dictupdate.update(copy.deepcopy(mdict),
  91. {'C': {'F': {'G': ['d', 'c', 'b', 'a']}}}, merge_lists=True)
  92. mdict['C']['F']['G'] = ['a', 'b', 'd', 'c']
  93. self.assertEqual(res, mdict)
  94. # replace a sub-dictionary
  95. mdict = copy.deepcopy(self.dict1)
  96. mdict['C'] = 'Z'
  97. res = dictupdate.update(copy.deepcopy(self.dict1), {'C': 'Z'})
  98. self.assertEqual(res, mdict)
  99. # add a new scalar value
  100. mdict = copy.deepcopy(self.dict1)
  101. mdict['Z'] = 'Y'
  102. res = dictupdate.update(copy.deepcopy(self.dict1), {'Z': 'Y'})
  103. self.assertEqual(res, mdict)
  104. # add a dictionary
  105. mdict = copy.deepcopy(self.dict1)
  106. mdict['Z'] = {'Y': 'X'}
  107. res = dictupdate.update(copy.deepcopy(self.dict1), {'Z': {'Y': 'X'}})
  108. self.assertEqual(res, mdict)
  109. # add a nested dictionary
  110. mdict = copy.deepcopy(self.dict1)
  111. mdict['Z'] = {'Y': {'X': 'W'}}
  112. res = dictupdate.update(
  113. copy.deepcopy(self.dict1),
  114. {'Z': {'Y': {'X': 'W'}}}
  115. )
  116. self.assertEqual(res, mdict)
  117. class UtilDictMergeTestCase(TestCase):
  118. dict1 = {'A': 'B', 'C': {'D': 'E', 'F': {'G': 'H', 'I': 'J'}}}
  119. def test_merge_overwrite_traditional(self):
  120. '''
  121. Test traditional overwrite, wherein a key in the second dict overwrites a key in the first
  122. '''
  123. mdict = copy.deepcopy(self.dict1)
  124. mdict['A'] = 'b'
  125. ret = dictupdate.merge_overwrite(copy.deepcopy(self.dict1), {'A': 'b'})
  126. self.assertEqual(mdict, ret)
  127. def test_merge_overwrite_missing_source_key(self):
  128. '''
  129. Test case wherein the overwrite strategy is used but a key in the second dict is
  130. not present in the first
  131. '''
  132. mdict = copy.deepcopy(self.dict1)
  133. mdict['D'] = 'new'
  134. ret = dictupdate.merge_overwrite(copy.deepcopy(self.dict1), {'D': 'new'})
  135. self.assertEqual(mdict, ret)
  136. def test_merge_aggregate_traditional(self):
  137. '''
  138. Test traditional aggregation, where a val from dict2 overwrites one
  139. present in dict1
  140. '''
  141. mdict = copy.deepcopy(self.dict1)
  142. mdict['A'] = 'b'
  143. ret = dictupdate.merge_overwrite(copy.deepcopy(self.dict1), {'A': 'b'})
  144. self.assertEqual(mdict, ret)
  145. def test_merge_list_traditional(self):
  146. '''
  147. Test traditional list merge, where a key present in dict2 will be converted
  148. to a list
  149. '''
  150. mdict = copy.deepcopy(self.dict1)
  151. mdict['A'] = ['B', 'b']
  152. ret = dictupdate.merge_list(copy.deepcopy(self.dict1), {'A': 'b'})
  153. self.assertEqual(mdict, ret)
  154. def test_merge_list_append(self):
  155. '''
  156. This codifies the intended behaviour that items merged into a dict val that is already
  157. a list that those items will *appended* to the list, and not magically merged in
  158. '''
  159. mdict = copy.deepcopy(self.dict1)
  160. mdict['A'] = ['B', 'b', 'c']
  161. # Prepare a modified copy of dict1 that has a list as a val for the key of 'A'
  162. mdict1 = copy.deepcopy(self.dict1)
  163. mdict1['A'] = ['B']
  164. ret = dictupdate.merge_list(mdict1, {'A': ['b', 'c']})
  165. self.assertEqual({'A': [['B'], ['b', 'c']], 'C': {'D': 'E', 'F': {'I': 'J', 'G': 'H'}}}, ret)