def __init__(self, *args, **kwargs): TestCase.__init__(self, *args, **kwargs) self.configuration = None self.enabled = False self.mock_data = {} self.expected_data = {} self.ioc = GreaseContainer() self.detect = Detect(self.ioc)
def test_detection_bad_logical_block(self): d = Detect() source = {'key': 'var', 'ver': 'key', 'greg': 'old'} configuration = { 'name': 'demo config', 'job': 'otherThing', 'exe_env': 'general', 'source': 'Google', 'logic': { 'Regex': {} } } result, resultData = d.detection(source, configuration) self.assertFalse(result) self.assertFalse(resultData)
def test_get_schedule_staged(self): d = Detect() d.ioc.getCollection('SourceData').insert_one({ 'grease_data': { 'sourcing': { 'server': ObjectId(d.ioc.getConfig().NodeIdentity) }, 'detection': { 'server': ObjectId(d.ioc.getConfig().NodeIdentity), 'detectionStart': None, 'detectionEnd': None, 'detection': {} }, 'scheduling': { 'schedulingServer': None, 'schedulingStart': None, 'schedulingEnd': None }, 'execution': { 'server': None, 'assignmentTime': None, 'executionStart': None, 'executionEnd': None, 'context': {}, 'executionSuccess': False, 'commandSuccess': False, 'failures': 0, 'retryTime': datetime.datetime.utcnow() } }, 'source': str('test').encode('utf-8'), 'configuration': str('testConfig').encode('utf-8'), 'data': { 'dev': 'test' }, 'createTime': datetime.datetime.utcnow(), 'expiry': Deduplication.generate_max_expiry_time(1) }) self.assertTrue(d.getScheduledSource()) self.assertEqual( d.getScheduledSource().get('grease_data').get('detection').get( 'server'), ObjectId(d.ioc.getConfig().NodeIdentity)) d.ioc.getCollection('SourceData').drop()
def execute(self, context): """Execute method of the detection prototype Args: context (dict): Command Context Note: This method normally will *never* return. As it is a prototype. So it should continue into infinity Returns: bool: True always unless failures occur """ if context.get('foreground'): # set foreground if in context self.ioc.getLogger().foreground = True Detector = Detect(self.ioc) if 'loop' in context: # scan only a certain amount of times scan_count = 0 while scan_count < int(context.get('loop')): if not Detector.detectSource(): self.ioc.getLogger().warning("Detection Process Failed", notify=False) scan_count += 1 else: try: while True: if not Detector.detectSource(): self.ioc.getLogger().warning( "Detection Process Failed", notify=False) continue except KeyboardInterrupt: # graceful close for scanning self.ioc.getLogger().trace( "Keyboard interrupt in detect detected", trace=True) return True # ensure we clean up after ourselves if context.get('foreground'): self.ioc.getLogger().foreground = False return True
def test_detection_bad_source(self): d = Detect() configuration = { 'name': 'demo config', 'job': 'otherThing', 'exe_env': 'general', 'source': 'Google', 'logic': { 'Regex': [{ 'field': 'key', 'pattern': '.*', 'variable': True, 'variable_name': 'field' }, { 'field': 'ver', 'pattern': '.*' }] } } result, resultData = d.detection([], configuration) self.assertFalse(result) self.assertFalse(resultData)
def test_detection(self): d = Detect() source = {'key': 'var', 'ver': 'key', 'greg': 'old'} configuration = { 'name': 'demo config', 'job': 'otherThing', 'exe_env': 'general', 'source': 'Google', 'logic': { 'Regex': [{ 'field': 'key', 'pattern': '.*', 'variable': True, 'variable_name': 'field' }, { 'field': 'ver', 'pattern': '.*' }] } } result, resultData = d.detection(source, configuration) self.assertTrue(result) self.assertTrue(resultData.get('field'))
def test_scheduleScheduling(self): d = Detect() p = PrototypeConfig(d.ioc) source = { 'key': 'var', 'ver': 'key', 'greg': 'old', 'created': '2017-11-24' } configuration = { 'name': 'demoConfig', 'job': 'otherThing', 'exe_env': 'general', 'source': 'Google', 'logic': { 'DateRange': [{ 'field': 'created', 'format': '%Y-%m-%d', 'min': '2017-11-23', 'max': '2017-11-25' }], 'Regex': [{ 'field': 'key', 'pattern': '.*', 'variable': True, 'variable_name': 'field' }, { 'field': 'ver', 'pattern': '.*' }], 'Exists': [{ 'field': 'greg', 'variable': True, 'variable_name': 'greg' }] } } p.load(True, [configuration]) sourceId = d.ioc.getCollection('SourceData').insert_one({ 'grease_data': { 'sourcing': { 'server': ObjectId(d.ioc.getConfig().NodeIdentity) }, 'detection': { 'server': ObjectId(d.ioc.getConfig().NodeIdentity), 'detectionStart': None, 'detectionEnd': None, 'detection': {} }, 'scheduling': { 'schedulingServer': None, 'schedulingStart': None, 'schedulingEnd': None }, 'execution': { 'server': None, 'assignmentTime': None, 'executionStart': None, 'executionEnd': None, 'context': {}, 'executionSuccess': False, 'commandSuccess': False, 'failures': 0, 'retryTime': datetime.datetime.utcnow() } }, 'source': str('test').encode('utf-8'), 'configuration': configuration.get('name'), 'data': source, 'createTime': datetime.datetime.utcnow(), 'expiry': Deduplication.generate_max_expiry_time(1) }).inserted_id scheduleServer = d.ioc.getCollection('JobServer').insert_one({ 'jobs': 0, 'os': platform.system().lower(), 'roles': ["general"], 'prototypes': ["schedule"], 'active': True, 'activationTime': datetime.datetime.utcnow() }).inserted_id self.assertTrue(d.detectSource()) self.assertFalse(d.getScheduledSource()) self.assertTrue( len( d.ioc.getCollection('SourceData').find_one( { 'grease_data.scheduling.server': ObjectId(scheduleServer), 'grease_data.scheduling.start': None, 'grease_data.scheduling.end': None }, sort=[('createTime', pymongo.DESCENDING)]))) d.ioc.getCollection('JobServer').delete_one( {'_id': ObjectId(scheduleServer)}) d.ioc.getCollection('SourceData').delete_one( {'_id': ObjectId(sourceId)})
class AutomationTest(TestCase): """Automation Test Class Version II of GREASE was all about proving stability. Automation testing is critically important to ensure reliability during fault isolation. This class is an abstract class your tests can implement to ensure they will perform exactly as you expect in production. Make sure you set the **configuration** class attribute to ensure your configuration is tested, the **mock_data** class attribute with your mock data dictionary you expect to be sourced in production, and the **expected_data** with what you expect detection to find from your mocked source data. Then implement the **test_command** method to write standard unittests around your automation. The Platform will test your configuration for you, and execute **test_command** with `python setup.py test` is executed. Attributes: configuration (str|dict): Configuration to load for this test mock_data (dict): String Key -> Int/Float/String Value pair to mock source data expected_data (dict): data you expect context for your command to look like enabled (bool): set to true to enable your test to run Here is an example:: class TestAutomationTest(AutomationTest): def __init__(self, *args, **kwargs): AutomationTest.__init__(self, *args, **kwargs) self.configuration = "mongo://test_automation_test" self.mock_data = {'ver': 'var'} self.expected_data = {'ver': ['var']} self.enabled = True def test_command(self): myCommand = myCommand() self.assertTrue(myCommand.execute({'hostname': 'localhost'})) This is a pretty basic example but it will help you get started automatically testing your automation! Note: **YOU MUST SET THE PROPERTY `ENABLED` TO BOOLEAN TRUE IN ORDER FOR YOUR TEST TO BE PICKED UP** Note: To use a static configuration set `configuration` to a dictionary Note: To use a MongoDB configuration for a test prefix your configuration's name with mongo:// Note: To use a package configuration for a test prefix your configuration's name with pkg:// Note: to use a filesystem configuration for a test prefix your configuration's path with fs:// """ def __init__(self, *args, **kwargs): TestCase.__init__(self, *args, **kwargs) self.configuration = None self.enabled = False self.mock_data = {} self.expected_data = {} self.ioc = GreaseContainer() self.detect = Detect(self.ioc) def test_configuration(self): """Configuration Test This method tests your configuration and validates that detection will return as you expect """ if not self.enabled: raise SkipTest self.assertTrue(self.configuration, "Ensure configuration is not empty") self.assertIsInstance(self.configuration, str, "Ensure configuration is type string") self.assertTrue(self.mock_data, "Ensure mock_data is not empty") self.assertIsInstance(self.mock_data, dict, "Ensure mock_data is type dict") self.assertTrue(self.expected_data, "Ensure expected_data is not empty") self.assertIsInstance(self.expected_data, dict, "Ensure expected_data is type dict") config = None if str(self.configuration).startswith("mongo://"): config = self.ioc.getCollection('Configuration').find_one({ 'name': str(self.configuration).split("://")[1], 'active': True, "type": "prototype_config" }) self.assertTrue(config, "Ensuring MongoDB has configuration") config = dict(config) elif str(self.configuration).startswith("pkg://"): if os.path.isfile( pkg_resources.resource_filename( 'tgt_grease', str(self.configuration).split("://")[1])): with open( pkg_resources.resource_filename( 'tgt_grease', str(self.configuration).split("://")[1]), 'rb') as fil: config = json.loads(fil.read()) self.assertIsInstance(config, dict, "Ensuring Valid JSON") else: self.assertTrue( False, "Failed to load [{0}] from tgt_grease pkg".format( str(self.configuration).split("://")[1])) elif str(self.configuration).startswith("fs://"): if os.path.isfile(str(self.configuration).split("://")[1]): with open(str(self.configuration).split("://")[1], 'rb') as fil: config = json.loads(fil.read()) self.assertIsInstance(config, dict, "Ensuring Valid JSON") else: self.assertTrue( False, "Failed to load [{0}] from filesystem".format( str(self.configuration).split("://")[1])) else: self.assertTrue( False, "Failed to load configuration::Invalid Configuration Location Type" ) self.assertTrue(config, "Ensuring config is not boolean equatable to False") result, context = self.detect.detection(self.mock_data, config) self.assertTrue(result, "Detection Results") self.assertDictEqual(context, self.expected_data, "validating context expected") def test_command(self): """This method is for **you** to fill out to test your command Note: The more tests the better! Make sure to add as many tests as you need to ensure your automation is always successful """ if not self.enabled: raise SkipTest
def test_scheduling_fail(self): d = Detect() p = PrototypeConfig(d.ioc) s = Scheduler(d.ioc) source = { 'key': 'var', 'ver': 'key', 'greg': 'old', 'created': '2017-11-24' } configuration = { 'name': 'demoConfig', 'job': 'otherThing', 'exe_env': 'minix', 'source': 'Google', 'logic': { 'DateRange': [ { 'field': 'created', 'format': '%Y-%m-%d', 'min': '2017-11-23', 'max': '2017-11-25' } ], 'Regex': [ { 'field': 'key', 'pattern': '.*', 'variable': True, 'variable_name': 'field' }, { 'field': 'ver', 'pattern': '.*' } ], 'Exists': [ { 'field': 'greg', 'variable': True, 'variable_name': 'greg' } ] } } p.load(True, [configuration]) sourceId = d.ioc.getCollection('SourceData').insert_one({ 'grease_data': { 'sourcing': { 'server': ObjectId(d.ioc.getConfig().NodeIdentity) }, 'detection': { 'server': ObjectId(d.ioc.getConfig().NodeIdentity), 'detectionStart': None, 'detectionEnd': None, 'detection': {} }, 'scheduling': { 'schedulingServer': None, 'schedulingStart': None, 'schedulingEnd': None }, 'execution': { 'server': None, 'assignmentTime': None, 'executionStart': None, 'executionEnd': None, 'context': {}, 'executionSuccess': False, 'commandSuccess': False, 'failures': 0, 'retryTime': datetime.datetime.utcnow() } }, 'source': str('test').encode('utf-8'), 'configuration': configuration.get('name'), 'data': source, 'createTime': datetime.datetime.utcnow(), 'expiry': Deduplication.generate_max_expiry_time(1) }).inserted_id d.ioc.getCollection('JobServer').update_one( {'_id': ObjectId(d.ioc.getConfig().NodeIdentity)}, { '$set': { 'prototypes': ["scan", "detect", "schedule"] } } ) self.assertTrue(d.detectSource()) self.assertFalse(d.getScheduledSource()) self.assertTrue(s.getDetectedSource()) self.assertFalse(s.scheduleExecution()) self.assertTrue(d.ioc.getCollection('JobServer').update_one( {'_id': ObjectId(d.ioc.getConfig().NodeIdentity)}, { '$set': { 'prototypes': [] } } )) d.ioc.getCollection('SourceData').delete_one({'_id': ObjectId(sourceId)})
def test_get_schedule_empty(self): d = Detect() self.assertFalse(d.getScheduledSource())
def test_detection_bad_config(self): d = Detect() source = {'key': 'var', 'ver': 'key', 'greg': 'old'} result, resultData = d.detection(source, []) self.assertFalse(result) self.assertFalse(resultData)