254 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			254 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # -*- coding: utf-8; -*-
 | |
| 
 | |
| import sys
 | |
| from unittest import TestCase
 | |
| from unittest.mock import patch, MagicMock
 | |
| 
 | |
| # nb. setuptools must be imported before distutils, else weird
 | |
| # behavior may ensue within some of the tests below
 | |
| import setuptools
 | |
| 
 | |
| import pytest
 | |
| 
 | |
| from wuttjamaican import util
 | |
| 
 | |
| 
 | |
| class TestLoadEntryPoints(TestCase):
 | |
| 
 | |
|     def test_empty(self):
 | |
|         # empty set returned for unknown group
 | |
|         result = util.load_entry_points('this_should_never_exist!!!!!!')
 | |
|         self.assertEqual(result, {})
 | |
| 
 | |
|     def test_basic(self):
 | |
|         # load some entry points which should "always" be present,
 | |
|         # even in a testing environment.  basic sanity check
 | |
|         result = util.load_entry_points('console_scripts', ignore_errors=True)
 | |
|         self.assertTrue(len(result) >= 1)
 | |
|         self.assertIn('pip', result)
 | |
| 
 | |
|     def test_basic_pre_python_3_10(self):
 | |
| 
 | |
|         # the goal here is to get coverage for code which would only
 | |
|         # run on python 3,9 and older, but we only need that coverage
 | |
|         # if we are currently testing python 3.10+
 | |
|         if sys.version_info.major == 3 and sys.version_info.minor < 10:
 | |
|             pytest.skip("this test is not relevant before python 3.10")
 | |
| 
 | |
|         import importlib.metadata
 | |
|         real_entry_points = importlib.metadata.entry_points()
 | |
| 
 | |
|         class FakeEntryPoints(dict):
 | |
|             def get(self, group, default):
 | |
|                 return real_entry_points.select(group=group)
 | |
| 
 | |
|         importlib = MagicMock()
 | |
|         importlib.metadata.entry_points.return_value = FakeEntryPoints()
 | |
| 
 | |
|         with patch.dict('sys.modules', **{'importlib': importlib}):
 | |
| 
 | |
|             # load some entry points which should "always" be present,
 | |
|             # even in a testing environment.  basic sanity check
 | |
|             result = util.load_entry_points('console_scripts', ignore_errors=True)
 | |
|             self.assertTrue(len(result) >= 1)
 | |
|             self.assertIn('pip', result)
 | |
| 
 | |
|     def test_error(self):
 | |
| 
 | |
|         # skip if < 3.8
 | |
|         if sys.version_info.major == 3 and sys.version_info.minor < 8:
 | |
|             pytest.skip("this requires python 3.8 for entry points via importlib")
 | |
| 
 | |
|         entry_point = MagicMock()
 | |
|         entry_point.load.side_effect = NotImplementedError
 | |
| 
 | |
|         entry_points = MagicMock()
 | |
|         entry_points.select.return_value = [entry_point]
 | |
| 
 | |
|         importlib = MagicMock()
 | |
|         importlib.metadata.entry_points.return_value = entry_points
 | |
| 
 | |
|         with patch.dict('sys.modules', **{'importlib': importlib}):
 | |
| 
 | |
|             # empty set returned if errors suppressed
 | |
|             result = util.load_entry_points('wuttatest.thingers', ignore_errors=True)
 | |
|             self.assertEqual(result, {})
 | |
|             importlib.metadata.entry_points.assert_called_once_with()
 | |
|             entry_points.select.assert_called_once_with(group='wuttatest.thingers')
 | |
|             entry_point.load.assert_called_once_with()
 | |
| 
 | |
|             # error is raised, if not suppressed
 | |
|             importlib.metadata.entry_points.reset_mock()
 | |
|             entry_points.select.reset_mock()
 | |
|             entry_point.load.reset_mock()
 | |
|             self.assertRaises(NotImplementedError, util.load_entry_points, 'wuttatest.thingers')
 | |
|             importlib.metadata.entry_points.assert_called_once_with()
 | |
|             entry_points.select.assert_called_once_with(group='wuttatest.thingers')
 | |
