Skip to content

Commit

Permalink
Mock datetime in DAO correctly
Browse files Browse the repository at this point in the history
This patch fixes issues we have with mocked now in DAO tests.
The utcnow method is extracted into dci.common.time module in get_utc_now method.
This method is mocked when needed.

We use utcnow instead of now in the DAO.

Change-Id: I4da86c351db4f0235ccc476b990f832771bccb29
  • Loading branch information
rh-gvincent committed Jul 19, 2024
1 parent 1ded6a5 commit 01fe1a0
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 34 deletions.
10 changes: 6 additions & 4 deletions dci/analytics/access_data_layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@
# License for the specific language governing permissions and limitations
# under the License.

from datetime import datetime as dt, timedelta as td
from datetime import timedelta
import sqlalchemy.orm as sa_orm

from dci.db import models2
from dci.common.time import get_utc_now


def get_jobs(session, offset, limit, unit, amount, status=None):
delta = {unit: amount}

query = session.query(models2.Job)
if status:
query = query.filter(models2.Job.status == status)
query = query.filter(models2.Job.state != "archived")
query = query.filter(models2.Job.updated_at >= (dt.now() - td(**delta)))
query = query.filter(models2.Job.updated_at >= (get_utc_now() - timedelta(**delta)))
query = query.order_by(models2.Job.updated_at.asc())
query = query.from_self()

Expand Down Expand Up @@ -58,7 +58,9 @@ def get_components(session, offset, limit, unit, amount):

query = session.query(models2.Component)
query = query.filter(models2.Component.state != "archived")
query = query.filter(models2.Component.created_at >= (dt.now() - td(**delta)))
query = query.filter(
models2.Component.created_at >= (get_utc_now() - timedelta(**delta))
)
query = query.order_by(models2.Component.created_at.asc())

query = query.options(sa_orm.selectinload("jobs"))
Expand Down
4 changes: 2 additions & 2 deletions dci/api/v1/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
# License for the specific language governing permissions and limitations
# under the License.

import datetime
import io
import os

Expand All @@ -37,6 +36,7 @@
check_and_get_args,
)
from dci.common import utils
from dci.common.time import get_utc_now
from dci.db import models2
from dci.db import declarative
from dci.db import migration_components
Expand Down Expand Up @@ -351,7 +351,7 @@ def upload_component_file(user, c_id):
"id": file_id,
"component_id": c_id,
"name": file_id,
"created_at": datetime.datetime.utcnow().isoformat(),
"created_at": get_utc_now().isoformat(),
"etag": s_file.get("etag", s_file.get("ETag")),
"md5": s_file.get("etag", s_file.get("ChecksumSHA256")),
"mime": s_file.get("content-type", s_file.get("ContentType")),
Expand Down
7 changes: 1 addition & 6 deletions dci/api/v1/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@
from sqlalchemy import sql
import sqlalchemy.orm as sa_orm

from datetime import datetime

