From e80586d28b614c6a222e6d7fc05212c4752c13ba Mon Sep 17 00:00:00 2001
From: Lukas Holecek <hluk@email.cz>
Date: Apr 10 2019 10:01:00 +0000
Subject: [PATCH 1/4] Tests: Fix configuration for mocked consumers


Signed-off-by: Lukas Holecek <hluk@email.cz>

---

diff --git a/functional-tests/consumers/handlers.py b/functional-tests/consumers/handlers.py
new file mode 100644
index 0000000..e40b844
--- /dev/null
+++ b/functional-tests/consumers/handlers.py
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+import mock
+
+from greenwave.config import TestingConfig
+
+
+def create_handler(handler_class, topic, greenwave_server, cache_config=None):
+    hub = mock.MagicMock()
+    hub.config = {
+        'environment': 'environment',
+        'topic_prefix': 'topic_prefix',
+    }
+
+    config = TestingConfig()
+    config.GREENWAVE_API_URL = greenwave_server + '/api/v1.0'
+    if cache_config:
+        config.CACHE = cache_config
+
+    handler = handler_class(hub, config=config)
+    assert handler.topic == [topic]
+    return handler
diff --git a/functional-tests/consumers/test_resultsdb.py b/functional-tests/consumers/test_resultsdb.py
index 6146874..2cd7f45 100644
--- a/functional-tests/consumers/test_resultsdb.py
+++ b/functional-tests/consumers/test_resultsdb.py
@@ -4,27 +4,17 @@ import json
 import mock
 import pprint
 
-from greenwave.config import TestingConfig
 from greenwave.consumers import resultsdb
 
+import handlers
 
-def create_resultdb_handler(cache_config=None):
-    hub = mock.MagicMock()
-    hub.config = {
-        'environment': 'environment',
-        'topic_prefix': 'topic_prefix',
-    }
-
-    class Config(TestingConfig):
-        CACHE = cache_config or TestingConfig.CACHE
 
-    handler = resultsdb.ResultsDBHandler(hub, Config())
-    assert handler.topic == [
+def create_resultdb_handler(greenwave_server, cache_config=None):
+    return handlers.create_handler(
+        resultsdb.ResultsDBHandler,
         'topic_prefix.environment.taskotron.result.new',
-        # Not ready to handle waiverdb yet.
-        #'topic_prefix.environment.waiver.new',
-    ]
-    return handler
+        greenwave_server,
+        cache_config)
 
 
 @mock.patch('greenwave.consumers.resultsdb.fedmsg.publish')
@@ -51,7 +41,7 @@ def test_consume_new_result(
             }
         }
     }
-    handler = create_resultdb_handler()
+    handler = create_resultdb_handler(greenwave_server)
     handler.consume(message)
 
     assert len(mock_fedmsg.mock_calls) == 2
@@ -193,7 +183,7 @@ def test_consume_unchanged_result(
             }
         }
     }
-    handler = create_resultdb_handler()
+    handler = create_resultdb_handler(greenwave_server)
     handler.consume(message)
 
     assert len(mock_fedmsg.mock_calls) == 0
@@ -223,7 +213,7 @@ def test_invalidate_new_result_with_mocked_cache(
             }
         }
     }
-    handler = create_resultdb_handler()
+    handler = create_resultdb_handler(greenwave_server)
     handler.cache = mock.MagicMock()
     handler.consume(message)
     cache_key1 = 'greenwave.resources:CachedResults|koji_build {} dist.rpmdeplint'.format(nvr)
@@ -287,7 +277,7 @@ def test_invalidate_new_result_with_real_cache(
             }
         }
     }
-    handler = create_resultdb_handler(cache_config)
+    handler = create_resultdb_handler(greenwave_server, cache_config)
     handler.consume(message)
 
     # At this point, the invalidator should have invalidated the cache.  If we
@@ -326,7 +316,7 @@ def test_invalidate_new_result_with_no_preexisting_cache(
             }
         }
     }
-    handler = create_resultdb_handler()
+    handler = create_resultdb_handler(greenwave_server)
     handler.cache.delete = mock.MagicMock()
     handler.consume(message)
     cache_key1 = 'greenwave.resources:CachedResults|koji_build {} dist.rpmdeplint'.format(nvr)
@@ -363,7 +353,7 @@ def test_consume_compose_id_result(
             }
         }
     }
-    handler = create_resultdb_handler()
+    handler = create_resultdb_handler(greenwave_server)
     handler.consume(message)
 
     # get old decision
