Skip to content
Snippets Groups Projects
test_processing.py 12.4 KiB
Newer Older
Kien Le's avatar
Kien Le committed
from tempfile import TemporaryDirectory, NamedTemporaryFile
from pathlib import Path

from unittest import TestCase
from unittest.mock import patch

from sohstationviewer.controller.processing import (
    loadData,
    readChannels,
    detectDataType,
    getDataTypeFromFile
)
from sohstationviewer.database.extractData import signatureChannels
from PySide2 import QtWidgets
from sohstationviewer.model.mseed.mseed import MSeed
from sohstationviewer.model.reftek.reftek import RT130

TEST_DATA_DIR = Path(__file__).resolve().parent.parent.joinpath('test_data')
rt130_dir = TEST_DATA_DIR.joinpath('RT130-sample/2017149.92EB/2017150')
q330_dir = TEST_DATA_DIR.joinpath('Q330-sample/day_vols_AX08')
centaur_dir = TEST_DATA_DIR.joinpath('Centaur-sample/SOH')
pegasus_dir = TEST_DATA_DIR.joinpath('Pegasus-sample/Pegasus_SVC4/soh')


class TestLoadDataAndReadChannels(TestCase):
    """Test suite for loadData and readChannels."""

    def setUp(self) -> None:
        """Set up test fixtures."""
        patcher = patch.object(QtWidgets, 'QTextBrowser')
        self.addCleanup(patcher.stop)
        self.widget_stub = patcher.start()

        # The actual value can be 'Q330', 'Centaur', or 'Pegasus'.
        # The code that uses this string only cares that it is not 'RT130',
        # though, so we are setting it to a stub value.
        self.mseed_dtype = 'MSeed'

    def test_load_data_rt130_good_dir(self):
        """
        Test basic functionality of loadData - the given directory can be
        loaded without issues. Test RT130.
        """
        self.assertIsInstance(
            loadData('RT130', self.widget_stub, [rt130_dir]),
            RT130
        )

    def test_load_data_mseed_q330_good_data_dir(self):
        """
        Test basic functionality of loadData - the given directory can be
        loaded without issues. Test MSeed.
        """
        self.assertIsInstance(
            loadData(self.mseed_dtype, self.widget_stub, [q330_dir]),
            MSeed
        )
        self.assertIsInstance(
            loadData(self.mseed_dtype, self.widget_stub, [centaur_dir]),
            MSeed
        )
        self.assertIsInstance(
            loadData(self.mseed_dtype, self.widget_stub, [pegasus_dir]),
            MSeed
        )

    def test_load_data_rt130_no_dir(self):
        """Test basic functionality of loadData - no directory was given."""
        no_dir_given = []
        self.assertIsNone(loadData('RT130', self.widget_stub, no_dir_given))
        self.assertIsNone(
            loadData(self.mseed_dtype, self.widget_stub, no_dir_given))

    def test_load_data_rt130_dir_does_not_exist(self):
        """
        Test basic functionality of loadData - the given directory does not
        exist.
        """
        empty_name_dir = ['']
        non_existent_dir = ['dir_that_does_not_exist']

        with self.assertRaises(Exception):
            loadData('RT130', self.widget_stub, empty_name_dir)
        with self.assertRaises(Exception):
            loadData('RT130', self.widget_stub, non_existent_dir)

        self.assertIsNone(
            loadData(self.mseed_dtype, self.widget_stub, empty_name_dir))
        self.assertIsNone(
            loadData(self.mseed_dtype, self.widget_stub, non_existent_dir))

    def test_load_data_rt130_empty_dir(self):
        """
        Test basic functionality of loadData - the given directory is empty.
        """
        with TemporaryDirectory() as empty_dir:
            with self.assertRaises(Exception):
                loadData('RT130', self.widget_stub, [empty_dir])
            self.assertIsNone(
                loadData(self.mseed_dtype, self.widget_stub, [empty_dir]))

    def test_load_data_rt130_empty_data_dir(self):
        """
        Test basic functionality of loadData - the given directory
        contains a data folder but no data file.
        """
        with TemporaryDirectory() as outer_dir:
            with TemporaryDirectory(dir=outer_dir) as data_dir:
                with self.assertRaises(Exception):
                    loadData('RT130', self.widget_stub, [data_dir])
                self.assertIsNone(
                    loadData(self.mseed_dtype, self.widget_stub, [outer_dir]))

    def test_load_data_data_type_mismatch(self):
        """
        Test basic functionality of loadData - the data type given does not
        match the type of the data contained in the given directory.
        """
        with self.assertRaises(Exception):
            loadData('RT130', self.widget_stub, [q330_dir])
        self.assertIsNone(
            loadData(self.mseed_dtype, self.widget_stub, [rt130_dir]))

    def test_read_channels_mseed_dir(self):
        """
        Test basic functionality of loadData - the given directory contains
        MSeed data.
        """
        q330_channels = {'VKI', 'VM1'}
        self.assertSetEqual(readChannels(self.widget_stub, [q330_dir]),
                            q330_channels)

        centaur_channels = {'VDT', 'VM3', 'EX3', 'GEL', 'VEC', 'EX2', 'LCE',
                            'EX1', 'GLA', 'LCQ', 'GPL', 'GNS', 'GST', 'VCO',
                            'GAN', 'GLO', 'VPB', 'VEI', 'VM2', 'VM1'}
        self.assertSetEqual(readChannels(self.widget_stub, [centaur_dir]),
                            centaur_channels)

        pegasus_channels = {'VDT', 'VM1', 'VE1'}
        self.assertSetEqual(readChannels(self.widget_stub, [pegasus_dir]),
                            pegasus_channels)

    def test_read_channels_rt130_dir(self):
        """
        Test basic functionality of loadData - the given directory contains
        RT130 data.
        """
        with self.assertRaises(Exception):
            readChannels(self.widget_stub, [rt130_dir])

    def test_read_channels_no_dir(self):
        """
        Test basic functionality of readChannels - no directory was given.
        """
        no_dir = []
        with self.assertRaises(Exception):
            readChannels(self.widget_stub, no_dir)

    def test_read_channels_dir_does_not_exist(self):
        """
        Test basic functionality of readChannels - the given directory does not
        exist.
        """
        empty_name_dir = ['']
        non_existent_dir = ['non_existent_dir']
        with self.assertRaises(Exception):
            readChannels(self.widget_stub, empty_name_dir)
        with self.assertRaises(Exception):
            readChannels(self.widget_stub, non_existent_dir)

    def test_read_channels_empty_dir(self):
        """
        Test basic functionality of readChannels - the given directory is
        empty.
        """
        with TemporaryDirectory() as empty_dir:
            with self.assertRaises(Exception):
                readChannels(self.widget_stub, [empty_dir])

    def test_read_channels_empty_data_dir(self):
        """
        Test basic functionality of readChannels - the given directory
        contains a data folder but no data file.
        """
        with TemporaryDirectory() as outer_dir:
            with TemporaryDirectory(dir=outer_dir):
                with self.assertRaises(Exception):
                    readChannels(self.widget_stub, [outer_dir])


