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.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 == {
  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_repo_list_command_does_not_duplicate_flags_or_raise():
  106. arguments = borgmatic.commands.arguments.parse_arguments({}, 'repo-list')['repo-list']
  107. for argument_name in dir(arguments):
  108. if argument_name.startswith('_'):
  109. continue
  110. command = borgmatic.borg.repo_list.make_repo_list_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. )