@@ -436,7 +426,7 @@ def test_consume_legacy_result(
             }
         }
     }
-    handler = create_resultdb_handler()
+    handler = create_resultdb_handler(greenwave_server)
     handler.consume(message)
 
     # get old decision
@@ -567,7 +557,7 @@ def test_no_message_for_nonapplicable_policies(
             }
         }
     }
-    handler = create_resultdb_handler()
+    handler = create_resultdb_handler(greenwave_server)
     handler.consume(message)
     # No message should be published as the decision is unchanged since we
     # are still missing the required tests.
@@ -691,7 +681,7 @@ def test_consume_new_result_container_image(
             }
         }
     }
-    handler = create_resultdb_handler()
+    handler = create_resultdb_handler(greenwave_server)
     handler.consume(message)
 
     # get old decision
diff --git a/functional-tests/consumers/test_waiverdb.py b/functional-tests/consumers/test_waiverdb.py
index 49b3a0e..3382c25 100644
--- a/functional-tests/consumers/test_waiverdb.py
+++ b/functional-tests/consumers/test_waiverdb.py
@@ -5,6 +5,8 @@ import pytest
 
 from greenwave.consumers import waiverdb
 
+import handlers
+
 
 TASKTRON_RELEASE_CRITICAL_TASKS = [
     'dist.abicheck',
@@ -13,6 +15,13 @@ TASKTRON_RELEASE_CRITICAL_TASKS = [
 ]
 
 
+def create_waiverdb_handler(greenwave_server):
+    return handlers.create_handler(
+        waiverdb.WaiverDBHandler,
+        'topic_prefix.environment.waiver.new',
+        greenwave_server)
+
+
 @pytest.mark.parametrize('subject_type', ('koji_build', 'brew-build'))
 @mock.patch('greenwave.consumers.waiverdb.fedmsg.publish')
 def test_consume_new_waiver(
@@ -50,10 +59,7 @@ def test_consume_new_waiver(
             "msg": waiver,
         }
     }
-    hub = mock.MagicMock()
-    hub.config = {'environment': 'environment', 'topic_prefix': 'topic_prefix'}
-    handler = waiverdb.WaiverDBHandler(hub)
-    assert handler.topic == ['topic_prefix.environment.waiver.new']
+    handler = create_waiverdb_handler(greenwave_server)
     handler.consume(message)
 
     assert len(mock_fedmsg.mock_calls) == 1
diff --git a/greenwave/consumers/resultsdb.py b/greenwave/consumers/resultsdb.py
index 0e2afaf..5503d87 100644
--- a/greenwave/consumers/resultsdb.py
+++ b/greenwave/consumers/resultsdb.py
@@ -12,7 +12,6 @@ to the message bus about the newly satisfied/unsatisfied policy.
 import logging
 import re
 
-from flask import current_app
 import fedmsg.consumers
 import requests
 
@@ -63,7 +62,7 @@ def _guess_product_version(toparse, koji_build=False):
     return None
 
 
-def _subject_product_version(subject_identifier, subject_type):
+def _subject_product_version(subject_identifier, subject_type, koji_base_url=None):
     if subject_type == 'koji_build':
         try:
             short_prod_version = subject_identifier.split('.')[-1]
@@ -77,7 +76,6 @@ def _subject_product_version(subject_identifier, subject_type):
     if subject_type == "redhat-module":
         return "rhel-8"
 
-    koji_base_url = current_app.config['KOJI_BASE_URL']
     if koji_base_url:
         proxy = xmlrpc.client.ServerProxy(koji_base_url)
         try:
@@ -154,8 +152,7 @@ class ResultsDBHandler(fedmsg.consumers.FedmsgConsumer):
 
     config_key = 'resultsdb_handler'
 
-    def __init__(self, hub, config_obj=None, *args, **kwargs):
-        #pylint: disable=keyword-arg-before-vararg
+    def __init__(self, hub, *args, **kwargs):
         """
         Initialize the ResultsDBHandler, subscribing it to the appropriate topics.
 
@@ -170,9 +167,13 @@ class ResultsDBHandler(fedmsg.consumers.FedmsgConsumer):
         self.topic = ['.'.join([prefix, env, suffix])]
         self.fedmsg_config = fedmsg.config.load_config()
 
+        config = kwargs.pop('config', None)
+
         super(ResultsDBHandler, self).__init__(hub, *args, **kwargs)
 
-        self.flask_app = greenwave.app_factory.create_app(config_obj)
+        self.flask_app = greenwave.app_factory.create_app(config)
+        self.greenwave_api_url = self.flask_app.config['GREENWAVE_API_URL']
+        self.koji_base_url = self.flask_app.config['KOJI_BASE_URL']
         self.cache = self.flask_app.cache
 
         log.info('Greenwave resultsdb handler listening on: %s', self.topic)
@@ -262,7 +263,8 @@ class ResultsDBHandler(fedmsg.consumers.FedmsgConsumer):
             result_id (int): A result ID to ignore for comparison.
             testcase (munch.Munch): The name of a testcase to consider.
         """
-        product_version = _subject_product_version(subject_identifier, subject_type)
+        product_version = _subject_product_version(
+            subject_identifier, subject_type, self.koji_base_url)
         policies = self.flask_app.config['policies']
         contexts_product_versions = applicable_decision_context_product_version_pairs(
             policies,
@@ -274,7 +276,7 @@ class ResultsDBHandler(fedmsg.consumers.FedmsgConsumer):
         log.info('Getting greenwave info')
 
         for decision_context, product_version in sorted(contexts_product_versions):
-            greenwave_url = current_app.config['GREENWAVE_API_URL'] + '/decision'
+            greenwave_url = self.greenwave_api_url + '/decision'
 
             data = {
                 'decision_context': decision_context,
diff --git a/greenwave/consumers/waiverdb.py b/greenwave/consumers/waiverdb.py
index 1fa1e57..282e5a2 100644
--- a/greenwave/consumers/waiverdb.py
+++ b/greenwave/consumers/waiverdb.py
@@ -12,7 +12,6 @@ to the message bus about the newly satisfied/unsatisfied policy.
 import logging
 import json
 
-from flask import current_app
 import fedmsg.consumers
 import requests
 
@@ -59,9 +58,12 @@ class WaiverDBHandler(fedmsg.consumers.FedmsgConsumer):
         self.topic = ['.'.join([prefix, env, suffix])]
         self.fedmsg_config = fedmsg.config.load_config()
 
+        config = kwargs.pop('config', None)
+
         super(WaiverDBHandler, self).__init__(hub, *args, **kwargs)
 
-        self.flask_app = greenwave.app_factory.create_app()
+        self.flask_app = greenwave.app_factory.create_app(config)
+        self.greenwave_api_url = self.flask_app.config['GREENWAVE_API_URL']
         log.info('Greenwave waiverdb handler listening on: %s', self.topic)
 
     def consume(self, message):
@@ -103,7 +105,7 @@ class WaiverDBHandler(fedmsg.consumers.FedmsgConsumer):
                 'subject_identifier': subject_identifier,
             }
             response = requests_session.post(
-                current_app.config['GREENWAVE_API_URL'] + '/decision',
+                self.greenwave_api_url + '/decision',
                 headers={'Content-Type': 'application/json'},
                 data=json.dumps(data))
 
@@ -118,7 +120,7 @@ class WaiverDBHandler(fedmsg.consumers.FedmsgConsumer):
                 'ignore_waiver': [waiver_id],
             })
             response = requests_session.post(
-                current_app.config['GREENWAVE_API_URL'] + '/decision',
+                self.greenwave_api_url + '/decision',
                 headers={'Content-Type': 'application/json'},
                 data=json.dumps(data))
 

