test_commands.py 5.2 KB

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