"""Test cases for procedures defined in commands.py""" import unittest from dataclasses import dataclass from datetime import datetime from typing import Callable from unittest import mock from gn3.commands import compose_gemma_cmd from gn3.commands import compose_rqtl_cmd from gn3.commands import queue_cmd from gn3.commands import run_cmd from gn3.exceptions import RedisConnectionError @dataclass class MockRedis: """Mock Redis connection""" ping: Callable hset: mock.MagicMock rpush: mock.MagicMock class TestCommands(unittest.TestCase): """Test cases for commands.py""" def test_compose_gemma_cmd_no_extra_args(self): """Test that the gemma cmd is composed correctly""" self.assertEqual( compose_gemma_cmd(gemma_wrapper_cmd="gemma-wrapper", gemma_kwargs={ "g": "/tmp/genofile.txt", "p": "/tmp/gf13Ad0tRX/phenofile.txt" }, gemma_args=["-gk"]), ("gemma-wrapper --json -- " "-g /tmp/genofile.txt " "-p /tmp/gf13Ad0tRX/phenofile.txt" " -gk")) def test_compose_gemma_cmd_extra_args(self): """Test that the gemma cmd is composed correctly""" self.assertEqual( compose_gemma_cmd(gemma_wrapper_cmd="gemma-wrapper", gemma_wrapper_kwargs={ "loco": "1,2,3,4" }, gemma_kwargs={ "g": "/tmp/genofile.txt", "p": "/tmp/gf13Ad0tRX/phenofile.txt" }, gemma_args=["-gk"]), ("gemma-wrapper --json --loco 1,2,3,4 -- " "-g /tmp/genofile.txt " "-p /tmp/gf13Ad0tRX/phenofile.txt" " -gk")) def test_compose_rqtl_cmd(self): """Test that the R/qtl cmd is composed correctly""" self.assertEqual( compose_rqtl_cmd(rqtl_wrapper_cmd="rqtl-wrapper", rqtl_wrapper_kwargs={ "g": "the_genofile", "p": "the_phenofile", "model": "np", "method": "ehk", "nperm": 2000, "scale": "Mb", "control": "rs234567" }, rqtl_wrapper_bool_kwargs=[ "addcovar" ]), ("rqtl-wrapper " "--g the_genofile --p the_phenofile " "--model np --method ehk " "--nperm 2000 --scale Mb " "--control rs234567 " "--addcovar") ) def test_queue_cmd_exception_raised_when_redis_is_down(self): """Test that the correct error is raised when Redis is unavailable""" self.assertRaises(RedisConnectionError, queue_cmd, cmd="ls", job_queue="GN2::job-queue", conn=MockRedis(ping=lambda: False, hset=mock.MagicMock(), rpush=mock.MagicMock())) @mock.patch("gn3.commands.datetime") @mock.patch("gn3.commands.uuid4") def test_queue_cmd_correct_calls_to_redis(self, mock_uuid4, mock_datetime): """Test that the cmd is queued properly""" mock_uuid4.return_value = 1234 mock_datetime.now.return_value = datetime.fromisoformat('2021-02-12 ' '17:32:24.' '859097') mock_redis_conn = MockRedis(ping=lambda: True, hset=mock.MagicMock(), rpush=mock.MagicMock()) actual_unique_id = "cmd::2021-02-1217-3224-3224-1234" self.assertEqual(queue_cmd(cmd="ls", conn=mock_redis_conn, job_queue="GN2::job-queue"), actual_unique_id) mock_redis_conn.hset.assert_has_calls( [mock.call(name=actual_unique_id, key="cmd", value="ls"), mock.call(name=actual_unique_id, key="result", value=""), mock.call(name=actual_unique_id, key="status", value="queued")]) mock_redis_conn.rpush.assert_has_calls( [mock.call("GN2::job-queue", actual_unique_id)]) @mock.patch("gn3.commands.datetime") @mock.patch("gn3.commands.uuid4") def test_queue_cmd_right_calls_to_redis_with_email(self, mock_uuid4, mock_datetime): """Test that the cmd is queued properly when given the email""" mock_uuid4.return_value = 1234 mock_datetime.now.return_value = datetime.fromisoformat('2021-02-12 ' '17:32:24.' '859097') mock_redis_conn = MockRedis(ping=lambda: True, hset=mock.MagicMock(), rpush=mock.MagicMock()) actual_unique_id = "cmd::2021-02-1217-3224-3224-1234" self.assertEqual(queue_cmd(cmd="ls", conn=mock_redis_conn, job_queue="GN2::job-queue", email="me@me.com"), actual_unique_id) mock_redis_conn.hset.assert_has_calls( [mock.call(name=actual_unique_id, key="cmd", value="ls"), mock.call(name=actual_unique_id, key="result", value=""), mock.call(name=actual_unique_id, key="status", value="queued"), mock.call(name=actual_unique_id, key="email", value="me@me.com") ]) mock_redis_conn.rpush.assert_has_calls( [mock.call("GN2::job-queue", actual_unique_id)]) def test_run_cmd_correct_input(self): """Test that a correct cmd is processed correctly""" self.assertEqual(run_cmd("echo test"), {"code": 0, "output": "test\n"}) def test_run_cmd_incorrect_input(self): """Test that an incorrect cmd is processed correctly""" result = run_cmd("echoo test") self.assertEqual(127, result.get("code"))