From 7a565c616e8150a03be901a2dc8f79b646a79a32 Mon Sep 17 00:00:00 2001
From: Lukas Holecek <hluk@email.cz>
Date: Apr 10 2019 10:01:00 +0000
Subject: [PATCH 2/4] Tests: Allow to run functional tests without cleaning ResultsDB


Uses current time (seconds since epoch) as unique counter for generating
NVRs for new ResultsDB items. This allows rerun some tests without
needing to clean ResultsDB.

Signed-off-by: Lukas Holecek <hluk@email.cz>

---

diff --git a/functional-tests/conftest.py b/functional-tests/conftest.py
index ded6fd1..6c35680 100644
--- a/functional-tests/conftest.py
+++ b/functional-tests/conftest.py
@@ -235,7 +235,7 @@ class TestDataBuilder(object):
         self.resultsdb_url = resultsdb_url
         self.waiverdb_url = waiverdb_url
         self.distgit_url = distgit_url
-        self._counter = itertools.count(1)
+        self._counter = itertools.count(time.time())
 
     def unique_nvr(self, name='glibc', product_version='el7'):
         return '{}-1.0-{}.{}'.format(name, next(self._counter), product_version)
diff --git a/functional-tests/consumers/test_resultsdb.py b/functional-tests/consumers/test_resultsdb.py
index 2cd7f45..16fbbb6 100644
--- a/functional-tests/consumers/test_resultsdb.py
+++ b/functional-tests/consumers/test_resultsdb.py
@@ -1,8 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0+
 
