From 8603a535a7435f8ea235447efa6041bb93561488 Mon Sep 17 00:00:00 2001
From: Maeva Pourpoint <maeva@passcal.nmt.edu>
Date: Fri, 12 Jun 2020 13:45:57 -0600
Subject: [PATCH] Update test_data2passcal.py - add unit tests to mock ftp
 connection failure, and rename environment variable MOCK_TEST to SEND4REAL;
 Update tox.ini to pass environment variables to test commands

---
 data2passcal/data2passcal.py |  4 ++--
 tests/test_data2passcal.py   | 41 +++++++++++++++++++++++++++++++-----
 tox.ini                      |  6 ++++++
 3 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/data2passcal/data2passcal.py b/data2passcal/data2passcal.py
index 7d6a5f7..2edc50b 100644
--- a/data2passcal/data2passcal.py
+++ b/data2passcal/data2passcal.py
@@ -258,7 +258,7 @@ def get_FTP():
             FTP.set_debuglevel(FTP_DEBUG_LEVEL)
             FTP.cwd(FTP_DIR)
             FTP.set_pasv(True)
-        except ftplib.all_errors:
+        except Exception:
             logger.exception('Failed to open FTP connection to %s' % FTP_HOST)
             test_network()
             logger.info('Waiting %d seconds before trying to reconnect...'
@@ -407,7 +407,7 @@ def send2passcal(mslist, sentlist=None):
                 logger.exception('Failed to send file %s, permission error.'
                                  % current_file)
                 break
-            except (ftplib.all_errors, AttributeError):
+            except Exception:
                 # since we can restore with how we have proftp setup.
                 # There is nothing more we can do with this file
                 # Until the server rms the .in.file
diff --git a/tests/test_data2passcal.py b/tests/test_data2passcal.py
index 2c14616..cb075bc 100644
--- a/tests/test_data2passcal.py
+++ b/tests/test_data2passcal.py
@@ -18,10 +18,14 @@ else:
 
 VERSION = '2020.119'
 
-MOCK_TEST = os.environ.get('MOCK_TEST', 'True')
-print("MOCK_TEST = True by default. If one wants to test sending data to"
-      "PASSCAL for 'real', set MOCK_TEST=False as environment variable. "
-      "ex: MOCK_TEST=False python -m unittest test_data2passcal")
+SEND4REAL = os.environ.get('SEND4REAL', 'False')
+print("SEND4REAL=False by default. If one wants to test sending data to "
+      "PASSCAL for 'real', set SEND4REAL=True as environment variable. "
+      "ex: SEND4REAL=True python -m unittest test_data2passcal")
+FTP_FAILURE = os.environ.get('FTP_FAILURE', 'False')
+print("FTP_FAILURE=False by default. If one wants to mock test a failure to "
+      "FTP connect to PASSCAL, set FTP_FAILURE=True as environment variable. "
+      "ex: FTP_FAILURE=True python -m unittest test_data2passcal")
 
 TEST_DIR = os.path.dirname(os.path.realpath(__file__)) + '/test_data'
 MS_FILELIST = ['ST00.AB..BHZ.2007.160', 'ST00.AB..BHZ.2007.161',
@@ -67,6 +71,19 @@ class TestData2passcal(unittest.TestCase):
                         .format(d2p.FTP_CONNECT_ATTEMPTS))
         mock_ftp.quit()
 
+    @patch('data2passcal.data2passcal.ftplib.FTP', autospec=True)
+    @unittest.skipIf(FTP_FAILURE == 'False', "skipping mocking FTP failure")
+    def test_get_FTP_failure_mock(self, mock_ftp_constructor):
+        """
+        Mock test failure to create ftp connection to PASSCAL and exercise
+        get_FTP()
+        """
+        mock_ftp_constructor.return_value = None
+        d2p.get_FTP()
+        self.assertGreater(mock_ftp_constructor.call_count, 1,
+                           "ftplib.FTP() called only once - get_FTP() not "
+                           "fully exercised!")
+
     @patch('data2passcal.data2passcal.ftplib.FTP', autospec=True)
     def test_send_data_mock(self, mock_ftp_constructor):
         """Mock test sending MSEED files (test data) to PASSCAL's QC system"""
@@ -87,7 +104,21 @@ class TestData2passcal(unittest.TestCase):
                             'Attempted to send file {0} more than {1} times'
                             .format(f, d2p.FTP_SEND_ATTEMPTS))
 
-    @unittest.skipIf(MOCK_TEST == 'True', "skipping real send2passcal test")
+    @patch('data2passcal.data2passcal.os._exit', autospec=True)
+    @patch('data2passcal.data2passcal.ftplib.FTP', autospec=True)
+    @unittest.skipIf(FTP_FAILURE == 'False', "skipping mocking FTP failure")
+    def test_send_data_failure_mock(self, mock_ftp_constructor, mock_exit):
+        """
+        Mock test failure to create ftp connection to PASSCAL and exercise
+        send_data()
+        """
+        mock_ftp_constructor.return_value = None
+        filelist = [os.path.join(TEST_DIR, f) for f in MS_FILELIST]
+        d2p.send2passcal(filelist)
+        self.assertTrue(mock_exit.called, "os._exit(1) never called - "
+                                          "send_data() not fully exercised!")
+
+    @unittest.skipIf(SEND4REAL == 'False', "skipping real send2passcal test")
     def test_send_data(self):
         """Test sending MSEED files (test data) to PASSCAL's QC system"""
         ftp = d2p.get_FTP()
diff --git a/tox.ini b/tox.ini
index 7270737..2c6aebb 100644
--- a/tox.ini
+++ b/tox.ini
@@ -9,11 +9,17 @@ commands = flake8 --ignore=E722,E712 data2passcal
 
 [testenv:py27]
 changedir = tests
+passenv =
+         SEND4REAL
+         FTP_FAILURE
 deps =
       mock
       timeout-decorator
 commands = python -m unittest test_data2passcal
 
 [testenv]
+passenv =
+         SEND4REAL
+         FTP_FAILURE
 deps = timeout-decorator
 commands = python -m unittest
-- 
GitLab