from dci.api.v1 import api
from dci.api.v1 import base
from dci.api.v1 import components
from dci.api.v1 import utils as v1_utils
from dci.api.v1 import jobs_events
from dci import decorators
from dci.common import exceptions as dci_exc
from dci.common.time import get_utc_now
from dci.common.schemas import (
check_json_is_valid,
clean_json_with_schema,
Expand All @@ -52,10 +51,6 @@
logger = logging.getLogger(__name__)


def get_utc_now():
return datetime.utcnow()


@api.route("/jobs", methods=["POST"])
@decorators.login_required
def create_jobs(user):
Expand Down
4 changes: 2 additions & 2 deletions dci/api/v1/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
# License for the specific language governing permissions and limitations
# under the License.

import datetime
from OpenSSL import crypto

from dci.common import utils
from dci.common.time import get_utc_now
from dci.db import models2


Expand Down Expand Up @@ -109,7 +109,7 @@ def common_values_dict():
redoing this code everytime, this method ensures it is done only at
one place.
"""
now = datetime.datetime.utcnow().isoformat()
now = get_utc_now().isoformat()
etag = utils.gen_etag()
values = {
"id": utils.gen_uuid(),
Expand Down
6 changes: 5 additions & 1 deletion dci/common/time.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import datetime


def get_utc_now():
return datetime.datetime.utcnow()


def get_job_duration(job):
job_duration = datetime.datetime.utcnow() - job.created_at
job_duration = get_utc_now() - job.created_at
return job_duration.total_seconds()
27 changes: 13 additions & 14 deletions tests/analytics/test_access_data_layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,25 +59,24 @@ def test_get_jobs(

jobs = a_d_l.get_jobs(session, 0, 10, "hours", 3)
assert len(jobs) == 4
assert "jobstates" in jobs[0]
assert "files" in jobs[0]["jobstates"][0]
assert "components" in jobs[0]
assert "files" in jobs[0]
assert "pipeline" in jobs[0]
assert pipeline_id == jobs[0]["pipeline"]["id"]
assert "product" in jobs[0]
job1 = [j for j in jobs if len(j["jobstates"]) > 0][0]
assert "jobstates" in job1
assert "files" in job1["jobstates"][0]
assert "components" in job1
assert "files" in job1
assert "pipeline" in job1
assert pipeline_id == job1["pipeline"]["id"]
assert "product" in job1

jobs = a_d_l.get_jobs(session, 0, 10, "hours", 1)
assert len(jobs) == 2


@mock.patch("dci.api.v1.components.v1_utils.datetime")
def test_get_components(m_datetime, session, admin, topic_id):
m_utcnow = mock.MagicMock()
m_datetime.datetime.utcnow.return_value = m_utcnow
m_utcnow.isoformat.return_value = (
datetime.datetime.utcnow() - datetime.timedelta(hours=2)
).isoformat()
@mock.patch("dci.api.v1.utils.get_utc_now")
def test_get_components(m_get_utc_now, session, admin, topic_id):
m_get_utc_now.return_value = datetime.datetime.utcnow() - datetime.timedelta(
hours=2
)
for i in range(5):
admin.post(
"/api/v1/components",
Expand Down
10 changes: 5 additions & 5 deletions tests/api/v1/test_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# under the License.

from __future__ import unicode_literals
from datetime import datetime as dt
from datetime import datetime
import mock
import pytest
import uuid
Expand Down Expand Up @@ -366,7 +366,7 @@ def test_create_component_with_tags(admin, topic_id):


def test_create_component_with_release_at(admin, topic_id):
released_at = dt.utcnow().isoformat()
released_at = datetime.utcnow().isoformat()
data = {
"name": "pname",
"type": "first_type",
Expand Down Expand Up @@ -431,7 +431,7 @@ def test_get_all_components_updated_after(admin, topic_id):
assert len(db_all_cs["components"]) == 5
component_2 = db_all_cs["components"][2]

updated_after = dt.utcnow().isoformat()
updated_after = datetime.utcnow().isoformat()
db_all_cs = admin.get(
"/api/v1/topics/%s/components?updated_after=%s&sort=created_at"
% (topic_id, updated_after)
Expand Down Expand Up @@ -730,7 +730,7 @@ def test_update_component(admin, topic_id):


def test_update_component_v2(admin, topic_id):
released_at = dt.utcnow().isoformat()
released_at = datetime.utcnow().isoformat()
data = {
"name": "RHEL-8.6.0-20211205.3",
"version": "8.6.0-20211205.3",
Expand All @@ -746,7 +746,7 @@ def test_update_component_v2(admin, topic_id):
assert component["released_at"] == released_at
assert component["state"] == "inactive"

new_released_at = dt.utcnow().isoformat()
new_released_at = datetime.utcnow().isoformat()
component["name"] = "RHEL-8.6.0-20211205.4"
component["version"] = "8.6.0-20211205.4"
component["url"] = "http://example.org/RHEL-8.6.0-20211205.4"
Expand Down

0 comments on commit 01fe1a0

Please sign in to comment.