test_commands.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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.repo_list
  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 == dict.fromkeys(flag_counts, 1), (
  25. f"Duplicate flags found in: {' '.join(command)}"
  26. )
  27. if '--json' in command:
  28. return '{}'
  29. return None
  30. def fuzz_argument(arguments, argument_name):
  31. '''
  32. Given an argparse.Namespace instance of arguments and an argument name in it, copy the arguments
  33. namespace and set the argument name in the copy with a fake value. Return the copied arguments.
  34. This is useful for "fuzzing" a unit under test by passing it each possible argument in turn,
  35. making sure it doesn't blow up or duplicate Borg arguments.
  36. '''
  37. arguments_copy = copy.copy(arguments)
  38. value = getattr(arguments_copy, argument_name)
  39. setattr(arguments_copy, argument_name, not value if isinstance(value, bool) else 'value')
  40. return arguments_copy
  41. def test_transfer_archives_command_does_not_duplicate_flags_or_raise():
  42. arguments = borgmatic.commands.arguments.parse_arguments(
  43. {},
  44. 'transfer',
  45. '--source-repository',
  46. 'foo',
  47. )['transfer']
  48. flexmock(borgmatic.borg.transfer).should_receive('execute_command').replace_with(
  49. assert_command_does_not_duplicate_flags,
  50. )
  51. for argument_name in dir(arguments):
  52. if argument_name.startswith('_'):
  53. continue
  54. borgmatic.borg.transfer.transfer_archives(
  55. False,
  56. 'repo',
  57. {},
  58. '2.3.4',
  59. fuzz_argument(arguments, argument_name),
  60. global_arguments=flexmock(log_json=False),
  61. )
  62. def test_prune_archives_command_does_not_duplicate_flags_or_raise():
  63. arguments = borgmatic.commands.arguments.parse_arguments({}, 'prune')['prune']
  64. flexmock(borgmatic.borg.prune).should_receive('execute_command').replace_with(
  65. assert_command_does_not_duplicate_flags,
  66. )
  67. for argument_name in dir(arguments):
  68. if argument_name.startswith('_'):
  69. continue
  70. borgmatic.borg.prune.prune_archives(
  71. False,
  72. 'repo',
  73. {},
  74. '2.3.4',
  75. fuzz_argument(arguments, argument_name),
  76. argparse.Namespace(log_json=False),
  77. )
  78. def test_mount_archive_command_does_not_duplicate_flags_or_raise():
  79. arguments = borgmatic.commands.arguments.parse_arguments({}, 'mount', '--mount-point', 'tmp')[
  80. 'mount'
  81. ]
  82. flexmock(borgmatic.borg.mount).should_receive('execute_command').replace_with(
  83. assert_command_does_not_duplicate_flags,
  84. )
  85. for argument_name in dir(arguments):
  86. if argument_name.startswith('_'):
  87. continue
  88. borgmatic.borg.mount.mount_archive(
  89. 'repo',
  90. 'archive',
  91. fuzz_argument(arguments, argument_name),
  92. {},
  93. '2.3.4',
  94. argparse.Namespace(log_json=False),
  95. )
  96. def test_make_list_command_does_not_duplicate_flags_or_raise():
  97. arguments = borgmatic.commands.arguments.parse_arguments({}, 'list')['list']
  98. for argument_name in dir(arguments):
  99. if argument_name.startswith('_'):
  100. continue
  101. command = borgmatic.borg.list.make_list_command(
  102. 'repo',
  103. {},
  104. '2.3.4',
  105. fuzz_argument(arguments, argument_name),
  106. argparse.Namespace(log_json=False),
  107. )
  108. assert_command_does_not_duplicate_flags(command)
  109. def test_make_repo_list_command_does_not_duplicate_flags_or_raise():
  110. arguments = borgmatic.commands.arguments.parse_arguments({}, 'repo-list')['repo-list']
  111. for argument_name in dir(arguments):
  112. if argument_name.startswith('_'):
  113. continue
  114. command = borgmatic.borg.repo_list.make_repo_list_command(
  115. 'repo',
  116. {},
  117. '2.3.4',
  118. fuzz_argument(arguments, argument_name),
  119. global_arguments=flexmock(log_json=True),
  120. )
  121. assert_command_does_not_duplicate_flags(command)
  122. def test_display_archives_info_command_does_not_duplicate_flags_or_raise():
  123. arguments = borgmatic.commands.arguments.parse_arguments({}, 'info')['info']
  124. flexmock(borgmatic.borg.info).should_receive('execute_command_and_capture_output').replace_with(
  125. assert_command_does_not_duplicate_flags,
  126. )
  127. flexmock(borgmatic.borg.info).should_receive('execute_command').replace_with(
  128. assert_command_does_not_duplicate_flags,
  129. )
  130. for argument_name in dir(arguments):
  131. if argument_name.startswith('_'):
  132. continue
  133. borgmatic.borg.info.display_archives_info(
  134. 'repo',
  135. {},
  136. '2.3.4',
  137. fuzz_argument(arguments, argument_name),
  138. argparse.Namespace(log_json=False),
  139. )