|             entry_point.load.assert_called_once_with()
 | |
| 
 | |
|     def test_pkg_resources_empty(self):
 | |
|         orig_import = __import__
 | |
| 
 | |
|         def mock_import(name, *args, **kwargs):
 | |
|             if name == 'importlib.metadata':
 | |
|                 raise ImportError
 | |
|             return orig_import(name, *args, **kwargs)
 | |
| 
 | |
|         with patch('builtins.__import__', side_effect=mock_import):
 | |
| 
 | |
|             # empty set returned for unknown group
 | |
|             result = util.load_entry_points('this_should_never_exist!!!!!!')
 | |
|             self.assertEqual(result, {})
 | |
| 
 | |
|     def test_pkg_resources_basic(self):
 | |
|         orig_import = __import__
 | |
| 
 | |
|         def mock_import(name, *args, **kwargs):
 | |
|             if name == 'importlib.metadata':
 | |
|                 raise ImportError
 | |
|             return orig_import(name, *args, **kwargs)
 | |
| 
 | |
|         with patch('builtins.__import__', side_effect=mock_import):
 | |
| 
 | |
|             # load some entry points which should "always" be present,
 | |
|             # even in a testing environment.  basic sanity check
 | |
|             result = util.load_entry_points('console_scripts', ignore_errors=True)
 | |
|             self.assertTrue(len(result) >= 1)
 | |
|             self.assertIn('pip', result)
 | |
| 
 | |
|     def test_pkg_resources_error(self):
 | |
|         orig_import = __import__
 | |
| 
 | |
|         entry_point = MagicMock()
 | |
|         entry_point.load.side_effect = NotImplementedError
 | |
| 
 | |
|         iter_entry_points = MagicMock(return_value=[entry_point])
 | |
|         pkg_resources = MagicMock(iter_entry_points=iter_entry_points)
 | |
| 
 | |
|         def mock_import(name, *args, **kwargs):
 | |
|             if name == 'importlib.metadata':
 | |
|                 raise ImportError
 | |
|             return orig_import(name, *args, **kwargs)
 | |
| 
 | |
|         with patch('builtins.__import__', side_effect=mock_import):
 | |
|             with patch.dict('sys.modules', **{'pkg_resources': pkg_resources}):
 | |
| 
 | |
|                 # empty set returned if errors suppressed
 | |
|                 result = util.load_entry_points('wuttatest.thingers', ignore_errors=True)
 | |
|                 self.assertEqual(result, {})
 | |
|                 iter_entry_points.assert_called_once_with('wuttatest.thingers')
 | |
|                 entry_point.load.assert_called_once_with()
 | |
| 
 | |
|                 # error is raised, if not suppressed
 | |
|                 iter_entry_points.reset_mock()
 | |
|                 entry_point.load.reset_mock()
 | |
|                 self.assertRaises(NotImplementedError, util.load_entry_points, 'wuttatest.thingers')
 | |
|                 iter_entry_points.assert_called_once_with('wuttatest.thingers')
 | |
|                 entry_point.load.assert_called_once_with()
 | |
| 
 | |
| 
 | |
| class TestLoadObject(TestCase):
 | |
| 
 | |
|     def test_missing_spec(self):
 | |
|         self.assertRaises(ValueError, util.load_object, None)
 | |
| 
 | |
|     def test_basic(self):
 | |
|         result = util.load_object('unittest:TestCase')
 | |
|         self.assertIs(result, TestCase)
 | |
| 
 | |
| 
 | |
| class TestParseBool(TestCase):
 | |
| 
 | |
|     def test_null(self):
 | |
|         self.assertIsNone(util.parse_bool(None))
 | |
| 
 | |
|     def test_bool(self):
 | |
|         self.assertTrue(util.parse_bool(True))
 | |
|         self.assertFalse(util.parse_bool(False))
 | |
| 
 | |
|     def test_string_true(self):
 | |
|         self.assertTrue(util.parse_bool('true'))
 | |
|         self.assertTrue(util.parse_bool('yes'))
 | |
|         self.assertTrue(util.parse_bool('y'))
 | |
|         self.assertTrue(util.parse_bool('on'))
 | |
