test_commands.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import argparse
  2. import copy
  3. from flexmock import flexmock
  4. import borgmatic.borg.info
  5. import borgmatic.borg.list
  6. import borgmatic.borg.mount
  7. import borgmatic.borg.prune
  8. import borgmatic.borg.rlist
  9. import borgmatic.borg.transfer
  10. import borgmatic.commands.arguments
  11. def assert_command_does_not_duplicate_flags(command, *args, **kwargs):
  12. '''
  13. Assert that the given Borg command sequence does not contain any duplicated flags, e.g.
  14. "--match-archives" twice anywhere in the command.
  15. '''
  16. flag_counts = {}
  17. for flag_name in command:
  18. if not flag_name.startswith('--'):
  19. continue
  20. if flag_name in flag_counts:
  21. flag_counts[flag_name] += 1
  22. else:
  23. flag_counts[flag_name] = 1
  24. assert flag_counts == {
  25. flag_name: 1 for flag_name in flag_counts
  26. }, f"Duplicate flags found in: {' '.join(command)}"
  27. if '--json' in command:
  28. return '{}'
  29. def fuzz_argument(arguments, argument_name):
  30. '''
  31. Given an argparse.Namespace instance of arguments and an argument name in it, copy the arguments
  32. namespace and set the argument name in the copy with a fake value. Return the copied arguments.
  33. This is useful for "fuzzing" a unit under test by passing it each possible argument in turn,
  34. making sure it doesn't blow up or duplicate Borg arguments.
  35. '''
  36. arguments_copy = copy.copy(arguments)
  37. value = getattr(arguments_copy, argument_name)
  38. setattr(arguments_copy, argument_name, not value if isinstance(value, bool) else 'value')
  39. return arguments_copy
  40. def test_transfer_archives_command_does_not_duplicate_flags_or_raise():
  41. arguments = borgmatic.commands.arguments.parse_arguments(
  42. 'transfer', '--source-repository', 'foo'
  43. )['transfer']
  44. flexmock(borgmatic.borg.transfer).should_receive('execute_command').replace_with(
  45. assert_command_does_not_duplicate_flags
  46. )
  47. for argument_name in dir(arguments):
  48. if argument_name.startswith('_'):
  49. continue
  50. borgmatic.borg.transfer.transfer_archives(
  51. False,
  52. 'repo',
  53. {},
  54. '2.3.4',
  55. fuzz_argument(arguments, argument_name),
  56. global_arguments=flexmock(log_json=False),
  57. )
  58. def test_prune_archives_command_does_not_duplicate_flags_or_raise():
  59. arguments = borgmatic.commands.arguments.parse_arguments('prune')['prune']
  60. flexmock(borgmatic.borg.prune).should_receive('execute_command').replace_with(
  61. assert_command_does_not_duplicate_flags
  62. )
  63. for argument_name in dir(arguments):
  64. if argument_name.startswith('_'):
  65. continue
  66. borgmatic.borg.prune.prune_archives(
  67. False,
  68. 'repo',
  69. {},
  70. '2.3.4',
  71. fuzz_argument(arguments, argument_name),
  72. argparse.Namespace(log_json=False),
  73. )
  74. def test_mount_archive_command_does_not_duplicate_flags_or_raise():
  75. arguments = borgmatic.commands.arguments.parse_arguments('mount', '--mount-point', 'tmp')[
  76. 'mount'
  77. ]
  78. flexmock(borgmatic.borg.mount).should_receive('execute_command').replace_with(
  79. assert_command_does_not_duplicate_flags
  80. )
  81. for argument_name in dir(arguments):
  82. if argument_name.startswith('_'):
  83. continue
  84. borgmatic.borg.mount.mount_archive(
  85. 'repo',
  86. 'archive',
  87. fuzz_argument(arguments, argument_name),
  88. {},
  89. '2.3.4',
  90. argparse.Namespace(log_json=False),
  91. )
  92. def test_make_list_command_does_not_duplicate_flags_or_raise():
  93. arguments = borgmatic.commands.arguments.parse_arguments('list')['list']
  94. for argument_name in dir(arguments):
  95. if argument_name.startswith('_'):
  96. continue
  97. command = borgmatic.borg.list.make_list_command(
  98. 'repo',
  99. {},
  100. '2.3.4',
  101. fuzz_argument(arguments, argument_name),
  102. argparse.Namespace(log_json=False),
  103. )
  104. assert_command_does_not_duplicate_flags(command)
  105. def test_make_rlist_command_does_not_duplicate_flags_or_raise():
  106. arguments = borgmatic.commands.arguments.parse_arguments('rlist')['rlist']
  107. for argument_name in dir(arguments):
  108. if argument_name.startswith('_'):
  109. continue
  110. command = borgmatic.borg.rlist.make_rlist_command(
  111. 'repo',
  112. {},
  113. '2.3.4',
  114. fuzz_argument(arguments, argument_name),
  115. global_arguments=flexmock(log_json=True),
  116. )
  117. assert_command_does_not_duplicate_flags(command)
  118. def test_display_archives_info_command_does_not_duplicate_flags_or_raise():
  119. arguments = borgmatic.commands.arguments.parse_arguments('info')['info']
  120. flexmock(borgmatic.borg.info).should_receive('execute_command_and_capture_output').replace_with(
  121. assert_command_does_not_duplicate_flags
  122. )
  123. flexmock(borgmatic.borg.info).should_receive('execute_command').replace_with(
  124. assert_command_does_not_duplicate_flags
  125. )
  126. for argument_name in dir(arguments):
  127. if argument_name.startswith('_'):
  128. continue
  129. borgmatic.borg.info.display_archives_info(
  130. 'repo',
  131. {},
  132. '2.3.4',
  133. fuzz_argument(arguments, argument_name),
  134. argparse.Namespace(log_json=False),
  135. )