def submit(self, allow_invalid=False): self.db_desc = Descriptor() self.db_desc.is_public = self.is_public self.db_desc.user_id = self.user file = create_temporary_file(self.container.get_data()) if (isinstance(self.container, DescriptorDataCandidateURLContainer)): self.db_desc.data_url = self.container.get_url() self.db_desc.automatic_updating = self.automatic_updating else: self.db_desc.data_url = "" filename = uuid.uuid4().hex self.db_desc.data_file.save(filename, ContentFile(self.container.get_data())) self.db_desc.md5 = calculate_MD5(self.container.get_data()) if (self.carmin_platform): self.db_desc.carmin_platform = self.carmin_platform # Validation try: bosh.validate(file.name) self.validated = True except Exception as exc: self.validated = False file.close() if (not allow_invalid): # An invalid descriptor is allowed on submission only if the 'allow_invalid' argument is set return False # Add error message to desc self.db_desc.execution_status = EXECUTION_STATUS_ERROR self.db_desc.error_message = str(exc).replace('\n', '<br>') self.db_desc.last_updated = datetime.date.today() self.db_desc.save() return True self.db_desc.execution_status = EXECUTION_STATUS_UNCHECKED desc_JSON = json.loads(file.read()) self.db_desc.tool_name = desc_JSON["name"] self.db_desc.version = desc_JSON["tool-version"] self.db_desc.last_updated = datetime.date.today() self.db_desc.save() # Generate all the test profiles. desc_entry = DescriptorEntry(self.db_desc) desc_entry.generate_tests() return True
def _get_valid_descriptor_count(self, raw_descriptors): count = 0 for raw_descriptor in raw_descriptors: descriptor_file = create_temporary_file(raw_descriptor) try: bosh.validate(descriptor_file.name) count += 1 descriptor_file.close() except: descriptor_file.close() return count
def _execute_test(self): results = [] desc_JSON = json.loads(self.db_desc.data_file.read()) # This is a work-around: # To individually test each of the descriptors, # the source descriptor will be broken into x copies of the descriptor, where x is the amount of tests defined. # Each of those clones will be only include each of the tests in the source descriptor. # To perform a test on a single defined test-case, we only need to supply the descriptor which includes it. # - The output of bosh should indicate the successfullness of the test. # - The stdout procuced by the command will represent the console logs we need to capture. tests = desc_JSON["tests"] # We remove the test entries in the JSON descriptor. desc_JSON["tests"] = [] for test in tests: # We remove all the test entries in the JSON descriptor and only the current test entry desc_JSON["tests"] = [test] temporary_desc_file = create_temporary_file( json.dumps(desc_JSON).encode()) # Preparation of the bosh test call # Capture of the stdout old_stdout = sys.stdout sys.stdout = mystdout = StringIO() if (bosh.bosh(["test", temporary_desc_file.name]) == 0): # Bosh test (pytest) returned 0, this means that the test was successful. status = TEST_STATUS_SUCCESS else: # Otherwise, any other exit-code indicates failure. status = TEST_STATUS_FAILURE temporary_desc_file.close() sys.stdout = old_stdout console = mystdout.getvalue().replace('\\n', '<br>') results.append((status, console)) return results
def validate(self): # This is here in case we have a URL container if (self.container.is_medium_erroneous()): self.validated = False self.message = self.container.get_error() return False else: desc_content = self.container.get_data() # Call bosh validate on the data file = create_temporary_file(desc_content) #backedup = sys.tracebacklimit #sys.tracebacklimit = None try: bosh.validate(file.name) self.validated = True except Exception as exc: self.validated = False error = str(exc).replace('\n', '<br>') #sys.tracebacklimit = backedup if (self.validated == True): desc = json.loads(file.read()) if (desc.get("tests") == None): n_tests = 0 else: n_tests = len(desc["tests"]) self.message = "Associated descriptor is valid.<br><b>" + str( n_tests) + "</b> tests found defined inside descriptor." else: self.message = "<b> Validation failure.<br>Boutiques returned the following error(s):</b><br>" + error file.close() return self.validated
def generate_tests(self): # Get descriptor as JSON desc_JSON = json.loads(self.db_desc.data_file.read()) # Create new test entries test_list = [] for test_JSON in desc_JSON['tests']: test = DescriptorTest() test.test_name = test_JSON['name'] test.descriptor = self.db_desc test_list.append(test_JSON['name']) # Evaluate the descriptor's command line, using the invocation specified by the test. # To perform this evaluation, we need to extract the invocation from the test and put it into a temporary file invocation_tmp_file = create_temporary_file( json.dumps(test_JSON['invocation']).encode()) # If the invocation is erroneous, we simply mention it in in the entry itself # A wrongfull invocation should however not put a halt to the entire evaluation of a descriptor. erroneous_invocation = False try: bosh.invocation(self.db_desc.data_file.file.name, '-i', invocation_tmp_file.name) except: erroneous_invocation = True # Rewind invocation_tmp_file.seek(0) if (erroneous_invocation): test.evaluated_invocation = "Error: invalid invocation" else: #test.evaluated_invocation = bosh.evaluate(self.db_desc.data_file.file.name, invocation_tmp_file.name, "command-line/") test.evaluated_invocation = get_bosh_cmdline( self.db_desc.data_file.file.name, invocation_tmp_file.name) test.save() invocation_tmp_file.close() # Create assertion entries. if test_JSON['assertions'].get('exit-code') != None: # Create assertion entry with exit-code assertion = DescriptorTestAssertion() assertion.test = test assertion.operand1 = test_JSON['assertions']['exit-code'] assertion.type = ASSERTION_EXITCODE assertion.save() output_files = None if (erroneous_invocation == False): output_files = bosh.evaluate(self.db_desc.data_file.file.name, invocation_tmp_file.name, "output-files/") if test_JSON['assertions'].get('output-files') != None: for ouput_assertion_JSON in test_JSON['assertions'][ 'output-files']: assertion = DescriptorTestAssertion() assertion.test = test # Id processing id = ouput_assertion_JSON['id'] if erroneous_invocation == True: # Skip the evaluation of this entry because the associated invocation is invalid. assertion.operand1 = "Cannot evaluate: invocation invalid" else: assertion.operand1 = output_files[id] # MD5 reference processing if ouput_assertion_JSON.get('md5-reference') != None: assertion.operand2 = ouput_assertion_JSON[ 'md5-reference'] assertion.type = ASSERTION_OUTPUT_FILE_MATCHES_MD5 else: assertion.type = ASSERTION_OUTPUT_FILE_EXISTS assertion.save() # We are done filling up the test entry. self.db_desc.data_file.seek(0)