From 1ec1ceca68a71251a68f5eea273e2458b8cafb4c Mon Sep 17 00:00:00 2001
From: Lukas Holecek <hluk@email.cz>
Date: Aug 29 2018 14:24:42 +0000
Subject: Fetch all results when verbose=true


Fixes #287

---

diff --git a/conf/policies/fedora.yaml b/conf/policies/fedora.yaml
index 698723b..433f0d3 100644
--- a/conf/policies/fedora.yaml
+++ b/conf/policies/fedora.yaml
@@ -72,6 +72,14 @@ blacklist: []
 rules:
   - !PassingTestCaseRule {test_case_name: a_package_test}
 
+--- !Policy
+id: "taskotron_release_critical_tasks_for_stable"
+product_versions:
+  - fedora-28
+decision_context: bodhi_update_push_stable_with_no_rules
+subject_type: koji_build
+rules: []
+
 # No Fedora product has *actually* used an empty policy like this,
 # but we cover it in our tests for completeness.
 --- !Policy
diff --git a/functional-tests/consumers/test_resultsdb.py b/functional-tests/consumers/test_resultsdb.py
index a1b8f98..f85881a 100644
--- a/functional-tests/consumers/test_resultsdb.py
+++ b/functional-tests/consumers/test_resultsdb.py
@@ -320,8 +320,13 @@ def test_invalidate_new_result_with_mocked_cache(
         #'topic_prefix.environment.waiver.new',
     ]
     handler.consume(message)
-    cache_key = 'greenwave.resources:CachedResults|koji_build {} dist.rpmdeplint'.format(nvr)
-    handler.cache.delete.assert_called_once_with(cache_key)
+    cache_key1 = 'greenwave.resources:CachedResults|koji_build {} dist.rpmdeplint'.format(nvr)
+    cache_key2 = 'greenwave.resources:CachedResults|koji_build {} None'.format(nvr)
+    handler.cache.delete.assert_has_calls([
+        mock.call(cache_key1),
+        mock.call(cache_key2)
+    ])
+    assert handler.cache.delete.call_count == 2
 
 
 @mock.patch('greenwave.consumers.resultsdb.fedmsg.config.load_config')
@@ -442,8 +447,13 @@ def test_invalidate_new_result_with_no_preexisting_cache(
         #'topic_prefix.environment.waiver.new',
     ]
     handler.consume(message)
-    cache_key = 'greenwave.resources:CachedResults|koji_build {} dist.rpmdeplint'.format(nvr)
-    handler.cache.delete.assert_called_once_with(cache_key)
+    cache_key1 = 'greenwave.resources:CachedResults|koji_build {} dist.rpmdeplint'.format(nvr)
+    cache_key2 = 'greenwave.resources:CachedResults|koji_build {} None'.format(nvr)
+    handler.cache.delete.assert_has_calls([
+        mock.call(cache_key1),
+        mock.call(cache_key2)
+    ])
+    assert handler.cache.delete.call_count == 2
 
 
 @mock.patch('greenwave.consumers.resultsdb.fedmsg.config.load_config')
diff --git a/functional-tests/test_api_v1.py b/functional-tests/test_api_v1.py
index ea04fde..392b3e3 100644
--- a/functional-tests/test_api_v1.py
+++ b/functional-tests/test_api_v1.py
@@ -36,7 +36,7 @@ def test_inspect_policies(requests_session, greenwave_server):
     assert r.status_code == 200
     body = r.json()
     policies = body['policies']
-    assert len(policies) == 9
+    assert len(policies) == 10
     assert any(p['id'] == 'taskotron_release_critical_tasks' for p in policies)
     assert any(p['decision_context'] == 'bodhi_update_push_stable' for p in policies)
     assert any(p['product_versions'] == ['fedora-26'] for p in policies)
