Ejemplo n.º 1
0
class TestBCL2FastqRunnerFactory(unittest.TestCase):

    dummy_config = DummyConfig()

    def test_create_bcl2fastq1x_runner(self):
        config = Bcl2FastqConfig(general_config=DUMMY_CONFIG,
                                 bcl2fastq_version="1.8.4",
                                 runfolder_input="test/runfolder",
                                 output="test/output")

        factory = BCL2FastqRunnerFactory(self.dummy_config)
        runner = factory.create_bcl2fastq_runner(config)
        self.assertIsInstance(runner, BCL2Fastq1xRunner)

    def test_create_bcl2fastq2x_runner(self):
        config = Bcl2FastqConfig(general_config=DUMMY_CONFIG,
                                 bcl2fastq_version="2.15.2",
                                 runfolder_input="test/runfolder",
                                 output="test/output")

        factory = BCL2FastqRunnerFactory(self.dummy_config)
        runner = factory.create_bcl2fastq_runner(config)
        self.assertIsInstance(runner,
                              BCL2Fastq2xRunner,
                              msg="runner is: " + str(runner))

    def test_create_invalid_version_runner(self):
        config = Bcl2FastqConfig(general_config=DUMMY_CONFIG,
                                 bcl2fastq_version="1.7",
                                 runfolder_input="test/runfolder",
                                 output="test/output")

        factory = BCL2FastqRunnerFactory(self.dummy_config)
        with self.assertRaises(LookupError):
            factory.create_bcl2fastq_runner(config)
Ejemplo n.º 2
0
import unittest
from mock import patch
import tempfile
import os

from bcl2fastq.lib.bcl2fastq_utils import *
from bcl2fastq.lib.illumina import Samplesheet
from test_utils import TestUtils, DummyConfig


DUMMY_CONFIG = DummyConfig()

class TestBcl2FastqConfig(unittest.TestCase):

    test_dir = os.path.dirname(os.path.realpath(__file__))
    samplesheet_file = test_dir + "/sampledata/new_samplesheet_example.csv"
    samplesheet_with_no_tag = test_dir + "/sampledata/no_tag_samplesheet_example.csv"

    def test_get_bcl2fastq_version_from_run_parameters(self):
        runfolder = TestBcl2FastqConfig.test_dir + "/sampledata/HiSeq-samples/2014-02_13_average_run"
        version = Bcl2FastqConfig.get_bcl2fastq_version_from_run_parameters(runfolder, TestUtils.DUMMY_CONFIG)
        self.assertEqual(version, "1.8.4")

    def test_is_single_read_true(self):
        runfolder = TestBcl2FastqConfig.test_dir + "/sampledata/HiSeq-samples/2014-02_13_average_run"
        self.assertFalse(Bcl2FastqConfig.is_single_read(runfolder))

    def test_is_single_read_false(self):
        runfolder = TestBcl2FastqConfig.test_dir + "/sampledata/MiSeq-samples/2014-02_11_50kit_single_read"
        self.assertTrue(Bcl2FastqConfig.is_single_read(runfolder))
 def get_app(self):
     dummy_config = DummyConfig()
     return Application(routes(config=dummy_config))
