瀏覽代碼

AMBARI-8609: Enable ambari agent unit tests on Windows (Jayush Luniya)

Jayush Luniya 10 年之前
父節點
當前提交
4e6597059a

+ 12 - 5
ambari-agent/src/test/python/ambari_agent/TestActionQueue.py

@@ -37,6 +37,12 @@ from ambari_agent.CommandStatusDict import CommandStatusDict
 from ambari_agent.ActualConfigHandler import ActualConfigHandler
 from FileCache import FileCache
 from ambari_commons import OSCheck
+from only_for_platform import only_for_platform, get_platform, PLATFORM_LINUX, PLATFORM_WINDOWS
+
+if get_platform() != PLATFORM_WINDOWS:
+  os_distro_value = ('Suse','11','Final')
+else:
+  os_distro_value = ('win2012serverr2','6.3','WindowsServer')
 
 class TestActionQueue(TestCase):
   def setUp(self):
@@ -275,7 +281,7 @@ class TestActionQueue(TestCase):
     actionQueue.process_command(execution_command)
     self.assertTrue(print_exc_mock.called)
 
-  @patch.object(OSCheck, "os_distribution", new = MagicMock(return_value = ('Suse','11','Final')))
+  @patch.object(OSCheck, "os_distribution", new = MagicMock(return_value = os_distro_value))
   @patch("__builtin__.open")
   @patch.object(ActionQueue, "status_update_callback")
   def test_execute_command(self, status_update_callback_mock, open_mock):
@@ -326,9 +332,9 @@ class TestActionQueue(TestCase):
       if len(report['reports']) != 0:
         break
     expected = {'status': 'IN_PROGRESS',
-                'stderr': 'Read from {0}/errors-3.txt'.format(tempdir),
-                'stdout': 'Read from {0}/output-3.txt'.format(tempdir),
-                'structuredOut' : 'Read from {0}/structured-out-3.json'.format(tempdir),
+                'stderr': 'Read from {0}'.format(os.path.join(tempdir, "errors-3.txt")),
+                'stdout': 'Read from {0}'.format(os.path.join(tempdir, "output-3.txt")),
+                'structuredOut' : 'Read from {0}'.format(os.path.join(tempdir, "structured-out-3.json")),
                 'clusterName': u'cc',
                 'roleCommand': u'INSTALL',
                 'serviceName': u'HDFS',
@@ -648,7 +654,8 @@ class TestActionQueue(TestCase):
     
     report = actionQueue.result()
     self.assertEqual(len(report['reports']),1)
-      
+
+  @only_for_platform(PLATFORM_LINUX)
   @patch.object(CustomServiceOrchestrator, "resolve_script_path")
   @patch.object(StackVersionsFileHandler, "read_stack_version")
   def test_execute_python_executor(self, read_stack_version_mock, resolve_script_path_mock):

+ 11 - 2
ambari-agent/src/test/python/ambari_agent/TestController.py

@@ -28,14 +28,23 @@ import logging
 import platform
 from threading import Event
 import json
+from ambari_commons import OSCheck
+from only_for_platform import only_for_platform, get_platform, PLATFORM_LINUX, PLATFORM_WINDOWS
 
-with patch("platform.linux_distribution", return_value = ('Suse','11','Final')):
+if get_platform() != PLATFORM_WINDOWS:
+  os_distro_value = ('Suse','11','Final')
+else:
+  os_distro_value = ('win2012serverr2','6.3','WindowsServer')
+
+with patch.object(OSCheck, "os_distribution", new = MagicMock(return_value = os_distro_value)):
   from ambari_agent import Controller, ActionQueue, Register
   from ambari_agent import hostname
   from ambari_agent.Controller import AGENT_AUTO_RESTART_EXIT_CODE
   from ambari_commons import OSCheck
+  import ambari_commons
 
-@patch.object(platform, "linux_distribution", new = ('Suse','11','Final'))
+@only_for_platform(PLATFORM_LINUX)
+@patch.object(OSCheck, "os_distribution", new = os_distro_value)
 class TestController(unittest.TestCase):
 
   logger = logging.getLogger()

+ 17 - 11
ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py

@@ -41,6 +41,7 @@ from FileCache import FileCache
 from LiveStatus import LiveStatus
 from BackgroundCommandExecutionHandle import BackgroundCommandExecutionHandle
 from ambari_agent.ActionQueue import ActionQueue
+from only_for_platform import get_platform, PLATFORM_WINDOWS
 
 
 class TestCustomServiceOrchestrator(TestCase):
@@ -114,7 +115,8 @@ class TestCustomServiceOrchestrator(TestCase):
     json_file = orchestrator.dump_command_to_json(command)
     self.assertTrue(os.path.exists(json_file))
     self.assertTrue(os.path.getsize(json_file) > 0)
-    self.assertEqual(oct(os.stat(json_file).st_mode & 0777), '0600')
+    if get_platform() != PLATFORM_WINDOWS:
+      self.assertEqual(oct(os.stat(json_file).st_mode & 0777), '0600')
     self.assertTrue(json_file.endswith("command-3.json"))
     self.assertTrue(decompress_cluster_host_info_mock.called)
     os.unlink(json_file)
@@ -124,7 +126,8 @@ class TestCustomServiceOrchestrator(TestCase):
     json_file = orchestrator.dump_command_to_json(command)
     self.assertTrue(os.path.exists(json_file))
     self.assertTrue(os.path.getsize(json_file) > 0)
-    self.assertEqual(oct(os.stat(json_file).st_mode & 0777), '0600')
+    if get_platform() != PLATFORM_WINDOWS:
+      self.assertEqual(oct(os.stat(json_file).st_mode & 0777), '0600')
     self.assertTrue(json_file.endswith("status_command.json"))
     self.assertFalse(decompress_cluster_host_info_mock.called)
     os.unlink(json_file)
@@ -143,13 +146,13 @@ class TestCustomServiceOrchestrator(TestCase):
     # Testing existing path
     exists_mock.return_value = True
     path = orchestrator.\
-      resolve_script_path("/HBASE/package", "scripts/hbase_master.py", "PYTHON")
-    self.assertEqual("/HBASE/package/scripts/hbase_master.py", path)
+      resolve_script_path(os.path.join("HBASE", "package"), os.path.join("scripts", "hbase_master.py"), "PYTHON")
+    self.assertEqual(os.path.join("HBASE", "package", "scripts", "hbase_master.py"), path)
     # Testing not existing path
     exists_mock.return_value = False
     try:
       orchestrator.resolve_script_path("/HBASE",
-                                       "scripts/hbase_master.py", "PYTHON")
+                                       os.path.join("scripts", "hbase_master.py"), "PYTHON")
       self.fail('ExpectedException not thrown')
     except AgentException:
       pass # Expected