@@ -953,3 +953,38 @@ def test_make_a_decision_about_compose_new_variants_architectures(
     assert r.status_code == 200
     res_data = r.json()
     assert res_data['policies_satisfied']
+
+
+def test_make_a_decision_for_bodhi_with_verbose_flag(
+        requests_session, greenwave_server, testdatabuilder):
+    """
+    Bodhi uses verbose flag to get all results.
+    """
+    nvrs = [
+        testdatabuilder.unique_nvr(),
+        testdatabuilder.unique_nvr(),
+    ]
+
+    results = []
+    for nvr in reversed(nvrs):
+        for testcase_name in TASKTRON_RELEASE_CRITICAL_TASKS:
+            results.append(testdatabuilder.create_result(
+                item=nvr, testcase_name=testcase_name, outcome='PASSED'))
+
+    update = testdatabuilder.create_bodhi_update(build_nvrs=nvrs)
+    data = {
+        'decision_context': 'bodhi_update_push_stable_with_no_rules',
+        'product_version': 'fedora-28',
+        'subject_type': 'bodhi_update',
+        'subject_identifier': update['updateid'],
+        'verbose': True,
+    }
+
+    r = requests_session.post(greenwave_server + 'api/v1.0/decision', json=data)
+    assert r.status_code == 200
+    res_data = r.json()
+
+    assert len(res_data['results']) == len(TASKTRON_RELEASE_CRITICAL_TASKS) * len(nvrs)
+    assert res_data['results'] == list(reversed(results))
+    assert res_data['waivers'] == []
+    assert res_data['satisfied_requirements'] == []
diff --git a/greenwave/api_v1.py b/greenwave/api_v1.py
index e5fafde..95c95e6 100644
--- a/greenwave/api_v1.py
+++ b/greenwave/api_v1.py
@@ -354,6 +354,8 @@ def make_decision():
 
             for policy in build_policies:
                 answers.extend(policy.check(nvr, results_retriever, nvr_waivers))
+    else:
+        build_nvrs = []
 
     res = {
         'policies_satisfied': all(answer.is_satisfied for answer in answers),
@@ -363,8 +365,13 @@ def make_decision():
                                      if not answer.is_satisfied],
     }
     if verbose:
+        # Retrieve test results for all items when verbose output is requested.
+        results = list(results_retriever.retrieve(subject_type, subject_identifier))
+        for nvr in build_nvrs:
+            results += results_retriever.retrieve('koji_build', nvr)
+
         res.update({
-            'results': results_retriever.all_retrieved_results(),
+            'results': results,
             'waivers': waivers,
             'satisfied_requirements':
                 [answer.to_json() for answer in answers if answer.is_satisfied],
diff --git a/greenwave/consumers/resultsdb.py b/greenwave/consumers/resultsdb.py
index fbc2d10..9e0cbc9 100644
--- a/greenwave/consumers/resultsdb.py
+++ b/greenwave/consumers/resultsdb.py
@@ -39,6 +39,11 @@ def _invalidate_results_cache(
     except KeyError:
         log.debug("No cache value found for %r", key)
 
+    # Also invalidate query results without test case name.
+    if testcase:
+        _invalidate_results_cache(
+            cache, subject_type, subject_identifier, testcase=None)
+
 
 class ResultsDBHandler(fedmsg.consumers.FedmsgConsumer):
     """
diff --git a/greenwave/resources.py b/greenwave/resources.py
index ee1534d..9285ab9 100644
--- a/greenwave/resources.py
+++ b/greenwave/resources.py
@@ -52,22 +52,13 @@ class ResultsRetriever(object):
         self.timeout = timeout
         self.verify = verify
         self.url = url
-        self.all_results = []
 
-    def all_retrieved_results(self):
-        """
-        Returns all results retrieved from cache or ResultsDB by this instance.
-        """
-        return sorted(self.all_results, key=lambda x: x['id'], reverse=True)
-
-    def retrieve(self, subject_type, subject_identifier, testcase):
+    def retrieve(self, subject_type, subject_identifier, testcase=None):
         """
         Return generator over results.
         """
         for result in self._retrieve_helper(subject_type, subject_identifier, testcase):
             if result['id'] not in self.ignore_results:
-                if result not in self.all_results:
-                    self.all_results.append(result)
                 yield result
 
     def _retrieve_helper(self, subject_type, subject_identifier, testcase):
@@ -100,11 +91,13 @@ class ResultsRetriever(object):
 
     def _retrieve_page(self, page, subject_type, subject_identifier, testcase):
         params = {
-            'testcases': testcase,
             'limit': 1,
             'page': page,
         }
 
+        if testcase:
+            params['testcases'] = testcase
+
         results = []
         if subject_type == 'bodhi_update':
             params['type'] = subject_type