|         self.assertTrue(util.parse_bool('1'))
 | |
| 
 | |
|     def test_string_false(self):
 | |
|         self.assertFalse(util.parse_bool('false'))
 | |
|         self.assertFalse(util.parse_bool('no'))
 | |
|         self.assertFalse(util.parse_bool('n'))
 | |
|         self.assertFalse(util.parse_bool('off'))
 | |
|         self.assertFalse(util.parse_bool('0'))
 | |
|         # nb. assume false for unrecognized input
 | |
|         self.assertFalse(util.parse_bool('whatever-else'))
 | |
| 
 | |
| 
 | |
| class TestParseList(TestCase):
 | |
| 
 | |
|     def test_null(self):
 | |
|         value = util.parse_list(None)
 | |
|         self.assertIsInstance(value, list)
 | |
|         self.assertEqual(len(value), 0)
 | |
| 
 | |
|     def test_list_instance(self):
 | |
|         mylist = []
 | |
|         value = util.parse_list(mylist)
 | |
|         self.assertIs(value, mylist)
 | |
| 
 | |
|     def test_single_value(self):
 | |
|         value = util.parse_list('foo')
 | |
|         self.assertEqual(len(value), 1)
 | |
|         self.assertEqual(value[0], 'foo')
 | |
| 
 | |
|     def test_single_value_padded_by_spaces(self):
 | |
|         value = util.parse_list('   foo   ')
 | |
|         self.assertEqual(len(value), 1)
 | |
|         self.assertEqual(value[0], 'foo')
 | |
| 
 | |
|     def test_slash_is_not_a_separator(self):
 | |
|         value = util.parse_list('/dev/null')
 | |
|         self.assertEqual(len(value), 1)
 | |
|         self.assertEqual(value[0], '/dev/null')
 | |
| 
 | |
|     def test_multiple_values_separated_by_whitespace(self):
 | |
|         value = util.parse_list('foo bar baz')
 | |
|         self.assertEqual(len(value), 3)
 | |
|         self.assertEqual(value[0], 'foo')
 | |
|         self.assertEqual(value[1], 'bar')
 | |
|         self.assertEqual(value[2], 'baz')
 | |
| 
 | |
|     def test_multiple_values_separated_by_commas(self):
 | |
|         value = util.parse_list('foo,bar,baz')
 | |
|         self.assertEqual(len(value), 3)
 | |
|         self.assertEqual(value[0], 'foo')
 | |
|         self.assertEqual(value[1], 'bar')
 | |
|         self.assertEqual(value[2], 'baz')
 | |
| 
 | |
|     def test_multiple_values_separated_by_whitespace_and_commas(self):
 | |
|         value = util.parse_list('  foo,   bar   baz')
 | |
|         self.assertEqual(len(value), 3)
 | |
|         self.assertEqual(value[0], 'foo')
 | |
|         self.assertEqual(value[1], 'bar')
 | |
|         self.assertEqual(value[2], 'baz')
 | |
| 
 | |
|     def test_multiple_values_separated_by_whitespace_and_commas_with_some_quoting(self):
 | |
|         value = util.parse_list("""
 | |
|         foo
 | |
|         "C:\\some path\\with spaces\\and, a comma",
 | |
|         baz
 | |
|         """)
 | |
|         self.assertEqual(len(value), 3)
 | |
|         self.assertEqual(value[0], 'foo')
 | |
|         self.assertEqual(value[1], 'C:\\some path\\with spaces\\and, a comma')
 | |
|         self.assertEqual(value[2], 'baz')
 | |
| 
 | |
|     def test_multiple_values_separated_by_whitespace_and_commas_with_single_quotes(self):
 | |
|         value = util.parse_list("""
 | |
|         foo
 | |
|         'C:\\some path\\with spaces\\and, a comma',
 | |
|         baz
 | |
|         """)
 | |
|         self.assertEqual(len(value), 3)
 | |
|         self.assertEqual(value[0], 'foo')
 | |
|         self.assertEqual(value[1], 'C:\\some path\\with spaces\\and, a comma')
 | |
|         self.assertEqual(value[2], 'baz')
 | 
