text: '''
  Unit test of the driver for the Fortran loop breaking code
  Created on Oct 30, 2016
  
  @author: thomasriddick
  '''
  
  import unittest
  import numpy as np
  import re
  import subprocess
  from subprocess import CalledProcessError
  from Dynamic_HD_Scripts.base import field
  from Dynamic_HD_Scripts.tools import loop_breaker_driver
  from Dynamic_HD_Scripts import context as scripts_context
  from Dynamic_HD_Script_Tests import context
  
  class Test(unittest.TestCase):
      """Unit test object"""
  
      show_output = False
  
      course_rdirs = np.array([[6,1,6,6,1],
                               [8,4,4,8,7],
                               [1,-1,5,0,6],
                               [2,4,9,8,8],
                               [9,6,8,7,6]],dtype=np.float64)
  
      course_cumulative_flow = np.array([[0,0,1,0,0],
                                         [0,2,1,0,1],
                                         [0,0,1,0,0],
                                         [0,0,0,1,0],
                                         [0,0,0,1,1]],dtype=np.float64)
      course_catchments = np.array([[25,25,61,61,61],
                                    [25,25,25,61,61],
                                    [13,0,14,58,13],
                                    [9,9,58,19,13],
                                    [9,58,58,58,9]],dtype=np.float64)
      fine_rdirs = np.array([[6,6,6, 6,6,2, 6,6,3, 6,6,6, 6,6,2],
                             [6,6,6, 6,6,6, 9,8,4, 4,6,6, 6,6,2],
                             [6,6,6, 6,6,8, 8,8,8,  6,6,6, 6,6,2],
                             [6,6,6, 6,6,8, 8,8,8, 6,6,6, 6,6,2],
                             [6,6,6, 6,6,8, 8,8,8, 6,6,6, 6,6,2],
                             [6,6,6, 6,6,3, 8,8,8, 6,6,6, 6,6,6],
                             [4,4,4, 0,1,2, -1,-1,-1, 5,5,5, 7,6,8],
                             [4,4,4, 0,1,2, 5,6,2,    1,1,1, 8,6,6],
                             [4,4,4, 0,1,2, 1,5,2,    2,3,8, 8,6,6],
                             [4,6,6, 6,9,6, 3,2,1, 1,2,3,  8,8,8],
                             [6,6,6, 6,8,4, 4,5,6, 4,5,6,  8,8,8],
                             [6,6,6, 6,8,4, 9,8,7, 7,8,9,  8,8,8],
                             [8,8,8, 6,6,6, 8,8,8, 3,3,3,  2,2,2],
                             [8,8,8, 6,6,6, 8,8,8, 3,3,3,  2,2,2],
                             [8,8,8, 6,6,6, 8,8,6, 3,3,3,  2,2,2 ]],dtype=np.float64)
      fine_cumulative_flow = np.array([[1,1,205, 1,1,1,   1,1,1, 1,1,1, 1,1,1],
                                       [1,1,1, 1,1,206, 207,1,1, 61,1,1, 1,1,1],
                                       [1,1,1,  1,1,1,    1,1,1, 1,1,1, 1,1,1],
                                       [1,1,1, 1,1,1,  1,1,1, 1,1,1, 1,1,1],
                                       [1,1,1, 1,1,1,  1,1,1, 1,1,1, 1,1,1],
                                       [1,1,1, 1,1,221,  1,1,1, 1,1,1, 1,1,1],
                                       [1,1,1, 1,1,1, 1,1,1, 1,1,1, 207,1,56],
                                       [1,1,1, 1,1,1, 1,1,1, 1,1,1,   1,1,1],
                                       [1,1,1, 1,1,1, 1,1,1, 1,1,1,   1,1,1],
                                       [32,1,1, 35,36,37, 1,1,1, 1,1,1, 1,1,1],
                                       [1,1,1, 1,1,1, 1,90,1, 1,1,1, 1,1,1],
                                       [1,1,1, 1,1,1, 1,1,1, 1,1,1, 1,1,1],
                                       [1,1,1, 1,1,1, 1,1,1, 1,1,1, 1,1,1],
                                       [1,1,1, 1,1,1, 1,1,1, 1,1,1, 1,1,1],
                                       [1,1,1, 1,1,1, 1,1,11, 1,1,1, 1,1,1]],dtype=np.float64)
      expected_results = np.array([[6,6,6,4,1],
                                   [8,4,4,8,7],
                                   [1,-1,5,0,7],
                                   [2,6,5,8,8],
                                   [9,6,8,7,6 ]],dtype=np.float64)
      loop_nums_list = [25,61,9,58,13]
  
      def testUsingSmallGrid(self):
          """
          Test using a small 5 by 5 grid as the course grid, 15 by 15 fine grid
  
          Same data was used in FRUIT unit testing
          """
  
          course_rdirs_field = field.makeField(self.course_rdirs,
                                               field_type='RiverDirections',
                                               grid_type='LatLong',nlat=5,nlong=5)
          course_cumulative_flow_field = field.makeField(self.course_cumulative_flow,
                                                         field_type='CumulativeFlow',
                                                         grid_type='LatLong',nlat=5,nlong=5)
          course_catchments_field = field.makeField(self.course_catchments,
                                                    field_type='Generic',
                                                    grid_type='LatLong',nlat=15,nlong=15)
          fine_rdirs_field = field.makeField(self.fine_rdirs,
                                             field_type='RiverDirections',
                                             grid_type='LatLong',nlat=15,nlong=15)
          fine_cumulative_flow_field = field.makeField(self.fine_cumulative_flow,
                                                       field_type='CumulativeFlow',
                                                       grid_type='LatLong',nlat=15,nlong=15)
          updated_output_course_river_directions =\
              loop_breaker_driver.run_loop_breaker(course_rdirs_field, course_cumulative_flow_field,
                                                   course_catchments_field, fine_rdirs_field,
                                                   fine_cumulative_flow_field, self.loop_nums_list,
                                                   course_grid_type='LatLong',nlat=5,nlong=5)
          np.testing.assert_array_equal(updated_output_course_river_directions.get_data(), self.expected_results,
                                        "Testing the loop breaking code with a small test grid doesn't give"
                                        " expected results")
  
      @unittest.skip("Valgrind not working")
      def testForMemoryLeaksWithValgrind(self):
          """Use Valgrind to find any new memory leaks that are occuring"""
          try:
              valgrind_output =  subprocess.check_output([context.valgrind_path,'--leak-check=full',
                                                          scripts_context.fortran_project_executable_path],
                                                         stderr=subprocess.STDOUT,
                                                         cwd=scripts_context.fortran_project_include_path)
          except CalledProcessError as cperror:
              raise RuntimeError("Failure in called process {0}; return code {1}; output:\n{2}".format(cperror.cmd,
                                                                                                       cperror.returncode,
                                                                                                       cperror.output))
          direct_mem_loss_match = re.search(r'definitely lost: ([,0-9]*)',valgrind_output)
          indirect_mem_loss_match = re.search(r'indirectly lost: ([,0-9]*)',valgrind_output)
          if self.show_output:
              print(valgrind_output)
          direct_mem_loss = int(direct_mem_loss_match.group(1).replace(',',''))
          indirect_mem_loss = int(indirect_mem_loss_match.group(1).replace(',',''))
          # 80 byte loss is a known problem that occurs sometimes related to using valgrind in python
          self.assertTrue((direct_mem_loss == 0 or direct_mem_loss == 80),"Direct memory leak detected")
          # 68 byte loss is a known problem that occurs sometimes related to using valgrind in python
          self.assertTrue((indirect_mem_loss == 0 or indirect_mem_loss == 68),"Indirect memory leak detected")
  
  if __name__ == "__main__":
      #import sys;sys.argv = ['', 'Test.testName']
      unittest.main()
  