Ejemplo n.º 4
0
class TestBcl2FastqConfig(unittest.TestCase):

    test_dir = os.path.dirname(os.path.realpath(__file__))
    samplesheet_file = test_dir + "/sampledata/new_samplesheet_example.csv"
    samplesheet_with_no_tag = test_dir + "/sampledata/no_tag_samplesheet_example.csv"
    dummy_config = DummyConfig()

    def test_get_bcl2fastq_version_from_run_parameters(self):
        runfolder = TestBcl2FastqConfig.test_dir + "/sampledata/HiSeq-samples/2014-02_13_average_run"
        version = Bcl2FastqConfig.get_bcl2fastq_version_from_run_parameters(
            runfolder, self.dummy_config)
        self.assertEqual(version, "1.8.4")

    def test_is_single_read_true(self):
        runfolder = TestBcl2FastqConfig.test_dir + "/sampledata/HiSeq-samples/2014-02_13_average_run"
        self.assertFalse(Bcl2FastqConfig.is_single_read(runfolder))

    def test_is_single_read_false(self):
        runfolder = TestBcl2FastqConfig.test_dir + "/sampledata/MiSeq-samples/2014-02_11_50kit_single_read"
        self.assertTrue(Bcl2FastqConfig.is_single_read(runfolder))

    def test_get_length_of_indexes(self):
        runfolder = TestBcl2FastqConfig.test_dir + "/sampledata/HiSeq-samples/2014-02_13_average_run"
        index_and_length = Bcl2FastqConfig.get_length_of_indexes(runfolder)
        self.assertEqual(index_and_length, {2: 7})

    def test_write_samplesheet(self):
        f = tempfile.mktemp()
        Bcl2FastqConfig.write_samplesheet(TestUtils.DUMMY_SAMPLESHEET_STRING,
                                          f)
        with open(f, "r") as my_file:
            content = my_file.read()
            self.assertEqual(content, TestUtils.DUMMY_SAMPLESHEET_STRING)
        os.remove(f)

    def test_samplesheet_gets_written(self):
        with patch.object(Bcl2FastqConfig, "write_samplesheet") as ws:
            # If we provide a samplesheet to the config this should be written.
            # In this case this write call is mocked away to make testing easier,
            # but the write it self should be trivial.
            config = Bcl2FastqConfig(
                general_config=DUMMY_CONFIG,
                bcl2fastq_version="1.8.4",
                runfolder_input="test/runfolder",
                output="test/output",
                samplesheet=TestUtils.DUMMY_SAMPLESHEET_STRING)

            ws.assert_called_once_with(TestUtils.DUMMY_SAMPLESHEET_STRING,
                                       config.samplesheet_file)

    def test_get_bases_mask_per_lane_from_samplesheet(self):
        mock_read_index_lengths = {2: 9, 3: 9}
        expected_bases_mask = {
            1: "y*,i8n*,i8n*,y*",
            2: "y*,i6n*,n*,y*",
            3: "y*,i6n*,n*,y*",
            4: "y*,i7n*,n*,y*",
            5: "y*,i7n*,n*,y*",
            6: "y*,i7n*,n*,y*",
            7: "y*,i7n*,n*,y*",
            8: "y*,i7n*,n*,y*",
        }
        samplesheet = Samplesheet(TestBcl2FastqConfig.samplesheet_file)
        actual_bases_mask = Bcl2FastqConfig. \
            get_bases_mask_per_lane_from_samplesheet(samplesheet, mock_read_index_lengths, False)
        self.assertEqual(expected_bases_mask, actual_bases_mask)

    def test_get_bases_mask_per_lane_from_samplesheet_single_read(self):
        mock_read_index_lengths = {2: 9, 3: 9}
        expected_bases_mask = {
            1: "y*,i8n*,i8n*",
            2: "y*,i6n*,n*",
            3: "y*,i6n*,n*",
            4: "y*,i7n*,n*",
            5: "y*,i7n*,n*",
            6: "y*,i7n*,n*",
            7: "y*,i7n*,n*",
            8: "y*,i7n*,n*",
        }
        samplesheet = Samplesheet(TestBcl2FastqConfig.samplesheet_file)
        actual_bases_mask = Bcl2FastqConfig. \
            get_bases_mask_per_lane_from_samplesheet(samplesheet, mock_read_index_lengths, True)
        self.assertEqual(expected_bases_mask, actual_bases_mask)

    def test_get_bases_mask_per_lane_from_samplesheet_invalid_length_combo(
            self):
        # These are to short compared to the length indicated in the samplesheet
        mock_read_index_lengths = {2: 4, 3: 4}
        samplesheet = Samplesheet(TestBcl2FastqConfig.samplesheet_file)

        with self.assertRaises(ArteriaUsageException):
            Bcl2FastqConfig. \
                get_bases_mask_per_lane_from_samplesheet(samplesheet, mock_read_index_lengths, False)

    def test_get_bases_mask_per_lane_from_samplesheet_no_tag(self):
        # If we don't have tag for one lane in the samplesheet.
        mock_read_index_lengths = {2: 6}
        expected_bases_mask = {
            1: "y*,n*,y*",
            2: "y*,n*,y*",
            3: "y*,i6,y*",
            4: "y*,i6,y*",
            5: "y*,i6,y*",
            6: "y*,i6,y*",
            7: "y*,n*,y*",
            8: "y*,n*,y*",
        }
        samplesheet = Samplesheet(TestBcl2FastqConfig.samplesheet_with_no_tag)
        actual_bases_mask = Bcl2FastqConfig. \
            get_bases_mask_per_lane_from_samplesheet(samplesheet, mock_read_index_lengths, False)
        self.assertEqual(expected_bases_mask, actual_bases_mask)
