/ tooling / shadow-runner / test_filter.py
test_filter.py
  1  #!/usr/bin/env python3
  2  """
  3  Unit tests for Shadow Runner filter logic.
  4  """
  5  
  6  import os
  7  import sys
  8  
  9  # Add parent directory to path for imports
 10  sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
 11  
 12  import pytest
 13  from filter import should_use_shadow, get_speed, get_estimated_duration, REPO_SPEED
 14  
 15  
 16  class TestRepoClassification:
 17      def test_all_repos_classified(self):
 18          """Verify all repos appear in exactly one speed category."""
 19          fast = set(REPO_SPEED["fast"])
 20          medium = set(REPO_SPEED["medium"])
 21          slow = set(REPO_SPEED["slow"])
 22  
 23          # No overlaps
 24          assert fast.isdisjoint(medium), "Fast and medium overlap"
 25          assert fast.isdisjoint(slow), "Fast and slow overlap"
 26          assert medium.isdisjoint(slow), "Medium and slow overlap"
 27  
 28      def test_get_speed_fast(self):
 29          assert get_speed("acdc-core") == "fast"
 30          assert get_speed("sdk") == "fast"
 31          assert get_speed("acdc-wallet") == "fast"
 32  
 33      def test_get_speed_medium(self):
 34          assert get_speed("adnet") == "medium"
 35          assert get_speed("adl") == "medium"
 36          assert get_speed("wallet-core") == "medium"
 37  
 38      def test_get_speed_slow(self):
 39          assert get_speed("alphavm") == "slow"
 40          assert get_speed("deltavm") == "slow"
 41          assert get_speed("alphaos") == "slow"
 42          assert get_speed("deltaos") == "slow"
 43  
 44      def test_get_speed_unknown(self):
 45          assert get_speed("nonexistent-repo") == "unknown"
 46  
 47  
 48  class TestShouldUseShadow:
 49      # Fast repos - never use shadow
 50      def test_fast_repo_returns_false(self):
 51          result, reason = should_use_shadow("acdc-core", {})
 52          assert result is False
 53          assert "fast" in reason.lower()
 54  
 55      def test_fast_repo_ignores_context(self):
 56          result, _ = should_use_shadow("sdk", {"full_suite": True})
 57          assert result is False
 58  
 59      # Slow repos - always use shadow (unless interactive)
 60      def test_slow_repo_returns_true(self):
 61          result, reason = should_use_shadow("alphavm", {})
 62          assert result is True
 63          assert "60-90min" in reason
 64  
 65      def test_slow_repo_with_interactive_returns_false(self):
 66          result, reason = should_use_shadow("deltavm", {"interactive": True})
 67          assert result is False
 68          assert "interactive" in reason.lower()
 69  
 70      def test_slow_repo_with_single_test_returns_false(self):
 71          result, reason = should_use_shadow("alphaos", {"single_test": True})
 72          assert result is False
 73          assert "single test" in reason.lower()
 74  
 75      # Medium repos - depends on context
 76      def test_medium_repo_full_suite_returns_true(self):
 77          result, reason = should_use_shadow("adnet", {"full_suite": True})
 78          assert result is True
 79          assert "30-45min" in reason
 80  
 81      def test_medium_repo_default_returns_true(self):
 82          # Default is full_suite=True
 83          result, _ = should_use_shadow("adl", {})
 84          assert result is True
 85  
 86      def test_medium_repo_partial_returns_false(self):
 87          result, reason = should_use_shadow("adnet", {"full_suite": False})
 88          assert result is False
 89          assert "partial" in reason.lower()
 90  
 91      def test_medium_repo_interactive_returns_false(self):
 92          result, reason = should_use_shadow("wallet-core", {"interactive": True})
 93          assert result is False
 94  
 95      # Unknown repos
 96      def test_unknown_repo_returns_false(self):
 97          result, reason = should_use_shadow("mystery-repo", {})
 98          assert result is False
 99          assert "unknown" in reason.lower()
100  
101      # Small changes
102      def test_small_change_with_unit_tests_returns_false(self):
103          result, reason = should_use_shadow("alphavm", {
104              "files_changed": 1,
105              "unit_tests_only": True
106          })
107          assert result is False
108          assert "small change" in reason.lower()
109  
110  
111  class TestEstimatedDuration:
112      def test_fast_duration(self):
113          assert get_estimated_duration("acdc-core") == "<10 minutes"
114  
115      def test_medium_duration(self):
116          assert get_estimated_duration("adnet") == "30-45 minutes"
117  
118      def test_slow_duration(self):
119          assert get_estimated_duration("alphavm") == "60-90 minutes"
120  
121      def test_unknown_duration(self):
122          assert get_estimated_duration("unknown") == "unknown"
123  
124  
125  if __name__ == "__main__":
126      pytest.main([__file__, "-v"])