@@ -314,8 +317,11 @@ class TestCustomServiceOrchestrator(TestCase):
     self.assertFalse(command['taskId'] in orchestrator.commands_in_progress.keys())
     self.assertTrue(os.path.exists(out))
     self.assertTrue(os.path.exists(err))
-    os.remove(out)
-    os.remove(err)
+    try:
+      os.remove(out)
+      os.remove(err)
+    except:
+      pass
 
   from ambari_agent.StackVersionsFileHandler import StackVersionsFileHandler
 
@@ -437,13 +443,13 @@ class TestCustomServiceOrchestrator(TestCase):
     self.assertEqual(res1, None)
     # Testing existing hook script
     isfile_mock.return_value = True
-    res2 = orchestrator.resolve_hook_script_path("/hooks_dir/", "prefix", "command",
+    res2 = orchestrator.resolve_hook_script_path("hooks_dir", "prefix", "command",
                                             "script_type")
-    self.assertEqual(res2, ('/hooks_dir/prefix-command/scripts/hook.py',
-                            '/hooks_dir/prefix-command'))
+    self.assertEqual(res2, (os.path.join('hooks_dir', 'prefix-command', 'scripts', 'hook.py'),
+                            os.path.join('hooks_dir', 'prefix-command')))
     # Testing not existing hook script
     isfile_mock.return_value = False
-    res3 = orchestrator.resolve_hook_script_path("/hooks_dir/", "prefix", "command",
+    res3 = orchestrator.resolve_hook_script_path("hooks_dir", "prefix", "command",
                                                  "script_type")
     self.assertEqual(res3, None)
 

+ 12 - 13
ambari-agent/src/test/python/ambari_agent/TestDataCleaner.py

@@ -23,21 +23,21 @@ import unittest
 from mock.mock import patch, MagicMock, call, Mock
 from ambari_agent import DataCleaner
 import AmbariConfig
-
+import os
 
 class TestDataCleaner(unittest.TestCase):
 
   def setUp(self):
-    self.test_dir = [('/test_path', [],
+    self.test_dir = [('test_path', [],
                       ['errors-12.txt', 'output-12.txt', 'site-12.pp', 'site-13.pp', 'site-15.pp',
                        'structured-out-13.json', 'command-13.json', 'version'])]
     self.config = MagicMock()
-    self.config.get.side_effect = [2592000, (3600 + 1), 10000, "/test_path"]
+    self.config.get.side_effect = [2592000, (3600 + 1), 10000, "test_path"]
     DataCleaner.logger = MagicMock()
 
   def test_init_success(self):
     config = MagicMock()
-    config.get.side_effect = [2592000, (3600 + 1), 10000, "/test_path"]
+    config.get.side_effect = [2592000, (3600 + 1), 10000, "test_path"]
     DataCleaner.logger.reset_mock()
     cleaner = DataCleaner.DataCleaner(config)
     self.assertFalse(DataCleaner.logger.warn.called)
@@ -59,7 +59,7 @@ class TestDataCleaner(unittest.TestCase):
 
   def test_init_warn(self):
     config = MagicMock()
-    config.get.side_effect = [1, (3600 - 1), (10000 + 1), "/test_path"]
+    config.get.side_effect = [1, (3600 - 1), (10000 + 1), "test_path"]
     DataCleaner.logger.reset_mock()
     cleaner = DataCleaner.DataCleaner(config)
     self.assertTrue(DataCleaner.logger.warn.called)
@@ -85,12 +85,12 @@ class TestDataCleaner(unittest.TestCase):
     cleaner.cleanup()
 
     self.assertTrue(len(remMock.call_args_list) == 6)
-    remMock.assert_any_call('/test_path/errors-12.txt')
-    remMock.assert_any_call('/test_path/output-12.txt')
-    remMock.assert_any_call('/test_path/site-12.pp')
-    remMock.assert_any_call('/test_path/site-15.pp')
-    remMock.assert_any_call('/test_path/structured-out-13.json')
-    remMock.assert_any_call('/test_path/command-13.json')
+    remMock.assert_any_call(os.path.join('test_path', 'errors-12.txt'))
+    remMock.assert_any_call(os.path.join('test_path', 'output-12.txt'))
+    remMock.assert_any_call(os.path.join('test_path', 'site-12.pp'))
+    remMock.assert_any_call(os.path.join('test_path', 'site-15.pp'))
+    remMock.assert_any_call(os.path.join('test_path', 'structured-out-13.json'))
+    remMock.assert_any_call(os.path.join('test_path', 'command-13.json'))
     pass
 
   @patch('os.walk')
@@ -108,11 +108,10 @@ class TestDataCleaner(unittest.TestCase):
     sizeMock.return_value = 100
 
     def side_effect(arg):
-      if arg == '/test_path/site-15.pp':
+      if arg == os.path.join('test_path', 'site-15.pp'):
         raise Exception("Can't remove file")
 
     remMock.side_effect = side_effect
-
     cleaner = DataCleaner.DataCleaner(self.config)
     cleaner.cleanup()
 

+ 19 - 22
ambari-agent/src/test/python/ambari_agent/TestFileCache.py

@@ -64,15 +64,15 @@ class TestFileCache(TestCase):
     fileCache = FileCache(self.config)
     command = {
       'commandParams' : {
-        'service_package_folder' : 'stacks/HDP/2.1.1/services/ZOOKEEPER/package'
+        'service_package_folder' : os.path.join('stacks', 'HDP', '2.1.1', 'services', 'ZOOKEEPER', 'package')
       }
     }
     res = fileCache.get_service_base_dir(command, "server_url_pref")
     self.assertEquals(
       pprint.pformat(provide_directory_mock.call_args_list[0][0]),
       "('/var/lib/ambari-agent/cache',\n "
-      "'stacks/HDP/2.1.1/services/ZOOKEEPER/package',\n"
-      " 'server_url_pref')")
+      "{0},\n"
+      " 'server_url_pref')".format(pprint.pformat(os.path.join('stacks', 'HDP', '2.1.1', 'services', 'ZOOKEEPER', 'package'))))
     self.assertEquals(res, "dummy value")
 
 
@@ -91,7 +91,7 @@ class TestFileCache(TestCase):
     # Check existing dir case
     command = {
       'commandParams' : {
-        'hooks_folder' : 'HDP/2.1.1/hooks'
+        'hooks_folder' : os.path.join('HDP', '2.1.1', 'hooks')
       }
     }
     provide_directory_mock.return_value = "dummy value"
@@ -100,8 +100,8 @@ class TestFileCache(TestCase):
     self.assertEquals(
       pprint.pformat(provide_directory_mock.call_args_list[0][0]),
       "('/var/lib/ambari-agent/cache', "
-      "'stacks/HDP/2.1.1/hooks', "
-      "'server_url_pref')")
+      "{0}, "
+      "'server_url_pref')".format(pprint.pformat(os.path.join('stacks','HDP', '2.1.1', 'hooks'))))
     self.assertEquals(res, "dummy value")
 
 
@@ -134,7 +134,7 @@ class TestFileCache(TestCase):
 
     # Test uptodate dirs after start
     self.assertFalse(fileCache.uptodate_paths)
-
+    path = os.path.join("cache_path", "subdirectory")
     # Test initial downloading (when dir does not exist)
     fetch_url_mock.return_value = membuffer
     read_hash_sum_mock.return_value = "hash2"
@@ -144,8 +144,8 @@ class TestFileCache(TestCase):
     self.assertTrue(write_hash_sum_mock.called)
     self.assertEquals(fetch_url_mock.call_count, 2)
     self.assertEquals(pprint.pformat(fileCache.uptodate_paths),
-                     "['cache_path/subdirectory']")
-    self.assertEquals(res, 'cache_path/subdirectory')
+                      pprint.pformat([path]))
+    self.assertEquals(res, path)
 
     fetch_url_mock.reset_mock()
     write_hash_sum_mock.reset_mock()
@@ -162,9 +162,10 @@ class TestFileCache(TestCase):
     self.assertFalse(invalidate_directory_mock.called)
     self.assertFalse(write_hash_sum_mock.called)
     self.assertEquals(fetch_url_mock.call_count, 1)
+
     self.assertEquals(pprint.pformat(fileCache.uptodate_paths),
-                      "['cache_path/subdirectory']")
-    self.assertEquals(res, 'cache_path/subdirectory')
+                      pprint.pformat([path]))
+    self.assertEquals(res, path)
 
     fetch_url_mock.reset_mock()
     write_hash_sum_mock.reset_mock()
