test_custom_provider.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. """
  2. Tests for the custom binary provider plugin.
  3. Tests the custom bash binary installer with safe commands.
  4. """
  5. import json
  6. import os
  7. import subprocess
  8. import sys
  9. import tempfile
  10. from pathlib import Path
  11. import pytest
  12. from django.test import TestCase
  13. # Get the path to the custom provider hook
  14. PLUGIN_DIR = Path(__file__).parent.parent
  15. INSTALL_HOOK = next(PLUGIN_DIR.glob('on_Binary__*_custom_install.py'), None)
  16. class TestCustomProviderHook(TestCase):
  17. """Test the custom binary provider hook."""
  18. def setUp(self):
  19. """Set up test environment."""
  20. self.temp_dir = tempfile.mkdtemp()
  21. def tearDown(self):
  22. """Clean up."""
  23. import shutil
  24. shutil.rmtree(self.temp_dir, ignore_errors=True)
  25. def test_hook_script_exists(self):
  26. """Hook script should exist."""
  27. self.assertTrue(INSTALL_HOOK and INSTALL_HOOK.exists(), f"Hook not found: {INSTALL_HOOK}")
  28. def test_hook_skips_when_custom_not_allowed(self):
  29. """Hook should skip when custom not in allowed binproviders."""
  30. env = os.environ.copy()
  31. env['DATA_DIR'] = self.temp_dir
  32. result = subprocess.run(
  33. [
  34. sys.executable, str(INSTALL_HOOK),
  35. '--name=echo',
  36. '--binary-id=test-uuid',
  37. '--machine-id=test-machine',
  38. '--binproviders=pip,apt', # custom not allowed
  39. '--custom-cmd=echo hello',
  40. ],
  41. capture_output=True,
  42. text=True,
  43. timeout=30,
  44. env=env
  45. )
  46. # Should exit cleanly (code 0) when custom not allowed
  47. self.assertEqual(result.returncode, 0)
  48. self.assertIn('custom provider not allowed', result.stderr)
  49. def test_hook_runs_custom_command_and_finds_binary(self):
  50. """Hook should run custom command and find the binary in PATH."""
  51. env = os.environ.copy()
  52. env['DATA_DIR'] = self.temp_dir
  53. # Use a simple echo command that doesn't actually install anything
  54. # Then check for 'echo' which is already in PATH
  55. result = subprocess.run(
  56. [
  57. sys.executable, str(INSTALL_HOOK),
  58. '--name=echo',
  59. '--binary-id=test-uuid',
  60. '--machine-id=test-machine',
  61. '--custom-cmd=echo "custom install simulation"',
  62. ],
  63. capture_output=True,
  64. text=True,
  65. timeout=30,
  66. env=env
  67. )
  68. # Should succeed since echo is in PATH
  69. self.assertEqual(result.returncode, 0, f"Hook failed: {result.stderr}")
  70. # Parse JSONL output
  71. for line in result.stdout.split('\n'):
  72. line = line.strip()
  73. if line.startswith('{'):
  74. try:
  75. record = json.loads(line)
  76. if record.get('type') == 'Binary' and record.get('name') == 'echo':
  77. self.assertEqual(record['binprovider'], 'custom')
  78. self.assertTrue(record['abspath'])
  79. return
  80. except json.JSONDecodeError:
  81. continue
  82. self.fail("No Binary JSONL record found in output")
  83. def test_hook_fails_for_missing_binary_after_command(self):
  84. """Hook should fail if binary not found after running custom command."""
  85. env = os.environ.copy()
  86. env['DATA_DIR'] = self.temp_dir
  87. result = subprocess.run(
  88. [
  89. sys.executable, str(INSTALL_HOOK),
  90. '--name=nonexistent_binary_xyz123',
  91. '--binary-id=test-uuid',
  92. '--machine-id=test-machine',
  93. '--custom-cmd=echo "failed install"', # Doesn't actually install
  94. ],
  95. capture_output=True,
  96. text=True,
  97. timeout=30,
  98. env=env
  99. )
  100. # Should fail since binary not found after command
  101. self.assertEqual(result.returncode, 1)
  102. self.assertIn('not found', result.stderr.lower())
  103. def test_hook_fails_for_failing_command(self):
  104. """Hook should fail if custom command returns non-zero exit code."""
  105. env = os.environ.copy()
  106. env['DATA_DIR'] = self.temp_dir
  107. result = subprocess.run(
  108. [
  109. sys.executable, str(INSTALL_HOOK),
  110. '--name=echo',
  111. '--binary-id=test-uuid',
  112. '--machine-id=test-machine',
  113. '--custom-cmd=exit 1', # Command that fails
  114. ],
  115. capture_output=True,
  116. text=True,
  117. timeout=30,
  118. env=env
  119. )
  120. # Should fail with exit code 1
  121. self.assertEqual(result.returncode, 1)
  122. if __name__ == '__main__':
  123. pytest.main([__file__, '-v'])