class TestDetectDataType(TestCase):
    """Test suite for detectDataType and getDataTypeFromFile functions."""

    def setUp(self) -> None:
        """Set up text fixtures."""
        widget_patcher = patch.object(QtWidgets, 'QTextBrowser')
        self.addCleanup(widget_patcher.stop)
        self.widget_stub = widget_patcher.start()

        func_patcher = patch('sohstationviewer.controller.processing.'
                             'getDataTypeFromFile')
        self.addCleanup(func_patcher.stop)
        self.mock_get_data_type_from_file = func_patcher.start()

        self.dir1 = TemporaryDirectory()
        self.dir2 = TemporaryDirectory()
        self.file1 = NamedTemporaryFile(dir=self.dir1.name)
        self.file2 = NamedTemporaryFile(dir=self.dir2.name)

    def tearDown(self) -> None:
        """Teardown text fixtures."""
        del self.file1, self.file2
        self.dir1.cleanup()
        self.dir2.cleanup()

    def test_one_directory_not_unknown_data_type(self):
        """
        Test basic functionality of detectDataType - only one directory was
        given and the data type it contains can be detected.
        """
        expected_data_type = ('RT130', '_')
        self.mock_get_data_type_from_file.return_value = expected_data_type

        self.assertEqual(
            detectDataType(self.widget_stub, [self.dir1.name]),
            expected_data_type[0]
        )

    def test_same_data_type_and_channel(self):
        """
        Test basic functionality of detectDataType - the given directories
        contain the same data type and the data type was detected using the
        same channel.
        """
        expected_data_type = ('RT130', '_')
        self.mock_get_data_type_from_file.return_value = expected_data_type

        self.assertEqual(
            detectDataType(self.widget_stub, [self.dir1.name, self.dir2.name]),
            expected_data_type[0]
        )

    def test_same_data_type_different_channel(self):
        """
        Test basic functionality of detectDataType - the given directories
        contain the same data type but the data type was detected using
        different channels.
        """
        returned_data_types = [('Q330', 'OCF'), ('Q330', 'VEP')]
        self.mock_get_data_type_from_file.side_effect = returned_data_types

        self.assertEqual(
            detectDataType(self.widget_stub, [self.dir1.name, self.dir2.name]),
            returned_data_types[0][0]
        )

    def test_different_data_types(self):
        """
        Test basic functionality of detectDataType - the given directories
        contain different data types.
        """
        returned_data_types = [('RT130', '_'), ('Q330', 'VEP')]
        self.mock_get_data_type_from_file.side_effect = returned_data_types

        self.assertIsNone(
            detectDataType(self.widget_stub, [self.dir1.name, self.dir2.name])
        )

    def test_unknown_data_type(self):
        """
        Test basic functionality of detectDataType - can't detect any data
        type.
        """
        unknown_data_type = ('Unknown', '_')
        self.mock_get_data_type_from_file.return_value = unknown_data_type

        self.assertIsNone(detectDataType(self.widget_stub, [self.dir1.name]))


