test_env_provider.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. """
  2. Tests for the env binary provider plugin.
  3. Tests the real env provider hook with actual system binaries.
  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 env provider hook
  14. PLUGIN_DIR = Path(__file__).parent.parent
  15. INSTALL_HOOK = next(PLUGIN_DIR.glob('on_Binary__*_env_install.py'), None)
  16. class TestEnvProviderHook(TestCase):
  17. """Test the env 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_finds_python(self):
  29. """Hook should find python3 binary in PATH."""
  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=python3',
  36. '--binary-id=test-uuid',
  37. '--machine-id=test-machine',
  38. ],
  39. capture_output=True,
  40. text=True,
  41. timeout=30,
  42. env=env
  43. )
  44. # Should succeed and output JSONL
  45. self.assertEqual(result.returncode, 0, f"Hook failed: {result.stderr}")
  46. # Parse JSONL output
  47. for line in result.stdout.split('\n'):
  48. line = line.strip()
  49. if line.startswith('{'):
  50. try:
  51. record = json.loads(line)
  52. if record.get('type') == 'Binary' and record.get('name') == 'python3':
  53. self.assertEqual(record['binprovider'], 'env')
  54. self.assertTrue(record['abspath'])
  55. self.assertTrue(Path(record['abspath']).exists())
  56. return
  57. except json.JSONDecodeError:
  58. continue
  59. self.fail("No Binary JSONL record found in output")
  60. def test_hook_finds_bash(self):
  61. """Hook should find bash binary in PATH."""
  62. env = os.environ.copy()
  63. env['DATA_DIR'] = self.temp_dir
  64. result = subprocess.run(
  65. [
  66. sys.executable, str(INSTALL_HOOK),
  67. '--name=bash',
  68. '--binary-id=test-uuid',
  69. '--machine-id=test-machine',
  70. ],
  71. capture_output=True,
  72. text=True,
  73. timeout=30,
  74. env=env
  75. )
  76. # Should succeed and output JSONL
  77. self.assertEqual(result.returncode, 0, f"Hook failed: {result.stderr}")
  78. # Parse JSONL output
  79. for line in result.stdout.split('\n'):
  80. line = line.strip()
  81. if line.startswith('{'):
  82. try:
  83. record = json.loads(line)
  84. if record.get('type') == 'Binary' and record.get('name') == 'bash':
  85. self.assertEqual(record['binprovider'], 'env')
  86. self.assertTrue(record['abspath'])
  87. return
  88. except json.JSONDecodeError:
  89. continue
  90. self.fail("No Binary JSONL record found in output")
  91. def test_hook_fails_for_missing_binary(self):
  92. """Hook should fail for binary not in PATH."""
  93. env = os.environ.copy()
  94. env['DATA_DIR'] = self.temp_dir
  95. result = subprocess.run(
  96. [
  97. sys.executable, str(INSTALL_HOOK),
  98. '--name=nonexistent_binary_xyz123',
  99. '--binary-id=test-uuid',
  100. '--machine-id=test-machine',
  101. ],
  102. capture_output=True,
  103. text=True,
  104. timeout=30,
  105. env=env
  106. )
  107. # Should fail with exit code 1
  108. self.assertEqual(result.returncode, 1)
  109. self.assertIn('not found', result.stderr.lower())
  110. def test_hook_skips_when_env_not_allowed(self):
  111. """Hook should skip when env not in allowed binproviders."""
  112. env = os.environ.copy()
  113. env['DATA_DIR'] = self.temp_dir
  114. result = subprocess.run(
  115. [
  116. sys.executable, str(INSTALL_HOOK),
  117. '--name=python3',
  118. '--binary-id=test-uuid',
  119. '--machine-id=test-machine',
  120. '--binproviders=pip,apt', # env not allowed
  121. ],
  122. capture_output=True,
  123. text=True,
  124. timeout=30,
  125. env=env
  126. )
  127. # Should exit cleanly (code 0) when env not allowed
  128. self.assertEqual(result.returncode, 0)
  129. self.assertIn('env provider not allowed', result.stderr)
  130. if __name__ == '__main__':
  131. pytest.main([__file__, '-v'])