@@ -178,8 +179,8 @@ class TestFileCache(TestCase):
     self.assertFalse(write_hash_sum_mock.called)
     self.assertEquals(fetch_url_mock.call_count, 0)
     self.assertEquals(pprint.pformat(fileCache.uptodate_paths),
-                      "['cache_path/subdirectory']")
-    self.assertEquals(res, 'cache_path/subdirectory')
+                      pprint.pformat([path]))
+    self.assertEquals(res, path)
 
     # Check exception handling when tolerance is disabled
     self.config.set('agent', 'tolerate_download_failures', "false")
@@ -213,7 +214,7 @@ class TestFileCache(TestCase):
     fileCache = FileCache(self.config)
     res = fileCache.provide_directory("cache_path", "subdirectory",
                                   "server_url_prefix")
-    self.assertEquals(res, 'cache_path/subdirectory')
+    self.assertEquals(res, path)
 
 
   def test_build_download_url(self):
@@ -322,15 +323,11 @@ class TestFileCache(TestCase):
 
   def test_unpack_archive(self):
     tmpdir = tempfile.mkdtemp()
-    dummy_archive = os.path.join("ambari_agent", "dummy_files",
+    dummy_archive_name = os.path.join("ambari_agent", "dummy_files",
                                  "dummy_archive.zip")
-    # Test normal flow
-    with open(dummy_archive, "r") as f:
-      data = f.read(os.path.getsize(dummy_archive))
-      membuf = StringIO.StringIO(data)
-
+    archive_file = open(dummy_archive_name, "rb")
     fileCache = FileCache(self.config)
-    fileCache.unpack_archive(membuf, tmpdir)
+    fileCache.unpack_archive(archive_file, tmpdir)
     # Count summary size of unpacked files:
     total_size = 0
     total_files = 0
@@ -350,7 +347,7 @@ class TestFileCache(TestCase):
     with patch("os.path.isdir") as isdir_mock:
       isdir_mock.side_effect = self.exc_side_effect
       try:
-        fileCache.unpack_archive(membuf, tmpdir)
+        fileCache.unpack_archive(archive_file, tmpdir)
         self.fail('CachingException not thrown')
       except CachingException:
         pass # Expected

+ 3 - 3
ambari-agent/src/test/python/ambari_agent/TestGrep.py

@@ -52,7 +52,7 @@ err: /Stage[main]//Exec[command_good]/returns: change from notrun to 0 failed: w
 debug: /Schedule[weekly]: Skipping device resources because running on a host
 debug: /Schedule[puppet]: Skipping device resources because running on a host
 debug: Finishing transaction 70171639726240
-""".strip()
+""".replace("\n", os.linesep).strip()
     self.assertEquals(fragment, desired, "Grep grep function should return only last 3 lines of file")
 
   def test_grep_no_result(self):
@@ -82,7 +82,7 @@ debug: Finishing transaction 70171639726240
 debug: Finishing transaction 70060456663980
 debug: Received report to process from ambari-dmi
 debug: Processing report from ambari-dmi with processor Puppet::Reports::Store
-""".strip()
+""".replace("\n", os.linesep).strip()
     self.assertEquals(fragment, desired, "Grep tail function should return only last 3 lines of file")
 
   def test_tail_no_lines(self):
@@ -104,7 +104,7 @@ debug: Processing report from ambari-dmi with processor Puppet::Reports::Store
 info: Applying configuration version '1352127563'
 err: /Stage[main]//Exec[command_good]/returns: change from notrun to 0 failed: wget e432423423xample.com/badurl444111 returned 4 instead of one of [0] at /root/puppet-learn/2-bad.pp:5
 notice: Finished catalog run in 0.23 seconds
-""".strip()
+""".replace("\n", os.linesep).strip()
     self.assertEquals(fragment, desired, 'Grep cleanByTemplate function should return string without debug lines.')
 
 

+ 2 - 0
ambari-agent/src/test/python/ambari_agent/TestHardware.py

@@ -22,6 +22,7 @@ from unittest import TestCase
 from mock.mock import patch
 import unittest
 import platform
+from only_for_platform import only_for_platform, PLATFORM_LINUX
 
 with patch("platform.linux_distribution", return_value = ('Suse','11','Final')):
   from ambari_agent import hostname
@@ -29,6 +30,7 @@ with patch("platform.linux_distribution", return_value = ('Suse','11','Final')):
   from ambari_agent.Facter import Facter, FacterLinux
   from ambari_commons import OSCheck
 
+@only_for_platform(PLATFORM_LINUX)
 @patch.object(platform,"linux_distribution", new = ('Suse','11','Final'))
 class TestHardware(TestCase):
   @patch.object(OSCheck, "get_os_type")

+ 2 - 0
ambari-agent/src/test/python/ambari_agent/TestHeartbeat.py

@@ -36,7 +36,9 @@ with patch("platform.linux_distribution", return_value = ('Suse','11','Final')):
   from ambari_agent.StackVersionsFileHandler import StackVersionsFileHandler
   from ambari_agent.HostInfo import HostInfoLinux
 
+from only_for_platform import only_for_platform, PLATFORM_LINUX
 
+@only_for_platform(PLATFORM_LINUX)
 class TestHeartbeat(TestCase):
 
   def setUp(self):

+ 3 - 0
ambari-agent/src/test/python/ambari_agent/TestHostCleanup.py

@@ -67,6 +67,9 @@ pkg_list = sqoop.noarch,hadoop-libhdfs.x86_64,rrdtool.x86_64,ganglia-gmond.x86_6
 [metadata]
 created = 2013-07-02 20:39:22.162757"""
 
+from only_for_platform import only_for_platform, PLATFORM_LINUX
+
+@only_for_platform(PLATFORM_LINUX)
 class TestHostCleanup(TestCase):
 
   def setUp(self):

+ 42 - 14
ambari-agent/src/test/python/ambari_agent/TestHostInfo.py

@@ -24,12 +24,21 @@ import logging
 import unittest
 import subprocess
 import socket
+import platform
 from mock.mock import patch
 from mock.mock import MagicMock
 from mock.mock import create_autospec
 import ambari_commons
+from ambari_commons import OSCheck
+import os
+from only_for_platform import only_for_platform, get_platform, PLATFORM_WINDOWS, PLATFORM_LINUX
 
-with patch("platform.linux_distribution", return_value = ('redhat','11','Final')):
+if get_platform() != PLATFORM_WINDOWS:
+  os_distro_value = ('Suse','11','Final')
+else:
+  os_distro_value = ('win2012serverr2','6.3','WindowsServer')
+
+with patch.object(OSCheck, "os_distribution", new = MagicMock(return_value = os_distro_value)):
   from ambari_agent.HostCheckReportFileHandler import HostCheckReportFileHandler
   from ambari_agent.PackagesAnalyzer import PackagesAnalyzer
   from ambari_agent.HostInfo import HostInfo, HostInfoLinux
@@ -39,10 +48,13 @@ with patch("platform.linux_distribution", return_value = ('redhat','11','Final')
   from ambari_commons import OSCheck, Firewall, FirewallChecks ,OSConst
   import ambari_commons
 
-@patch.object(System, "os_family", new = 'redhat')
-@patch.object(OSCheck, "os_distribution", new = MagicMock(return_value = ('redhat','11','Final')))
+
+
+
+@patch.object(OSCheck, "os_distribution", new = MagicMock(return_value = os_distro_value))
 class TestHostInfo(TestCase):
 
+  @only_for_platform(PLATFORM_LINUX)
   @patch.object(OSCheck, 'get_os_family')
   @patch.object(PackagesAnalyzer, 'subprocessWithTimeout')
   def test_analyze_zypper_out(self, spwt_mock, get_os_family_mock):
@@ -74,6 +86,7 @@ class TestHostInfo(TestCase):
     self.assertTrue(installedPackages[3][2], "HDP")
     self.assertTrue(installedPackages[6][1], "11-38.13.9")
 
+  @only_for_platform(PLATFORM_LINUX)
   def test_getReposToRemove(self):
     l1 = ["Hortonworks Data Platform Utils Version - HDP-UTILS-1.1.0.15", "Ambari 1.x", "HDP"]
     l2 = ["Ambari", "HDP-UTIL"]
@@ -87,6 +100,7 @@ class TestHostInfo(TestCase):
     self.assertTrue(1, len(l3))
     self.assertEqual(l3[0], "HDP-1.3.0")
 
+  @only_for_platform(PLATFORM_LINUX)
   def test_perform_package_analysis(self):
     packageAnalyzer = PackagesAnalyzer()
     installedPackages = [
@@ -134,6 +148,7 @@ class TestHostInfo(TestCase):
     for package in expected:
       self.assertTrue(package in allPackages)
 
+  @only_for_platform(PLATFORM_LINUX)
   @patch.object(OSCheck, 'get_os_family')
   @patch.object(PackagesAnalyzer, 'subprocessWithTimeout')
   def test_analyze_yum_output(self, subprocessWithTimeout_mock, get_os_family_mock):
@@ -190,11 +205,12 @@ class TestHostInfo(TestCase):
                                               "koji-override-0/$releasever"])
       self.assertFalse(package['repoName'] in ["AMBARI.dev-1.x"])
 
+  @only_for_platform(PLATFORM_LINUX)
   @patch.object(OSCheck, 'get_os_family')
   @patch.object(PackagesAnalyzer, 'subprocessWithTimeout')
   def test_analyze_yum_output_err(self, subprocessWithTimeout_mock, get_os_family_mock):
     get_os_family_mock.return_value = OSConst.REDHAT_FAMILY
-    
+
     packageAnalyzer = PackagesAnalyzer()
 
     result = {}
@@ -211,15 +227,19 @@ class TestHostInfo(TestCase):
   @patch('os.path.exists')
   def test_checkFolders(self, path_mock):
     path_mock.return_value = True
-    hostInfo = HostInfoLinux()
+    hostInfo = HostInfo()
     results = []
-    existingUsers = [{'name':'a1', 'homeDir':'/home/a1'}, {'name':'b1', 'homeDir':'/home/b1'}]
-    hostInfo.checkFolders(["/etc/conf", "/var/lib", "/home/"], ["a1", "b1"], existingUsers, results)
+    existingUsers = [{'name':'a1', 'homeDir':os.path.join('home', 'a1')}, {'name':'b1', 'homeDir':os.path.join('home', 'b1')}]
+    hostInfo.checkFolders([os.path.join("etc", "conf"), os.path.join("var", "lib"), "home"], ["a1", "b1"], existingUsers, results)
+    print results
     self.assertEqual(4, len(results))
     names = [i['name'] for i in results]
-    for item in ['/etc/conf/a1', '/var/lib/a1', '/etc/conf/b1', '/var/lib/b1']:
+    for item in [os.path.join('etc','conf','a1'), os.path.join('var','lib','a1'), os.path.join('etc','conf','b1'), os.path.join('var','lib','b1')]:
+
       self.assertTrue(item in names)
 
+  @only_for_platform(PLATFORM_LINUX)
+  @patch.object(OSCheck, "os_distribution", new = MagicMock(return_value = os_distro_value))
   @patch('os.path.exists')
   @patch('__builtin__.open')
   def test_checkUsers(self, builtins_open_mock, path_mock):
@@ -241,6 +261,7 @@ class TestHostInfo(TestCase):
     self.assertTrue(newlist[1]['status'], "Invalid home directory")
     print(path_mock.mock_calls)
 
+  @only_for_platform(PLATFORM_LINUX)
   @patch.object(OSCheck, "get_os_type")
   @patch('os.umask')
   @patch.object(HostCheckReportFileHandler, 'writeHostCheckFile')
@@ -283,7 +304,7 @@ class TestHostInfo(TestCase):
     self.assertTrue(0 < len(dict['installedPackages']))
     self.assertTrue('agentTimeStampAtReporting' in dict['hostHealth'])
 
-
+  @only_for_platform(PLATFORM_LINUX)
   @patch.object(OSCheck, "get_os_type")
   @patch('os.umask')
   @patch.object(HostCheckReportFileHandler, 'writeHostCheckFile')
@@ -386,7 +407,7 @@ class TestHostInfo(TestCase):
     result = host.dirType("/home")
     self.assertEquals(result, 'unknown')
 
-
+  @only_for_platform(PLATFORM_LINUX)
   @patch("os.path.exists")
   @patch("glob.glob")
   def test_hadoopVarRunCount(self, glob_glob_mock, os_path_exists_mock):
@@ -401,7 +422,7 @@ class TestHostInfo(TestCase):
     result = hostInfo.hadoopVarRunCount()
     self.assertEquals(result, 0)
 
-
+  @only_for_platform(PLATFORM_LINUX)
   @patch("os.path.exists")
   @patch("glob.glob")
   def test_hadoopVarLogCount(self, glob_glob_mock, os_path_exists_mock):
@@ -416,6 +437,8 @@ class TestHostInfo(TestCase):
     result = hostInfo.hadoopVarLogCount()
     self.assertEquals(result, 0)
 
+  @only_for_platform(PLATFORM_LINUX)
+  @patch.object(OSCheck, "os_distribution", new = MagicMock(return_value = ('redhat','11','Final')))
   @patch("os.listdir", create=True, autospec=True)
   @patch("__builtin__.open", create=True, autospec=True)
   @patch("pwd.getpwuid", create=True, autospec=True)
@@ -436,7 +459,7 @@ class TestHostInfo(TestCase):
     self.assertTrue(list[0]['hadoop'])
     self.assertEquals(list[0]['user'], 'user')
 
-
+  @only_for_platform(PLATFORM_LINUX)
   @patch("subprocess.Popen")
   @patch.object(Hardware, 'extractMountInfo')
   def test_osdiskAvailableSpace(self, extract_mount_info_mock, subproc_popen_mock):
@@ -454,7 +477,7 @@ class TestHostInfo(TestCase):
 
     self.assertEquals(result, {})
 
-
+  @only_for_platform(PLATFORM_LINUX)
   @patch.object(OSCheck, "get_os_type")
   @patch("subprocess.Popen")
   def test_checkLiveServices(self, subproc_popen, get_os_type_method):
@@ -498,6 +521,8 @@ class TestHostInfo(TestCase):
     self.assertEquals(result[0]['name'], 'service1')
     self.assertTrue(len(result[0]['desc']) > 0)
 
+  @only_for_platform(PLATFORM_LINUX)
+  @patch.object(OSCheck, "os_distribution", new = MagicMock(return_value = ('redhat','11','Final')))
   @patch("os.path.exists")
   @patch("os.listdir", create=True, autospec=True)
   @patch("os.path.islink")
@@ -519,6 +544,7 @@ class TestHostInfo(TestCase):
     self.assertEquals(result[0]['name'], 'config1')
     self.assertEquals(result[0]['target'], 'real_path_to_conf')
 
+  @only_for_platform(PLATFORM_LINUX)
   @patch.object(OSCheck, "get_os_family")
   @patch.object(OSCheck, "get_os_type")
   @patch.object(OSCheck, "get_os_major_version")
@@ -554,7 +580,7 @@ class TestHostInfo(TestCase):
 
     self.assertFalse(hostInfo.checkReverseLookup())
 
-
+  @only_for_platform(PLATFORM_LINUX)
   @patch.object(OSCheck, "get_os_family")
   @patch.object(OSCheck, "get_os_type")
   @patch.object(OSCheck, "get_os_major_version")
@@ -565,6 +591,8 @@ class TestHostInfo(TestCase):
     run_os_command_mock.return_value = 3, "", ""
     self.assertFalse(Firewall().getFirewallObject().check_iptables())
 
+  @only_for_platform(PLATFORM_LINUX)
+  @patch.object(OSCheck, "os_distribution", new = MagicMock(return_value = ('redhat','11','Final')))
   @patch("os.path.isfile")
   @patch('__builtin__.open')
   def test_transparent_huge_page(self, open_mock, os_path_isfile_mock):

+ 3 - 0
ambari-agent/src/test/python/ambari_agent/TestHostname.py

@@ -27,6 +27,7 @@ import tempfile
 import shutil
 import os, pprint, json,stat
 from mock.mock import patch
+from only_for_platform import only_for_platform, PLATFORM_LINUX
 
 class TestHostname(TestCase):
 
@@ -38,6 +39,7 @@ class TestHostname(TestCase):
                       "hostname should equal the socket-based hostname")
     pass
 
+  @only_for_platform(PLATFORM_LINUX)
   def test_hostname_override(self):
     hostname.cached_hostname = None
     hostname.cached_public_hostname = None
@@ -60,6 +62,7 @@ class TestHostname(TestCase):
       config.remove_option('agent', 'hostname_script')
     pass
 
+  @only_for_platform(PLATFORM_LINUX)
   def test_public_hostname_override(self):
     hostname.cached_hostname = None
     hostname.cached_public_hostname = None

+ 24 - 13
ambari-agent/src/test/python/ambari_agent/TestMain.py

@@ -25,19 +25,27 @@ import signal
 import os
 import socket
 import tempfile
+import platform
 import ConfigParser
-
+from ambari_commons import OSCheck
+from only_for_platform import only_for_platform, get_platform, PLATFORM_WINDOWS, PLATFORM_LINUX
 from mock.mock import MagicMock, patch, ANY, Mock
 
-with patch("platform.linux_distribution", return_value = ('Suse','11','Final')):
+if get_platform() != PLATFORM_WINDOWS:
+  os_distro_value = ('Suse','11','Final')
+else:
+  os_distro_value = ('win2012serverr2','6.3','WindowsServer')
+
+with patch.object(OSCheck, "os_distribution", new = MagicMock(return_value = os_distro_value)):
   from ambari_agent import NetUtil, security
   from ambari_agent import ProcessHelper, main
-  from ambari_agent import ProcessHelper, main
   from ambari_agent.AmbariConfig import AmbariConfig
   from ambari_agent.PingPortListener import PingPortListener
   from ambari_agent.Controller import Controller
   from ambari_agent.DataCleaner import DataCleaner
   import ambari_agent.HeartbeatHandlers as HeartbeatHandlers
+  from ambari_commons.os_check import OSConst, OSCheck
+
   from ambari_agent.shell import shellRunner
 
 class TestMain(unittest.TestCase):
@@ -52,7 +60,7 @@ class TestMain(unittest.TestCase):
     # enable stdout
     sys.stdout = sys.__stdout__
 
-
+  @only_for_platform(PLATFORM_LINUX)
   @patch("ambari_agent.HeartbeatHandlers.HeartbeatStopHandlersLinux")
   @patch("os._exit")
   @patch("os.getpid")
@@ -119,7 +127,7 @@ class TestMain(unittest.TestCase):
     main.update_log_level(config)
     setLevel_mock.assert_called_with(logging.INFO)
 
-
+  @only_for_platform(PLATFORM_LINUX)
   @patch("signal.signal")
   def test_bind_signal_handlers(self, signal_mock):
     main.bind_signal_handlers(os.getpid())
@@ -162,11 +170,12 @@ class TestMain(unittest.TestCase):
 
     exit_mock.reset_mock()
 
-    # Trying case if there is another instance running
-    isfile_mock.return_value = True
-    isdir_mock.return_value = True
-    main.perform_prestart_checks(None)
-    self.assertTrue(exit_mock.called)
+    if OSCheck.get_os_family() != OSConst.WINSRV_FAMILY:
+      # Trying case if there is another instance running, only valid for linux
+      isfile_mock.return_value = True
+      isdir_mock.return_value = True
+      main.perform_prestart_checks(None)
+      self.assertTrue(exit_mock.called)
 
     isfile_mock.reset_mock()
     isdir_mock.reset_mock()
@@ -188,7 +197,7 @@ class TestMain(unittest.TestCase):
     main.perform_prestart_checks(None)
     self.assertFalse(exit_mock.called)
 
-
+  @only_for_platform(PLATFORM_LINUX)
   @patch("time.sleep")
   @patch.object(shellRunner,"run")
   @patch("os._exit")
@@ -303,10 +312,12 @@ class TestMain(unittest.TestCase):
 
     self.assertTrue(setup_logging_mock.called)
     self.assertTrue(bind_signal_handlers_mock.called)
-    self.assertTrue(stop_mock.called)
+    if OSCheck.get_os_family() != OSConst.WINSRV_FAMILY:
+      self.assertTrue(stop_mock.called)
     #self.assertTrue(resolve_ambari_config_mock.called)
     self.assertTrue(perform_prestart_checks_mock.called)
-    self.assertTrue(daemonize_mock.called)
+    if OSCheck.get_os_family() != OSConst.WINSRV_FAMILY:
+      self.assertTrue(daemonize_mock.called)
     self.assertTrue(update_log_level_mock.called)
     try_to_connect_mock.assert_called_once_with(ANY, -1, ANY)
     self.assertTrue(start_mock.called)

+ 2 - 2
ambari-agent/src/test/python/ambari_agent/TestNetUtil.py

@@ -22,7 +22,7 @@ from ambari_agent import NetUtil
 from mock.mock import MagicMock, patch
 import unittest
 import threading
-
+from only_for_platform import only_for_platform, PLATFORM_LINUX
 class TestNetUtil(unittest.TestCase):
 
   @patch("urlparse.urlparse")
@@ -50,7 +50,7 @@ class TestNetUtil(unittest.TestCase):
     httpsConMock.side_effect = Exception("test")
     self.assertFalse(netutil.checkURL("url")[0])
 
-
+  @only_for_platform(PLATFORM_LINUX)
   @patch("time.sleep")
   @patch.object(threading._Event, "wait")
   def test_try_to_connect(self, event_mock,

+ 2 - 1
ambari-agent/src/test/python/ambari_agent/TestProcessHelper.py

@@ -25,7 +25,8 @@ import unittest
 from mock.mock import patch, MagicMock
 from ambari_agent import ProcessHelper
 
-
+from only_for_platform import only_for_platform, PLATFORM_LINUX
+@only_for_platform(PLATFORM_LINUX)
 class TestProcessHelper(unittest.TestCase):
 
   @patch.object(ProcessHelper, "getTempFiles")

+ 6 - 1
ambari-agent/src/test/python/ambari_agent/TestPythonExecutor.py

@@ -104,7 +104,12 @@ class TestPythonExecutor(TestCase):
     executor = PythonExecutor("/tmp", AmbariConfig().getConfig())
     _, tmpoutfile = tempfile.mkstemp()
     _, tmperrfile = tempfile.mkstemp()
-    _, tmpstroutfile = tempfile.mkstemp()
+    # PythonExecutor need only filename and will try to delete this file before execution, this will fail on windows
+    # so we will use NamedTemporaryFile only to generate temp file and close it immediately after creation
+    tmp_file = tempfile.NamedTemporaryFile(delete=False)
+    tmpstroutfile = tmp_file.name
+    tmp_file.close()
+
     PYTHON_TIMEOUT_SECONDS =  5
 
     def launch_python_subprocess_method(command, tmpout, tmperr):

+ 3 - 0
ambari-agent/src/test/python/ambari_agent/TestRegistration.py

@@ -23,6 +23,7 @@ import os
 import tempfile
 from mock.mock import patch
 from mock.mock import MagicMock
+from only_for_platform import only_for_platform, PLATFORM_LINUX
 
 with patch("platform.linux_distribution", return_value = ('Suse','11','Final')):
   from ambari_agent.Register import Register
@@ -30,6 +31,8 @@ with patch("platform.linux_distribution", return_value = ('Suse','11','Final')):
   from ambari_commons import OSCheck, Firewall, FirewallChecks
 
 class TestRegistration(TestCase):
+
+  @only_for_platform(PLATFORM_LINUX)
   @patch.object(FirewallChecks, "run_os_command")
   @patch.object(OSCheck, "get_os_type")
   @patch.object(OSCheck, "get_os_version")

+ 8 - 6
ambari-agent/src/test/python/ambari_agent/TestSecurity.py

@@ -175,7 +175,7 @@ class TestSecurity(unittest.TestCase):
     self.config.set('security', 'keysdir', '/dummy-keysdir')
     man = CertificateManager(self.config)
     res = man.getAgentKeyName()
-    self.assertEquals(res, "/dummy-keysdir/dummy.hostname.key")
+    self.assertEquals(res, os.path.abspath("/dummy-keysdir/dummy.hostname.key"))
 
 
   @patch("ambari_agent.hostname.hostname")
@@ -184,7 +184,7 @@ class TestSecurity(unittest.TestCase):
     self.config.set('security', 'keysdir', '/dummy-keysdir')
     man = CertificateManager(self.config)
     res = man.getAgentCrtName()
-    self.assertEquals(res, "/dummy-keysdir/dummy.hostname.crt")
+    self.assertEquals(res, os.path.abspath("/dummy-keysdir/dummy.hostname.crt"))
 
 
   @patch("ambari_agent.hostname.hostname")
@@ -193,14 +193,14 @@ class TestSecurity(unittest.TestCase):
     self.config.set('security', 'keysdir', '/dummy-keysdir')
     man = CertificateManager(self.config)
     res = man.getAgentCrtReqName()
-    self.assertEquals(res, "/dummy-keysdir/dummy.hostname.csr")
+    self.assertEquals(res, os.path.abspath("/dummy-keysdir/dummy.hostname.csr"))
 
 
   def test_getSrvrCrtName(self):
     self.config.set('security', 'keysdir', '/dummy-keysdir')
     man = CertificateManager(self.config)
     res = man.getSrvrCrtName()
-    self.assertEquals(res, "/dummy-keysdir/ca.crt")
+    self.assertEquals(res, os.path.abspath("/dummy-keysdir/ca.crt"))
 
 
   @patch("os.path.exists")
@@ -265,8 +265,10 @@ class TestSecurity(unittest.TestCase):
     # Checking file contents
     saved = open(tmpoutfile, 'r').read()
     self.assertEqual(saved, read_mock.read.return_value)
-
-    os.unlink(tmpoutfile)
+    try:
+      os.unlink(tmpoutfile)
+    except:
+      pass
 
 
   @patch("ambari_agent.hostname.hostname")

+ 2 - 0
ambari-agent/src/test/python/ambari_agent/TestShell.py

@@ -27,8 +27,10 @@ from ambari_agent.AmbariConfig import AmbariConfig
 from ambari_agent import shell
 from shell import shellRunner
 from sys import platform as _platform
+from only_for_platform import only_for_platform, PLATFORM_LINUX
 import subprocess, time
 
+@only_for_platform(PLATFORM_LINUX)
 class TestShell(unittest.TestCase):
 
 

+ 13 - 4
ambari-agent/src/test/python/unitTests.py

@@ -23,6 +23,8 @@ import doctest
 from os.path import dirname, split, isdir
 import logging.handlers
 import logging
+import platform
+from only_for_platform import get_platform, PLATFORM_WINDOWS
 #TODO Add an option to randomize the tests' execution
 #from random import shuffle
 
@@ -30,6 +32,11 @@ LOG_FILE_NAME='tests.log'
 SELECTED_PREFIX = "_"
 PY_EXT='.py'
 
+if get_platform() == PLATFORM_WINDOWS:
+  IGNORE_FOLDERS = ["resource_management"]
+else:
+  IGNORE_FOLDERS = ["resource_management_windows"]
+
 class TestAgent(unittest.TestSuite):
   def run(self, result):
     run = unittest.TestSuite.run
@@ -54,7 +61,7 @@ def all_tests_suite():
   src_dir = os.getcwd()
   files_list = []
   for directory in os.listdir(src_dir):
-    if os.path.isdir(directory):
+    if os.path.isdir(directory) and not (directory in IGNORE_FOLDERS):
       files_list += os.listdir(src_dir + os.sep + directory)
   #TODO Add an option to randomize the tests' execution
   #shuffle(files_list)
@@ -77,7 +84,7 @@ def all_tests_suite():
   logger.info('------------------------------------------------------------------------')
 
   suite = unittest.TestLoader().loadTestsFromNames(tests_list)
-  return TestAgent([suite])
+  return unittest.TestSuite([suite])
 
 def main():
 
@@ -93,7 +100,10 @@ def main():
     logger.error('Python unit tests failed')
     logger.error('Find detailed logs in ' + path)
     logger.error('-----------------------------------------------------------------------')
-    exit(1)
+    if get_platform() == PLATFORM_WINDOWS:
+      os._exit(1)
+    else:
+      exit(1)
   else:
     logger.info('------------------------------------------------------------------------')
     logger.info('Python unit tests finished succesfully')
@@ -102,7 +112,6 @@ def main():
 if __name__ == '__main__':
   import os
   import sys
-  import io
   sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
   sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + os.sep + 'main' + os.sep + 'python')
   sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + os.sep + 'main' + os.sep + 'python' + os.sep + 'ambari_agent')

+ 35 - 0
ambari-common/src/test/python/only_for_platform.py

@@ -0,0 +1,35 @@
+"""
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Ambari Agent
+
+"""
+
+
+import platform
+
+PLATFORM_WINDOWS = "Windows"
+PLATFORM_LINUX = "Linux"
+
+def get_platform():
+  return platform.system()
+
+def only_for_platform(system):
+  def decorator(obj):
+    if platform.system() == system:
+      return obj
+  return decorator