Navegador

navegador / tests / test_chef_enricher.py
Source Blame History 210 lines
b45288f… lmata 1 """Tests for navegador.enrichment.chef — ChefEnricher."""
b45288f… lmata 2
b45288f… lmata 3 from unittest.mock import MagicMock
b45288f… lmata 4
b45288f… lmata 5 from navegador.enrichment.chef import ChefEnricher
b45288f… lmata 6
b45288f… lmata 7
b45288f… lmata 8 def _make_store(query_results=None):
b45288f… lmata 9 """Create a mock GraphStore.
b45288f… lmata 10
b45288f… lmata 11 *query_results* maps Cypher query substrings to result_set lists.
b45288f… lmata 12 Unmatched queries return an empty result_set.
b45288f… lmata 13 """
b45288f… lmata 14 store = MagicMock()
b45288f… lmata 15 mapping = query_results or {}
b45288f… lmata 16
b45288f… lmata 17 def _side_effect(query, params=None):
b45288f… lmata 18 result = MagicMock()
b45288f… lmata 19 for substr, rows in mapping.items():
b45288f… lmata 20 if substr in query:
b45288f… lmata 21 result.result_set = rows
b45288f… lmata 22 return result
b45288f… lmata 23 result.result_set = []
b45288f… lmata 24 return result
b45288f… lmata 25
b45288f… lmata 26 store.query.side_effect = _side_effect
b45288f… lmata 27 return store
b45288f… lmata 28
b45288f… lmata 29
b45288f… lmata 30 class TestIdentity:
b45288f… lmata 31 """Framework identity properties."""
b45288f… lmata 32
b45288f… lmata 33 def test_framework_name(self):
b45288f… lmata 34 store = _make_store()
b45288f… lmata 35 enricher = ChefEnricher(store)
b45288f… lmata 36 assert enricher.framework_name == "chef"
b45288f… lmata 37
b45288f… lmata 38 def test_detection_files(self):
b45288f… lmata 39 store = _make_store()
b45288f… lmata 40 enricher = ChefEnricher(store)
b45288f… lmata 41 assert "metadata.rb" in enricher.detection_files
b45288f… lmata 42 assert "Berksfile" in enricher.detection_files
b45288f… lmata 43
b45288f… lmata 44 def test_detection_patterns(self):
b45288f… lmata 45 store = _make_store()
b45288f… lmata 46 enricher = ChefEnricher(store)
b45288f… lmata 47 assert "chef" in enricher.detection_patterns
b45288f… lmata 48
b45288f… lmata 49
b45288f… lmata 50 class TestDetect:
b45288f… lmata 51 """Tests for detect() — framework presence detection."""
b45288f… lmata 52
b45288f… lmata 53 def test_detect_true_when_metadata_rb_exists(self):
b45288f… lmata 54 store = _make_store(
b45288f… lmata 55 {
b45288f… lmata 56 "f.name = $name": [[1]],
b45288f… lmata 57 }
b45288f… lmata 58 )
b45288f… lmata 59 enricher = ChefEnricher(store)
b45288f… lmata 60 assert enricher.detect() is True
b45288f… lmata 61
b45288f… lmata 62 def test_detect_false_when_no_markers(self):
b45288f… lmata 63 store = _make_store()
b45288f… lmata 64 enricher = ChefEnricher(store)
b45288f… lmata 65 assert enricher.detect() is False
b45288f… lmata 66
b45288f… lmata 67 def test_detect_true_via_import_pattern(self):
b45288f… lmata 68 store = _make_store(
b45288f… lmata 69 {
b45288f… lmata 70 "n.name = $name OR n.module = $name": [[1]],
b45288f… lmata 71 }
b45288f… lmata 72 )
b45288f… lmata 73 enricher = ChefEnricher(store)
b45288f… lmata 74 assert enricher.detect() is True
b45288f… lmata 75
b45288f… lmata 76
b45288f… lmata 77 class TestEnrichRecipes:
b45288f… lmata 78 """Tests for enrich() promoting recipe files."""
b45288f… lmata 79
b45288f… lmata 80 def test_promotes_recipe_files(self):
b45288f… lmata 81 store = _make_store(
b45288f… lmata 82 {
b45288f… lmata 83 "n.file_path CONTAINS $pattern": [
b45288f… lmata 84 ["default.rb", "cookbooks/web/recipes/default.rb"],
b45288f… lmata 85 ["install.rb", "cookbooks/web/recipes/install.rb"],
b45288f… lmata 86 ],
b45288f… lmata 87 }
b45288f… lmata 88 )
b45288f… lmata 89 enricher = ChefEnricher(store)
b45288f… lmata 90 result = enricher.enrich()
b45288f… lmata 91
b45288f… lmata 92 assert result.patterns_found["recipes"] == 2
b45288f… lmata 93 assert result.promoted >= 2
b45288f… lmata 94
b45288f… lmata 95 # Verify _promote_node was called via store.query SET
b45288f… lmata 96 set_calls = [c for c in store.query.call_args_list if "SET n.semantic_type" in str(c)]
b45288f… lmata 97 assert len(set_calls) >= 2
b45288f… lmata 98
b45288f… lmata 99
b45288f… lmata 100 class TestEnrichResources:
b45288f… lmata 101 """Tests for enrich() promoting Chef resource calls."""
b45288f… lmata 102
b45288f… lmata 103 def test_promotes_resource_functions(self):
b45288f… lmata 104 # _enrich_resources queries twice (recipes/ and libraries/),
b45288f… lmata 105 # so we use a custom side_effect to return data only once.
b45288f… lmata 106 call_count = {"resource": 0}
b45288f… lmata 107 original_results = [
b45288f… lmata 108 ["package", "cookbooks/web/recipes/default.rb"],
b45288f… lmata 109 ["template", "cookbooks/web/recipes/default.rb"],
b45288f… lmata 110 ["not_a_resource", "cookbooks/web/recipes/default.rb"],
b45288f… lmata 111 ]
b45288f… lmata 112
b45288f… lmata 113 def _side_effect(query, params=None):
b45288f… lmata 114 result = MagicMock()
b45288f… lmata 115 if "(n:Function OR n:Method)" in query:
b45288f… lmata 116 call_count["resource"] += 1
b45288f… lmata 117 if call_count["resource"] == 1:
b45288f… lmata 118 result.result_set = original_results
b45288f… lmata 119 else:
b45288f… lmata 120 result.result_set = []
b45288f… lmata 121 else:
b45288f… lmata 122 result.result_set = []
b45288f… lmata 123 return result
b45288f… lmata 124
b45288f… lmata 125 store = MagicMock()
b45288f… lmata 126 store.query.side_effect = _side_effect
b45288f… lmata 127 enricher = ChefEnricher(store)
b45288f… lmata 128 result = enricher.enrich()
b45288f… lmata 129
b45288f… lmata 130 # "package" and "template" match, "not_a_resource" does not
b45288f… lmata 131 assert result.patterns_found["resources"] == 2
b45288f… lmata 132
b45288f… lmata 133 def test_skips_non_resource_functions(self):
b45288f… lmata 134 store = _make_store(
b45288f… lmata 135 {
b45288f… lmata 136 "(n:Function OR n:Method)": [
b45288f… lmata 137 ["my_helper", "cookbooks/web/libraries/helpers.rb"],
b45288f… lmata 138 ],
b45288f… lmata 139 }
b45288f… lmata 140 )
b45288f… lmata 141 enricher = ChefEnricher(store)
b45288f… lmata 142 result = enricher.enrich()
b45288f… lmata 143
b45288f… lmata 144 assert result.patterns_found["resources"] == 0
b45288f… lmata 145
b45288f… lmata 146
b45288f… lmata 147 class TestEnrichIncludeRecipe:
b45288f… lmata 148 """Tests for enrich() handling include_recipe edges."""
b45288f… lmata 149
b45288f… lmata 150 def test_creates_depends_on_edge(self):
b45288f… lmata 151 # Strategy 1: follow CALLS edges from include_recipe nodes
b45288f… lmata 152 def _query_side_effect(query, params=None):
b45288f… lmata 153 result = MagicMock()
b45288f… lmata 154 if "[:CALLS]" in query and "n.name = $name" in query:
b45288f… lmata 155 result.result_set = [
b45288f… lmata 156 [
b45288f… lmata 157 "cookbooks/web/recipes/default.rb",
b45288f… lmata 158 "database::install",
b45288f… lmata 159 ],
b45288f… lmata 160 ]
b45288f… lmata 161 elif "f.file_path CONTAINS $recipes" in query:
b45288f… lmata 162 result.result_set = [["install.rb"]]
b45288f… lmata 163 elif "f.file_path = $path" in query:
b45288f… lmata 164 result.result_set = [["default.rb"]]
b45288f… lmata 165 elif "MERGE" in query:
b45288f… lmata 166 result.result_set = []
b45288f… lmata 167 else:
b45288f… lmata 168 result.result_set = []
b45288f… lmata 169 return result
b45288f… lmata 170
b45288f… lmata 171 store = MagicMock()
b45288f… lmata 172 store.query.side_effect = _query_side_effect
b45288f… lmata 173 enricher = ChefEnricher(store)
b45288f… lmata 174 result = enricher.enrich()
b45288f… lmata 175
b45288f… lmata 176 assert result.edges_added >= 1
b45288f… lmata 177 assert result.patterns_found["include_recipe"] >= 1
b45288f… lmata 178
b45288f… lmata 179 # Verify MERGE query was issued for the DEPENDS_ON edge
b45288f… lmata 180 merge_calls = [
b45288f… lmata 181 c for c in store.query.call_args_list if "MERGE" in str(c) and "DEPENDS_ON" in str(c)
b45288f… lmata 182 ]
b45288f… lmata 183 assert len(merge_calls) >= 1
b45288f… lmata 184
b45288f… lmata 185 def test_no_edges_when_no_include_recipe(self):
b45288f… lmata 186 store = _make_store()
b45288f… lmata 187 enricher = ChefEnricher(store)
b45288f… lmata 188 result = enricher.enrich()
b45288f… lmata 189
b45288f… lmata 190 assert result.edges_added == 0
b45288f… lmata 191 assert result.patterns_found["include_recipe"] == 0
b45288f… lmata 192
b45288f… lmata 193
b45288f… lmata 194 class TestEnrichCookbooks:
b45288f… lmata 195 """Tests for enrich() promoting cookbook metadata files."""
b45288f… lmata 196
b45288f… lmata 197 def test_promotes_metadata_rb(self):
b45288f… lmata 198 store = _make_store(
b45288f… lmata 199 {
b45288f… lmata 200 "n.name = $name": [
b45288f… lmata 201 ["metadata.rb", "cookbooks/web/metadata.rb"],
b45288f… lmata 202 ],
b45288f… lmata 203 }
b45288f… lmata 204 )
b45288f… lmata 205 enricher = ChefEnricher(store)
b45288f… lmata 206 result = enricher.enrich()
b45288f… lmata 207
b45288f… lmata 208 assert result.patterns_found["cookbooks"] == 1
b45288f… lmata 209 set_calls = [c for c in store.query.call_args_list if "chef_cookbook" in str(c)]
b45288f… lmata 210 assert len(set_calls) >= 1

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button