def test_read_line_state_read_api_title(self): v = ApiaryValidator() state = _state_read_api_title self._test_read_line(line=' ', validator=v, state=state, expected_state=_state_read_api_title) for method in ['GET', 'POST', 'DELETE', 'PUT']: self._test_read_line(line=_TEST_API_METHOD_TEMPLATE % method, state=state, validator=v, expected_state=_state_read_api_method) self._test_read_line(line=_TEST_PARAMETER_TAG, state=state, validator=v, expected_error=ApiarySyntaxError()) self._test_read_line(line=_TEST_PARAMETER_STRING, state=state, validator=v, expected_error=ApiarySyntaxError()) self._test_read_line(line=_TEST_REQUEST_TAG, state=state, validator=v, expected_error=ApiarySyntaxError()) self._test_read_line(line=_TEST_RESPONSE_TAG, state=state, validator=v, expected_error=ApiarySyntaxError())
def test_read_line_state_read_param_tag(self): v = ApiaryValidator() v._parameters = ['test'] state = _state_read_param_tag self._test_read_line(line=' ', state=state, validator=v, expected_state=state) self._test_read_line(line=_TEST_PARAMETER_TAG, state=state, validator=v, expected_error=ApiarySyntaxError()) self._test_read_line(line=_TEST_PARAMETER_STRING, state=state, validator=v, expected_state=state) self._test_read_line(line=_TEST_REQUEST_TAG, state=state, validator=v, expected_state=_state_read_request_tag) self._test_read_line(line=_TEST_RESPONSE_TAG, state=state, validator=v, expected_state=_state_read_response_tag)
def _scan_line_by_decoder(self, line): assert self.decoder is not None assert isinstance(line, str) error = None # validation for the newline constrain: if not self._read_newline: if re.match(r'^\s*[\r\n]?$', line): self._read_newline = True error = None else: error = ApiarySyntaxError( message= 'SyntaxError: the code block should be started with a newline' ) return error # validation for the indent constrain: if not ApiaryValidator._indent_validation(line): self.state = _state_error return ApiarySyntaxError( message= 'SyntaxError: each line in the code block should be indented by 8 spaces ot 2 tabs' ) # scan line with the decoder: try: self.decoder.scan_line(line) except AssertionError as e: error = ApiarySyntaxError(message='DecoderAssertion: %s' % e.args) self.state = _state_error except Exception as e: error = ApiarySyntaxError(message='DecodeException: %s' % getattr(e, 'message', None)) self.state = _state_error return error
def _test_with_lines_of_content(self, validator, lines, expected_error_line_count): line_count = 0 # add a newline before the code block validator._read_line(' ') for line in lines: line_count += 1 line = ' %s' % line valid, error = validator._read_line(line) if line_count == expected_error_line_count: self.assertFalse(valid) self.assertEqual(error.type, ApiarySyntaxError().type) break else: if error: print('error(@ line %d): %s' % (line_count, error)) self.assertTrue(valid) self.assertEqual(error, None)
def test_read_line_with_indent_validation(self): v = ApiaryValidator() valid_examples = [' ', ' {', '\t\t{'] invalid_examples = ['"test":123, ', ' "test": false, '] for state in [_state_read_response_tag, _state_read_request_tag]: for line in valid_examples: v.state = state v.decoder.clear() valid, error = v._read_line(line) if error and DEBUG: print('\nUnexpected Error: %s' % error) self.assertTrue(valid) self.assertEqual(error, None) for line in invalid_examples: v.state = state v.decoder.clear() valid, error = v._read_line(line) self.assertFalse(valid) self.assertEqual(error.type, ApiarySyntaxError().type)
def test_for_check_code_block_newline(self): v = ApiaryValidator() # valid cases: newline_examples = [' ', '\n', '\r', ' \n', ' \r'] for newline in newline_examples: for state in [_state_read_response_tag, _state_read_request_tag]: v.decoder.clear() v.state = state v._read_newline = False v._read_line(newline) valid, error = v._read_line(' {') if error and DEBUG: print('\nUnexpected Error: %s' % error) self.assertTrue(valid) self.assertIsNone(error) # invalid cases: for state in [_state_read_request_tag, _state_read_request_tag]: v.decoder.clear() v.state = state v._read_newline = False valid, error = v._read_line(' {') self.assertFalse(valid) self.assertEqual(error.type, ApiarySyntaxError().type)
def pre_validate(self, line): if _tab(line) is not None: valid, error = False, ApiarySyntaxError(message='contains tab in line') else: valid, error = super(PreValidationTabMixin, self).pre_validate(line) return valid, error
def _read_line(self, line): error = None assert not self.state < 0, 'StateError: the validator is in the error state with line %s' % line if self.state == _state_read_group_title: if _api_title(line): if not _api_url(line): error = ApiarySyntaxError( message='Cannot find the api url in line: %s' % line) self.state = _state_error else: self._parameters = ApiaryValidator._get_parameters_from_api_title( line) self.state = _state_read_api_title elif _api_method(line) or _param_title(line) or _param_string(line) or _request_title(line) \ or _response_title(line): error = ApiarySyntaxError(message='Missing api title string') self.state = _state_error elif self.state == _state_read_api_title: if _api_method(line): self.state = _state_read_api_method elif _param_title(line) or _param_string(line) or _request_title( line) or _response_title(line): error = ApiarySyntaxError(message='Missing api method string') self.state = _state_error elif self.state == _state_read_api_method: if _param_title(line): self._read_parameter_string = False self.state = _state_read_param_tag elif _request_title(line): self._prepare_for_scanning_request_content() elif _response_title(line): self._prepare_for_scanning_response_content() elif _param_string(line): error = ApiarySyntaxError(message='Missing parameter title') self.state = _state_error elif self.state == _state_read_param_tag: if _param_string(line): self._read_parameter_string = True parameter = ApiaryValidator._get_parameter_from_parameter_string( line) if parameter not in self._parameters: error = ApiaryParameterNotDefinedError(parameter=parameter) self.state = _state_error elif _request_title(line): if not self._read_parameter_string: error = ApiarySyntaxError(message='Missing parameter info') self.state = _state_error else: self._prepare_for_scanning_request_content() elif _response_title(line): if not self._read_parameter_string: error = ApiarySyntaxError(message='Missing parameter info') self.state = _state_error else: self._prepare_for_scanning_response_content() elif not re.match(r'\s+', line): error = ApiarySyntaxError( message='The lines should contain the parameter info') self.state = _state_error elif self.state == _state_read_request_tag: test_line = line if _response_title(line): if not self.decoder.get_parsed_objects(): error = ApiarySyntaxError( message='Missing request content') self.state = _state_error else: self._prepare_for_scanning_response_content() elif _request_title(line): self._prepare_for_scanning_request_content() else: error = self._scan_line_by_decoder(line) elif self.state == _state_read_response_tag: if _group_title(line): if not self.decoder.get_parsed_objects(): error = ApiarySyntaxError( message='Missing response content') self.state = _state_error else: self.decoder.clear() self._read_newline = False self.state = _state_read_group_title elif _api_title(line): if not self.decoder.get_parsed_objects(): error = ApiarySyntaxError( message='Missing response content') self.state = _state_error else: self.decoder.clear() self._parameters = ApiaryValidator._get_parameters_from_api_title( line) self.state = _state_read_api_title elif _api_method(line): if not self.decoder.get_parsed_objects(): error = ApiarySyntaxError( message='Missing response content') self.state = _state_error else: self.decoder.clear() self.state = _state_read_api_method elif _request_title(line): if not self.decoder.get_parsed_objects(): error = ApiarySyntaxError('Missing the request content') self.state = _state_error else: self._prepare_for_scanning_request_content() elif _response_title(line): if not self.decoder.get_parsed_objects(): error = ApiarySyntaxError('Missing the response content') self.state = _state_error else: self._prepare_for_scanning_response_content() else: error = self._scan_line_by_decoder(line) else: # _state_init if _group_title(line): self.state = _state_read_group_title return (error is None), error