#!/usr/bin/env python
#
# Copyright 2016-2017 VMware, Inc.  All rights reserved. -- VMware Confidential
#

import os
import unittest
from distutils.version import LooseVersion

# Absolute import so that one can run the unitests from the endpoint-b2b folder
# with PYTHONPATH=$(dirname `pwd`) python3.5 -m unittest
# import_module is used because of the dash in the module's name.
from importlib import import_module
module = import_module('endpoint-b2b.properties_util')

PROPERTIES_FILE = "test.properties"
PROPERTIES_FILE_CONTENTS = """\
property = 42
another.property = 84
"""
PROPERTY_NAME = "property"
PROPERTIES_BCK_FILE = PROPERTIES_FILE + ".bck"
NON_EXISTING_PROPERTY = "non.existing"

class PropertiesUtilTestCase(unittest.TestCase):
   """
   Unit tests for the "properties_util" module
   """

   def setUp(self):
      # Create "test.properties" in the current folder
      with open(PROPERTIES_FILE, "w") as fp:
         fp.write(PROPERTIES_FILE_CONTENTS)

   def tearDown(self):
      if os.path.exists(PROPERTIES_FILE):
         os.remove(PROPERTIES_FILE)

      if os.path.exists(PROPERTIES_BCK_FILE):
         os.remove(PROPERTIES_BCK_FILE)

   def test_backup(self):
      """
      Test backing up the properties file
      """

      header = "# Automatic backup of %s\n\n" % PROPERTIES_FILE
      backup_file_path = module.backup(PROPERTIES_FILE)

      # Verify the result
      self.assertEqual(PROPERTIES_BCK_FILE, backup_file_path)
      self._assert_file_is_untouched()
      with open(PROPERTIES_BCK_FILE) as fp:
         content = fp.read()
         self.assertEqual(content, header + PROPERTIES_FILE_CONTENTS)

   def test_backup_overrides(self):
      """
      Test backing up the properties file overrides the old backup
      """

      module.backup(PROPERTIES_FILE)
      property_new_value = "46"
      module.replace(PROPERTIES_FILE,
                              PROPERTY_NAME,
                              property_new_value)
      module.backup(PROPERTIES_FILE)

      # Verify the result
      bck_value = module.value(PROPERTIES_BCK_FILE, PROPERTY_NAME)
      self.assertEqual(property_new_value, bck_value)

   def test_add(self):
      """
      Test adding a property
      """

      property_new_value = "46"
      property_new_key = "new.property"

      has_been_added = module.add(PROPERTIES_FILE,
                                           property_new_key,
                                           property_new_value)

      added_value = module.value(PROPERTIES_FILE, property_new_key)
      self.assertEqual(added_value, property_new_value)
      self.assertTrue(has_been_added)
      self._assert_the_other_property_is_untouched()

   def test_skip_adding_existing_property(self):
      """
      Test adding an already existing property
      """

      has_been_added = module.add(PROPERTIES_FILE,
                                           PROPERTY_NAME,
                                           "46")

      # Verify the result
      self._assert_file_is_untouched()
      self.assertFalse(has_been_added)

   def test_delete(self):
      """
      Test deleting a property
      """

      has_been_deleted = module.delete(PROPERTIES_FILE, PROPERTY_NAME)

      # Verify the result
      deleted_value = module.value(PROPERTIES_FILE, PROPERTY_NAME)
      self.assertIsNone(deleted_value)
      self.assertTrue(has_been_deleted)
      self._assert_the_other_property_is_untouched()

   def test_delete_non_existing(self):
      """
      Test deleting a property that's not there
      """

      has_been_deleted = module.delete(PROPERTIES_FILE,
                                                NON_EXISTING_PROPERTY)

      # Verify the result
      self._assert_file_is_untouched()
      self.assertFalse(has_been_deleted)

   def test_replace(self):
      """
      Test replacing a property's value
      """

      property_new_value = "46"
      has_been_replaced = module.replace(PROPERTIES_FILE,
                                                  PROPERTY_NAME,
                                                  property_new_value)

      # Verify the result
      self.assertTrue(has_been_replaced)

      #Verify the property is in its original place and the value has changed
      with open(PROPERTIES_FILE) as fr:
         first_line = fr.readline()
         self.assertEqual(first_line,
                          "%s = %s\n" % (PROPERTY_NAME, property_new_value))

      self._assert_the_other_property_is_untouched()

   def test_replace_non_existing(self):
      """
      Test replacing a property that's not there
      """

      has_been_replaced = module.replace(PROPERTIES_FILE,
                                                  NON_EXISTING_PROPERTY,
                                                  "42")

      # Verify the result
      self._assert_file_is_untouched()
      self.assertFalse(has_been_replaced)

   def test_get_value(self):
      """
      Test retrieving a property's value
      """

      value = module.value(PROPERTIES_FILE, PROPERTY_NAME)

      # Verify the result
      self.assertEqual("42", value)

   def test_get_non_existing_property_value(self):
      """
      Test retrieving a non-existing property value
      """

      value = module.value(PROPERTIES_FILE, NON_EXISTING_PROPERTY)

      # Verify the result
      self.assertIsNone(value)

   def _assert_file_is_untouched(self):
      with open(PROPERTIES_FILE) as fp:
         content = fp.read()
         self.assertEqual(content, PROPERTIES_FILE_CONTENTS)

   def _assert_the_other_property_is_untouched(self):
      another_property_value = module.value(PROPERTIES_FILE,
                                                     "another.property")
      self.assertEqual("84", another_property_value)