class TestGetDataTypeFromFile(TestCase):
    """Test suite for getDataTypeFromFile"""
    def test_rt130_data(self):
        """
        Test basic functionality of getDataTypeFromFile - given file contains
        RT130 data.
        """
        rt130_file = Path(rt130_dir).joinpath(
            '92EB/0/000000000_00000000')
        expected_data_type = ('RT130', '_')
        self.assertTupleEqual(
            getDataTypeFromFile(rt130_file, signatureChannels()),
            expected_data_type
        )

    def test_cannot_detect_data_type(self):
        """
        Test basic functionality of getDataTypeFromFile - cannot detect data
        type contained in given file.
        """
        test_file = NamedTemporaryFile()
        self.assertIsNone(
            getDataTypeFromFile(test_file.name, signatureChannels()))

    def test_mseed_data(self):
        """
        Test basic functionality of getDataTypeFromFile - given file contains
        MSeed data.
        """
        q330_file = q330_dir.joinpath('AX08.XA..VKI.2021.186')
        centaur_file = centaur_dir.joinpath(
            'XX.3734.SOH.centaur-3_3734..20180817_000000.miniseed.miniseed')
        pegasus_file = pegasus_dir.joinpath(
            '2020/XX/KC01/VE1.D/XX.KC01..VE1.D.2020.129')
        q330_data_type = ('Q330', 'VKI')
        centaur_data_type = ('Centaur', 'GEL')
        pegasus_data_type = ('Pegasus', 'VE1')

        sig_chan = signatureChannels()

        self.assertTupleEqual(getDataTypeFromFile(q330_file, sig_chan),
                              q330_data_type)
        self.assertTupleEqual(getDataTypeFromFile(centaur_file, sig_chan),
                              centaur_data_type)
        self.assertTupleEqual(getDataTypeFromFile(pegasus_file, sig_chan),
                              pegasus_data_type)

    def test_file_does_not_exist(self):
        """
        Test basic functionality of getDataTypeFromFile - given file does not
        exist.
        """
        empty_name_file = ''
        non_existent_file = 'non_existent_dir'
        with self.assertRaises(FileNotFoundError):
            getDataTypeFromFile(empty_name_file, signatureChannels())
        with self.assertRaises(FileNotFoundError):
            getDataTypeFromFile(non_existent_file, signatureChannels())