Ejemplo n.º 5
0
class TestBcl2FastqHandlers(AsyncHTTPTestCase):

    _start_api_call = 0

    def start_api_call_nbr(self):
        TestBcl2FastqHandlers._start_api_call += 1
        return TestBcl2FastqHandlers._start_api_call

    API_BASE = "/api/1.0"
    MOCK_BCL2FASTQ_DICT = {
        1: "y*,8i,8i,y*",
        2: "y*,6i,n*,y*",
        3: "y*,6i,n*,y*",
        4: "y*,7i,n*,y*",
        5: "y*,7i,n*,y*",
        6: "y*,7i,n*,y*",
        7: "y*,7i,n*,y*",
        8: "y*,7i,n*,y*",
    }

    dummy_config = DummyConfig()
    DUMMY_RUNNER_CONF = DummyRunnerConfig(output='/foo/bar/runfolder',
                                          general_config=dummy_config)

    def get_app(self):
        return Application(routes(config=self.dummy_config))

    def test_versions(self):
        response = self.fetch(self.API_BASE + "/versions")
        self.assertEqual(response.code, 200)
        self.assertEqual(sorted(json.loads(response.body)),
                         sorted(["2.15.2", "1.8.4"]))

    def test_start_missing_runfolder_in_body(self):
        response = self.fetch(self.API_BASE +
                              "/start/150415_D00457_0091_AC6281ANXX",
                              method="POST",
                              body="")
        self.assertEqual(response.code, 500)

    def test_start(self):
        # Use mock to ensure that this will run without
        # creating the runfolder.
        with mock.patch.object(os.path, 'isdir', return_value=True), \
             mock.patch.object(shutil, 'rmtree', return_value=None), \
             mock.patch.object(Bcl2FastqConfig, 'get_bcl2fastq_version_from_run_parameters', return_value="2.15.2"), \
             mock.patch.object(BCL2FastqRunnerFactory, "create_bcl2fastq_runner",
                               return_value=FakeRunner("2.15.2", self.DUMMY_RUNNER_CONF)), \
             mock.patch.object(BCL2FastqRunner, 'symlink_output_to_unaligned', return_value=None):

            body = {"runfolder_input": "/path/to/runfolder"}
            response = self.fetch(self.API_BASE +
                                  "/start/150415_D00457_0091_AC6281ANXX",
                                  method="POST",
                                  body=json_encode(body))

            api_call_nbr = self.start_api_call_nbr()

            self.assertEqual(response.code, 202)
            self.assertEqual(json.loads(response.body)["job_id"], api_call_nbr)
            expected_link = "http://localhost:{0}/api/1.0/status/{1}".format(
                self.get_http_port(), api_call_nbr)
            self.assertEqual(json.loads(response.body)["link"], expected_link)
            self.assertEqual(
                json.loads(response.body)["bcl2fastq_version"], "2.15.2")
            self.assertEqual(json.loads(response.body)["state"], "started")

    def test_start_with_empty_body(self):
        # Use mock to ensure that this will run without
        # creating the runfolder.
        with mock.patch.object(os.path, 'isdir', return_value=True), \
             mock.patch.object(shutil, 'rmtree', return_value=None), \
             mock.patch.object(Bcl2FastqConfig, 'get_bcl2fastq_version_from_run_parameters', return_value="2.15.2"), \
             mock.patch.object(BCL2FastqRunnerFactory, "create_bcl2fastq_runner",
                               return_value=FakeRunner("2.15.2", self.DUMMY_RUNNER_CONF)), \
             mock.patch.object(BCL2FastqRunner, 'symlink_output_to_unaligned', return_value=None):

            response = self.fetch(self.API_BASE +
                                  "/start/150415_D00457_0091_AC6281ANXX",
                                  method="POST",
                                  body="")

            api_call_nbr = self.start_api_call_nbr()

            self.assertEqual(response.code, 202)
            self.assertEqual(json.loads(response.body)["job_id"], api_call_nbr)
            expected_link = "http://localhost:{0}/api/1.0/status/{1}".format(
                self.get_http_port(), api_call_nbr)
            self.assertEqual(json.loads(response.body)["link"], expected_link)
            self.assertEqual(
                json.loads(response.body)["bcl2fastq_version"], "2.15.2")
            self.assertEqual(json.loads(response.body)["state"], "started")

    def test_start_with_disallowed_output_specified(self):

        # TODO Please note that this test is not very good, since the
        #      what we ideally want to test is the output specifed by the request,
        #      and that that gets rejected, however since the create_bcl2fastq_runner command
        #      is mocked away here and that is what returns the invalid output the tests is
        #      a bit misleading. In the future we probably want to refactor this.
        #      / JD 20170117
        runner_conf_with_invalid_output = DummyRunnerConfig(
            output='/not/foo/bar/runfolder', general_config=self.dummy_config)
        with mock.patch.object(os.path, 'isdir', return_value=True), \
             mock.patch.object(shutil, 'rmtree', return_value=None) as rmmock, \
             mock.patch.object(Bcl2FastqConfig, 'get_bcl2fastq_version_from_run_parameters', return_value="2.15.2"), \
             mock.patch.object(BCL2FastqRunnerFactory, "create_bcl2fastq_runner",
                               return_value=FakeRunner("2.15.2", runner_conf_with_invalid_output)), \
             mock.patch.object(BCL2FastqRunner, 'symlink_output_to_unaligned', return_value=None):

            # This output dir is not allowed by the config
            body = {'output': '/not/foo/bar'}
            response = self.fetch(self.API_BASE +
                                  "/start/150415_D00457_0091_AC6281ANXX",
                                  method="POST",
                                  body=json_encode(body))

            self.assertEqual(response.code, 500)
            self.assertEqual(
                response.reason,
                "Invalid output directory /not/foo/bar/runfolder was specified."
                " Allowed dirs were: ['/foo/bar']")
            rmmock.assert_not_called()

    def test_start_with_allowed_output_specified(self):
        with mock.patch.object(os.path, 'isdir', return_value=True), \
            mock.patch.object(shutil, 'rmtree', return_value=None) as rmmock, \
            mock.patch.object(Bcl2FastqConfig, 'get_bcl2fastq_version_from_run_parameters', return_value="2.15.2"), \
            mock.patch.object(BCL2FastqRunnerFactory, "create_bcl2fastq_runner",
                              return_value=FakeRunner("2.15.2", self.DUMMY_RUNNER_CONF)), \
            mock.patch.object(BCL2FastqRunner, 'symlink_output_to_unaligned', return_value=None):
            body = {'output': '/foo/bar'}
            response = self.fetch(self.API_BASE +
                                  "/start/150415_D00457_0091_AC6281ANXX",
                                  method="POST",
                                  body=json_encode(body))

            # Just increment it here so it doesn't break the other tests
            self.start_api_call_nbr()
            self.assertEqual(response.code, 202)
            rmmock.assert_called_with('/foo/bar/runfolder')

    def test_start_providing_samplesheet(self):
        # Use mock to ensure that this will run without
        # creating the runfolder.
        with mock.patch.object(os.path, 'isdir', return_value=True), \
             mock.patch.object(shutil, 'rmtree', return_value=None), \
             mock.patch.object(Bcl2FastqConfig, 'get_bcl2fastq_version_from_run_parameters', return_value="2.15.2"), \
             mock.patch.object(BCL2FastqRunner, 'symlink_output_to_unaligned', return_value=None), \
             mock.patch.object(Bcl2FastqConfig, "write_samplesheet") as ws , \
                mock.patch.object(BCL2FastqRunnerFactory, "create_bcl2fastq_runner",
                                  return_value=FakeRunner("2.15.2", self.DUMMY_RUNNER_CONF)):

            body = {
                "runfolder_input": "/path/to/runfolder",
                "samplesheet": TestUtils.DUMMY_SAMPLESHEET_STRING
            }

            response = self.fetch(self.API_BASE +
                                  "/start/150415_D00457_0091_AC6281ANXX",
                                  method="POST",
                                  body=json_encode(body))

            api_call_nbr = self.start_api_call_nbr()

            self.assertEqual(response.code, 202)
            self.assertEqual(json.loads(response.body)["job_id"], api_call_nbr)
            expected_link = "http://localhost:{0}/api/1.0/status/{1}".format(
                self.get_http_port(), api_call_nbr)
            self.assertEqual(json.loads(response.body)["link"], expected_link)
            self.assertEqual(
                json.loads(response.body)["bcl2fastq_version"], "2.15.2")
            self.assertEqual(json.loads(response.body)["state"], "started")
            ws.assert_called_once_with(
                TestUtils.DUMMY_SAMPLESHEET_STRING,
                "/data/biotank3/runfolders/150415_D00457_0091_AC6281ANXX/SampleSheet.csv"
            )

    def test_status_with_id(self):
        #TODO Add real tests here!
        response = self.fetch(self.API_BASE + "/status/1123456546",
                              method="GET")
        self.assertEqual(response.code, 200)

    def test_status_without_id(self):
        #TODO Add real tests here!
        response = self.fetch(self.API_BASE + "/status/", method="GET")
        self.assertEqual(response.code, 200)

    def test_all_stop_handler(self):
        response = self.fetch(self.API_BASE + "/stop/all",
                              method="POST",
                              body="")
        self.assertEqual(response.code, 200)

    def test_stop_handler(self):
        response = self.fetch(self.API_BASE + "/stop/3",
                              method="POST",
                              body="")
        self.assertEqual(response.code, 200)

    def test_exception_stop_handler(self):
        response = self.fetch(self.API_BASE + "/stop/lll",
                              method="POST",
                              body="")
        self.assertEqual(response.code, 500)

    def test_get_logs(self):
        with mock.patch.object(Bcl2FastqLogFileProvider,
                               "get_log_for_runfolder",
                               return_value="This is a string"):
            response = self.fetch(self.API_BASE + "/logs/coolest_runfolder",
                                  method="GET")
            self.assertEqual(response.code, 200)
            self.assertEqual(
                json.loads(response.body)["log"], "This is a string")

    def test_get_logs_trying_to_reach_other_files(self):
        response = self.fetch(self.API_BASE + "/logs/../../../etc/shadow",
                              method="GET")
        self.assertEqual(response.code, 404)