From 45a8590d10c045b17197c5465aa0e8a97fea9eb9 Mon Sep 17 00:00:00 2001
From: kienle <kienle@passcal.nmt.edu>
Date: Mon, 26 Sep 2022 15:53:35 -0600
Subject: [PATCH] Add tests for saveData2File

---
 tests/test_model/test_handling_data.py | 91 +++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 3 deletions(-)

diff --git a/tests/test_model/test_handling_data.py b/tests/test_model/test_handling_data.py
index 2efec2403..e8de60b7a 100644
--- a/tests/test_model/test_handling_data.py
+++ b/tests/test_model/test_handling_data.py
@@ -2,11 +2,12 @@ from pathlib import Path
 import tempfile
 from math import isclose
 from copy import copy as shallow_copy
+import tracemalloc
 
-from unittest import TestCase
+from unittest import TestCase, expectedFailure
 from unittest.mock import patch
 
-from obspy.core import Stream, read as read_ms
+from obspy.core import Trace, read as read_ms
 import numpy as np
 
 from sohstationviewer.model.handling_data import (
@@ -18,6 +19,7 @@ from sohstationviewer.model.handling_data import (
     readWaveformReftek,
     readASCII,
     readText,
+    saveData2File,
 )
 from sohstationviewer.model.reftek.from_rt2ms.core import Reftek130
 
@@ -420,6 +422,7 @@ class TestReadASCII(TestCase):
             'Quanterra Packet Baler Model 14 Restart. Version 2.26'
         )
 
+    @expectedFailure
     def test_trace_does_not_contain_log_data(self):
         raise NotImplementedError(
             self.test_trace_does_not_contain_log_data.__qualname__)
@@ -478,4 +481,86 @@ class TestReadText(TestCase):
         with self.assertRaises(FileNotFoundError):
             readText(str(non_existent_file),
                      non_existent_file.name,
-                     self.text_logs)
\ No newline at end of file
+                     self.text_logs)
+
+
+class TestSaveData2File(TestCase):
+    def setUp(self) -> None:
+        self.temp_dir = tempfile.TemporaryDirectory()
+        self.time_data = 'timedata'
+        self.station_id = 'station'
+        self.channel_id = 'channel'
+        self.trace_idx = 0
+        self.trace_size = 100
+        tracemalloc.start()
+        # We do not need the metadata of a data set (stored in Trace.stats), so
+        # we can create a trace without reading any data set. This approach
+        # allows us to create a trace that contains a large amount of data
+        # without having to store a large data set in the GitLab server.
+        self.trace = Trace(np.ones(self.trace_size))
+
+        # The current implementation stores the data in a memmap that contains
+        # 64-bit integers, and so each data point has a size of 8 bytes in the
+        # memmap
+        self.data_point_size = 8
+
+    def tearDown(self) -> None:
+        self.temp_dir.cleanup()
+        tracemalloc.stop()
+
+    def test_file_created(self):
+        mem_file_name = saveData2File(self.temp_dir.name, self.time_data,
+                                      self.station_id, self.channel_id,
+                                      self.trace, self.trace_idx,
+                                      self.trace_size)
+
+        self.assertTrue(mem_file_name.is_file())
+
+        expected_mem_file_name = "station-channel-timedata-0"
+        self.assertEqual(mem_file_name.name, expected_mem_file_name)
+
+        memmap_size = self.data_point_size * self.trace_size
+        self.assertEqual(mem_file_name.stat().st_size, memmap_size)
+
+    @patch.object(np, 'memmap')
+    def test_memmap_called(self, mock_memmap):
+        saveData2File(self.temp_dir.name, self.time_data, self.station_id,
+                      self.channel_id, self.trace, self.trace_idx,
+                      self.trace_size)
+        self.assertTrue(mock_memmap.called)
+
+    @expectedFailure
+    def test_memory_freed(self):
+        # This test works by calculating the amount of memory freed after
+        # saveData2File is called. Because there are operations happening
+        # between the memory being freed and the calculation, the calculated
+        # amount of memory won't be exact. Fixing this would involve removing
+        # all the aforementioned intermediate operations, which is (very
+        # likely) impossible and does not provide much value due to the actual
+        # deviation being small (consistently at most 1000 bytes).
+
+        # The difference between the calculated amount of freed memory and the
+        # size of the memmap is around 1000 bytes, we want data that is at
+        # least an order of magnitude bigger to ensure that this difference is
+        # obvious in our calculation.
+        self.trace_size = 10000
+        self.trace = Trace(np.ones(self.trace_size))
+        memmap_size = self.trace_size * self.data_point_size
+
+        current_mem_used = tracemalloc.get_traced_memory()[0]
+        saveData2File(self.temp_dir.name, self.time_data, self.station_id,
+                      self.channel_id, self.trace, self.trace_idx,
+                      self.trace_size)
+        freed_mem = current_mem_used - tracemalloc.get_traced_memory()[0]
+
+        freed_mem_max_error = 1000
+        self.assertTrue(isclose(memmap_size, freed_mem,
+                                abs_tol=freed_mem_max_error))
+
+    def test_empty_trace(self):
+        self.trace_size = 0
+        self.trace = Trace(np.ones(self.trace_size))
+        with self.assertRaises(ValueError):
+            saveData2File(self.temp_dir.name, self.time_data, self.station_id,
+                          self.channel_id, self.trace, self.trace_idx,
+                          self.trace_size)
\ No newline at end of file
-- 
GitLab