+import hashlib
 import json
 import mock
 import pprint
+import time
 
 from greenwave.consumers import resultsdb
 
@@ -568,7 +570,9 @@ def test_no_message_for_nonapplicable_policies(
 def test_consume_new_result_container_image(
         mock_fedmsg, requests_session, greenwave_server,
         testdatabuilder):
-    nvr = 'fedora@sha256:017eb7de7927da933a04a6c1ff59da0c41dcea194aaa6b5dd7148df286b92433'
+    unique_id = str(time.time()).encode('utf-8')
+    sha256 = hashlib.sha256(unique_id).hexdigest()
+    nvr = 'fedora@sha256:{}'.format(sha256)
     result = testdatabuilder.create_result(item=nvr,
                                            testcase_name='baseos-qe.baseos-ci.tier1.functional',
                                            outcome='PASSED', _type='container-image')
@@ -643,8 +647,7 @@ def test_consume_new_result_container_image(
                         "fedora"
                     ],
                     "item": [
-                        ("fedora@sha256:017eb7de7927da933a04a6c1ff59da0c"
-                         "41dcea194aaa6b5dd7148df286b92433")
+                        "fedora@sha256:{}".format(sha256)
                     ],
                     "system_provider": [
                         "openstack"
@@ -653,7 +656,7 @@ def test_consume_new_result_container_image(
                         "https://example.com"
                     ],
                     "digest": [
-                        "sha256:017eb7de7927da933a04a6c1ff59da0c41dcea194aaa6b5dd7148df286b92433"
+                        "sha256:{}".format(sha256)
                     ],
                     "xunit": [
                         "https://somewhere.com/job/ci-openstack/4794/artifacts/results.xml"

From a7024923fa2f20cb2bc65fe4001553769b3044dd Mon Sep 17 00:00:00 2001
From: Lukas Holecek <hluk@email.cz>
Date: Apr 10 2019 10:01:00 +0000
Subject: [PATCH 3/4] Tests: Fix testing version endpoint response


Signed-off-by: Lukas Holecek <hluk@email.cz>

---

diff --git a/functional-tests/test_api_v1.py b/functional-tests/test_api_v1.py
index 950fc26..a90e0ce 100644
--- a/functional-tests/test_api_v1.py
+++ b/functional-tests/test_api_v1.py
@@ -77,7 +77,7 @@ def test_about_endpoint_jsonp(requests_session, greenwave_server):
 def test_version_redirect(requests_session, greenwave_server):
     r = requests_session.get(greenwave_server + 'api/v1.0/version')
     assert r.status_code == 200
-    assert '"version": "%s"' % __version__ in r.text
+    assert __version__, r.json()['version']
     assert r.url.endswith('about')
 
 

From bada7d2c78e607217fc79461a10c0d9d92e59a2c Mon Sep 17 00:00:00 2001
From: Lukas Holecek <hluk@email.cz>
Date: Apr 10 2019 10:01:00 +0000
Subject: [PATCH 4/4] Tests: Try to use correct cache when GREENWAVE_TEST_URL is set


Signed-off-by: Lukas Holecek <hluk@email.cz>

---

diff --git a/functional-tests/conftest.py b/functional-tests/conftest.py
index 6c35680..59db49d 100644
--- a/functional-tests/conftest.py
+++ b/functional-tests/conftest.py
@@ -186,6 +186,17 @@ def distgit_server(tmpdir_factory):
 @pytest.yield_fixture(scope='session')
 def cache_config(tmpdir_factory):
     cache_file = tmpdir_factory.mktemp('greenwave').join('cache.dbm')
+    if 'GREENWAVE_TEST_URL' in os.environ:
+        # This should point to the same cache as the Greenwave server used by tests.
+        return {
+            'backend': "dogpile.cache.memcached",
+            'expiration_time': 300,
+            'arguments': {
+                'url': 'memcached:11211',
+                'distributed_lock': True
+            }
+        }
+
     return {
         'backend': 'dogpile.cache.dbm',
         'expiration_time': 300,

