mirror of https://github.com/yandex/gixy
Merge branch 'master' into nonstrict-encoding
commit
cb4dbc875a
|
@ -1,6 +1,7 @@
|
||||||
language: python
|
language: python
|
||||||
sudo: false
|
sudo: false
|
||||||
python:
|
python:
|
||||||
|
- "2.6"
|
||||||
- "2.7"
|
- "2.7"
|
||||||
- "3.5"
|
- "3.5"
|
||||||
- "3.6"
|
- "3.6"
|
||||||
|
@ -11,4 +12,4 @@ install:
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- nosetests --with-coverage --cover-package gixy -v
|
- nosetests --with-coverage --cover-package gixy -v
|
||||||
- flake8 --max-line-length=120 setup.py yodax
|
- if [[ $TRAVIS_PYTHON_VERSION != '2.6' ]]; then flake8 --max-line-length=120 setup.py gixy; fi
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# [add_header_multiline] Multiline response headers
|
# [add_header_multiline] Multiline response headers
|
||||||
|
|
||||||
You should avoid using multiline response headers, because:
|
You should avoid using multiline response headers, because:
|
||||||
* they are depricated (see [RFC 7230](https://tools.ietf.org/html/rfc7230#section-3.2.4));
|
* they are deprecated (see [RFC 7230](https://tools.ietf.org/html/rfc7230#section-3.2.4));
|
||||||
* some HTTP-clients and web browser never supported them (e.g. IE/Edge/Nginx).
|
* some HTTP-clients and web browser never supported them (e.g. IE/Edge/Nginx).
|
||||||
|
|
||||||
## How can I find it?
|
## How can I find it?
|
||||||
|
@ -22,4 +22,4 @@ more_set_headers -t 'text/html text/plain'
|
||||||
```
|
```
|
||||||
|
|
||||||
## What can I do?
|
## What can I do?
|
||||||
The only solution is to never use multiline response headers.
|
The only solution is to never use multiline response headers.
|
||||||
|
|
|
@ -92,7 +92,7 @@ class ArgsParser(ArgumentParser):
|
||||||
"""
|
"""
|
||||||
keys = []
|
keys = []
|
||||||
for arg in action.option_strings:
|
for arg in action.option_strings:
|
||||||
if arg in {'--config', '--write-config', '--version'}:
|
if arg in ['--config', '--write-config', '--version']:
|
||||||
continue
|
continue
|
||||||
if any([arg.startswith(2 * c) for c in self.prefix_chars]):
|
if any([arg.startswith(2 * c) for c in self.prefix_chars]):
|
||||||
keys += [arg[2:], arg] # eg. for '--bla' return ['bla', '--bla']
|
keys += [arg[2:], arg] # eg. for '--bla' return ['bla', '--bla']
|
||||||
|
|
|
@ -16,7 +16,6 @@ LOG = logging.getLogger()
|
||||||
def _init_logger(debug=False):
|
def _init_logger(debug=False):
|
||||||
LOG.handlers = []
|
LOG.handlers = []
|
||||||
log_level = logging.DEBUG if debug else logging.INFO
|
log_level = logging.DEBUG if debug else logging.INFO
|
||||||
logging.captureWarnings(True)
|
|
||||||
|
|
||||||
LOG.setLevel(log_level)
|
LOG.setLevel(log_level)
|
||||||
handler = logging.StreamHandler(sys.stderr)
|
handler = logging.StreamHandler(sys.stderr)
|
||||||
|
@ -31,7 +30,7 @@ def _create_plugin_help(option):
|
||||||
else:
|
else:
|
||||||
default = str(option)
|
default = str(option)
|
||||||
|
|
||||||
return 'Default: {}'.format(default)
|
return 'Default: {0}'.format(default)
|
||||||
|
|
||||||
|
|
||||||
def _get_cli_parser():
|
def _get_cli_parser():
|
||||||
|
@ -41,7 +40,7 @@ def _get_cli_parser():
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-v', '--version', action='version',
|
'-v', '--version', action='version',
|
||||||
version='Gixy v{}'.format(gixy.version))
|
version='Gixy v{0}'.format(gixy.version))
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-l', '--level', dest='level', action='count', default=0,
|
'-l', '--level', dest='level', action='count', default=0,
|
||||||
|
@ -106,7 +105,7 @@ def main():
|
||||||
try:
|
try:
|
||||||
severity = gixy.severity.ALL[args.level]
|
severity = gixy.severity.ALL[args.level]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
sys.stderr.write('Too high level filtering. Maximum level: -{}\n'.format('l' * (len(gixy.severity.ALL) - 1)))
|
sys.stderr.write('Too high level filtering. Maximum level: -{0}\n'.format('l' * (len(gixy.severity.ALL) - 1)))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if args.tests:
|
if args.tests:
|
||||||
|
@ -132,7 +131,7 @@ def main():
|
||||||
name = plugin_cls.__name__
|
name = plugin_cls.__name__
|
||||||
options = copy.deepcopy(plugin_cls.options)
|
options = copy.deepcopy(plugin_cls.options)
|
||||||
for opt_key, opt_val in options.items():
|
for opt_key, opt_val in options.items():
|
||||||
option_name = '{}:{}'.format(name, opt_key)
|
option_name = '{name}:{key}'.format(name=name, key=opt_key)
|
||||||
if option_name not in args:
|
if option_name not in args:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ class Context(object):
|
||||||
result = builtins.builtin_var(name)
|
result = builtins.builtin_var(name)
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
LOG.info("Can't find variable '{}'".format(name))
|
LOG.info("Can't find variable '{0}'".format(name))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
def __deepcopy__(self, memo):
|
||||||
|
|
|
@ -432,7 +432,7 @@ class BranchToken(Token):
|
||||||
elif isinstance(token, sre_parse.SubPattern):
|
elif isinstance(token, sre_parse.SubPattern):
|
||||||
self.childs.append(InternalSubpatternToken(token=token, parent=self.parent, regexp=self.regexp))
|
self.childs.append(InternalSubpatternToken(token=token, parent=self.parent, regexp=self.regexp))
|
||||||
else:
|
else:
|
||||||
raise RuntimeError('Unexpected token {} in branch'.format(token))
|
raise RuntimeError('Unexpected token {0} in branch'.format(token))
|
||||||
|
|
||||||
def can_contain(self, char, skip_literal=True):
|
def can_contain(self, char, skip_literal=True):
|
||||||
for child in self.childs:
|
for child in self.childs:
|
||||||
|
@ -461,7 +461,7 @@ class BranchToken(Token):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '(?:{})'.format('|'.join(str(x) for x in self.childs))
|
return '(?:{0})'.format('|'.join(str(x) for x in self.childs))
|
||||||
|
|
||||||
|
|
||||||
class SubpatternToken(Token):
|
class SubpatternToken(Token):
|
||||||
|
@ -661,7 +661,7 @@ class InToken(Token):
|
||||||
elif isinstance(child, CategoryToken):
|
elif isinstance(child, CategoryToken):
|
||||||
blacklisted.update(child.char_list)
|
blacklisted.update(child.char_list)
|
||||||
else:
|
else:
|
||||||
LOG.info('Unexpected child "{!r}"'.format(child))
|
LOG.info('Unexpected child "{0!r}"'.format(child))
|
||||||
|
|
||||||
for char in _build_reverse_list(set()):
|
for char in _build_reverse_list(set()):
|
||||||
if char not in blacklisted:
|
if char not in blacklisted:
|
||||||
|
@ -756,7 +756,7 @@ class GroupRefToken(Token):
|
||||||
return self.group.generate(context)
|
return self.group.generate(context)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '\\\\{}'.format(self.id)
|
return '\\\\{0}'.format(self.id)
|
||||||
|
|
||||||
|
|
||||||
class AssertToken(Token):
|
class AssertToken(Token):
|
||||||
|
@ -854,7 +854,7 @@ def parse(sre_obj, parent=None, regexp=None):
|
||||||
elif token[0] == sre_parse.ASSERT_NOT:
|
elif token[0] == sre_parse.ASSERT_NOT:
|
||||||
pass # TODO(buglloc): Do it!
|
pass # TODO(buglloc): Do it!
|
||||||
else:
|
else:
|
||||||
LOG.info('Unexpected token "{}"'.format(token[0]))
|
LOG.info('Unexpected token "{0}"'.format(token[0]))
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ class Block(Directive):
|
||||||
self.children.append(directive)
|
self.children.append(directive)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{} {} {}'.format(self.name, ' '.join(self.args), '{')
|
return '{name} {args} {{'.format(name=self.name, args=' '.join(self.args))
|
||||||
|
|
||||||
|
|
||||||
class Root(Block):
|
class Root(Block):
|
||||||
|
@ -89,7 +89,7 @@ class ServerBlock(Block):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
server_names = [str(sn) for sn in self.find('server_name')]
|
server_names = [str(sn) for sn in self.find('server_name')]
|
||||||
if server_names:
|
if server_names:
|
||||||
return 'server {{\n{}'.format('\n'.join(server_names[:2]))
|
return 'server {{\n{0}'.format('\n'.join(server_names[:2]))
|
||||||
return 'server {'
|
return 'server {'
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,10 +141,10 @@ class IfBlock(Block):
|
||||||
# if ($request_method = POST)
|
# if ($request_method = POST)
|
||||||
self.variable, self.operand, self.value = args
|
self.variable, self.operand, self.value = args
|
||||||
else:
|
else:
|
||||||
raise Exception('Unknown "if" definition, args: {}'.format(repr(args)))
|
raise Exception('Unknown "if" definition, args: {0!r}'.format(args))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{} ({}) {{'.format(self.name, ' '.join(self.args))
|
return '{name} ({args}) {{'.format(name=self.name, args=' '.join(self.args))
|
||||||
|
|
||||||
|
|
||||||
class IncludeBlock(Block):
|
class IncludeBlock(Block):
|
||||||
|
@ -156,7 +156,7 @@ class IncludeBlock(Block):
|
||||||
self.file_path = args[0]
|
self.file_path = args[0]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return 'include {};'.format(self.file_path)
|
return 'include {0};'.format(self.file_path)
|
||||||
|
|
||||||
|
|
||||||
class MapBlock(Block):
|
class MapBlock(Block):
|
||||||
|
|
|
@ -41,7 +41,7 @@ class Directive(object):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{} {};'.format(self.name, ' '.join(self.args))
|
return '{name} {args};'.format(name=self.name, args=' '.join(self.args))
|
||||||
|
|
||||||
|
|
||||||
class AddHeaderDirective(Directive):
|
class AddHeaderDirective(Directive):
|
||||||
|
|
|
@ -4,7 +4,7 @@ from gixy.directives import block
|
||||||
|
|
||||||
|
|
||||||
class BaseFormatter(object):
|
class BaseFormatter(object):
|
||||||
skip_parents = {block.Root, block.HttpBlock}
|
skip_parents = set([block.Root, block.HttpBlock])
|
||||||
|
|
||||||
def format_reports(self, reports, stats):
|
def format_reports(self, reports, stats):
|
||||||
raise NotImplementedError("Formatter must override format_reports function")
|
raise NotImplementedError("Formatter must override format_reports function")
|
||||||
|
@ -74,11 +74,11 @@ class BaseFormatter(object):
|
||||||
if leap.is_block:
|
if leap.is_block:
|
||||||
result.append('')
|
result.append('')
|
||||||
directive = str(leap).replace('\n', '\n' + '\t' * (level + 1))
|
directive = str(leap).replace('\n', '\n' + '\t' * (level + 1))
|
||||||
result.append('{:s}{:s}'.format('\t' * level, directive))
|
result.append('{indent:s}{dir:s}'.format(indent='\t' * level, dir=directive))
|
||||||
|
|
||||||
if leap.is_block:
|
if leap.is_block:
|
||||||
result.extend(self._traverse_tree(leap, points, level + 1 if printable else level))
|
result.extend(self._traverse_tree(leap, points, level + 1 if printable else level))
|
||||||
if printable and have_parentheses:
|
if printable and have_parentheses:
|
||||||
result.append('{:s}}}'.format('\t' * level))
|
result.append('{indent:s}}}'.format(indent='\t' * level))
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -22,8 +22,8 @@ class NginxParser(object):
|
||||||
self._init_directives()
|
self._init_directives()
|
||||||
|
|
||||||
def parse_file(self, path, root=None):
|
def parse_file(self, path, root=None):
|
||||||
LOG.debug("Parse file: {}".format(path))
|
LOG.debug("Parse file: {0}".format(path))
|
||||||
content = open(path, mode='rb').read()
|
content = open(path).read()
|
||||||
return self.parse(content=content, root=root, path_info=path)
|
return self.parse(content=content, root=root, path_info=path)
|
||||||
|
|
||||||
def parse(self, content, root=None, path_info=None):
|
def parse(self, content, root=None, path_info=None):
|
||||||
|
@ -103,7 +103,7 @@ class NginxParser(object):
|
||||||
if self.is_dump:
|
if self.is_dump:
|
||||||
return self._resolve_dump_include(pattern=pattern, parent=parent)
|
return self._resolve_dump_include(pattern=pattern, parent=parent)
|
||||||
if not self.allow_includes:
|
if not self.allow_includes:
|
||||||
LOG.debug('Includes are disallowed, skip: {}'.format(pattern))
|
LOG.debug('Includes are disallowed, skip: {0}'.format(pattern))
|
||||||
return
|
return
|
||||||
|
|
||||||
return self._resolve_file_include(pattern=pattern, parent=parent)
|
return self._resolve_file_include(pattern=pattern, parent=parent)
|
||||||
|
@ -117,7 +117,7 @@ class NginxParser(object):
|
||||||
self.parse_file(file_path, include)
|
self.parse_file(file_path, include)
|
||||||
|
|
||||||
if not file_path:
|
if not file_path:
|
||||||
LOG.warning("File not found: {}".format(path))
|
LOG.warning("File not found: {0}".format(path))
|
||||||
|
|
||||||
def _resolve_dump_include(self, pattern, parent):
|
def _resolve_dump_include(self, pattern, parent):
|
||||||
path = os.path.join(self.cwd, pattern)
|
path = os.path.join(self.cwd, pattern)
|
||||||
|
@ -130,7 +130,7 @@ class NginxParser(object):
|
||||||
self.parse_block(parsed, include)
|
self.parse_block(parsed, include)
|
||||||
|
|
||||||
if not founded:
|
if not founded:
|
||||||
LOG.warning("File not found: {}".format(path))
|
LOG.warning("File not found: {0}".format(path))
|
||||||
|
|
||||||
def _prepare_dump(self, parsed_block):
|
def _prepare_dump(self, parsed_block):
|
||||||
filename = ''
|
filename = ''
|
||||||
|
|
|
@ -33,7 +33,7 @@ def get_header_values(directive):
|
||||||
result = []
|
result = []
|
||||||
skip_next = False
|
skip_next = False
|
||||||
for arg in directive.args:
|
for arg in directive.args:
|
||||||
if arg in {'-s', '-t'}:
|
if arg in ['-s', '-t']:
|
||||||
# Skip next value, because it's not a header
|
# Skip next value, because it's not a header
|
||||||
skip_next = True
|
skip_next = True
|
||||||
elif arg.startswith('-'):
|
elif arg.startswith('-'):
|
||||||
|
|
|
@ -18,11 +18,11 @@ class add_header_redefinition(Plugin):
|
||||||
'See documentation: http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header')
|
'See documentation: http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header')
|
||||||
help_url = 'https://github.com/yandex/gixy/blob/master/docs/en/plugins/addheaderredefinition.md'
|
help_url = 'https://github.com/yandex/gixy/blob/master/docs/en/plugins/addheaderredefinition.md'
|
||||||
directives = ['server', 'location', 'if']
|
directives = ['server', 'location', 'if']
|
||||||
options = {'headers': {'x-frame-options',
|
options = {'headers': set(['x-frame-options',
|
||||||
'x-content-type-options',
|
'x-content-type-options',
|
||||||
'x-xss-protection',
|
'x-xss-protection',
|
||||||
'content-security-policy',
|
'content-security-policy',
|
||||||
'cache-control'}
|
'cache-control'])
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
|
|
|
@ -39,16 +39,16 @@ class origins(Plugin):
|
||||||
self.valid_re = re.compile(regex)
|
self.valid_re = re.compile(regex)
|
||||||
|
|
||||||
def audit(self, directive):
|
def audit(self, directive):
|
||||||
if directive.operand not in {'~', '~*', '!~', '!~*'}:
|
if directive.operand not in ['~', '~*', '!~', '!~*']:
|
||||||
# Not regexp
|
# Not regexp
|
||||||
return
|
return
|
||||||
|
|
||||||
if directive.variable not in {'$http_referer', '$http_origin'}:
|
if directive.variable not in ['$http_referer', '$http_origin']:
|
||||||
# Not interesting
|
# Not interesting
|
||||||
return
|
return
|
||||||
|
|
||||||
invalid_referers = set()
|
invalid_referers = set()
|
||||||
regexp = Regexp(directive.value, case_sensitive=(directive.operand in {'~', '!~'}))
|
regexp = Regexp(directive.value, case_sensitive=(directive.operand in ['~', '!~']))
|
||||||
for value in regexp.generate('/', anchored=True):
|
for value in regexp.generate('/', anchored=True):
|
||||||
if value.startswith('^'):
|
if value.startswith('^'):
|
||||||
value = value[1:]
|
value = value[1:]
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
from nose.tools import assert_true, assert_false
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
Various nose.tools helpers that doesn't exists in Python 2.6 Unittest :(
|
||||||
|
Must be removed with drop Python 2.6 support
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def assert_is_instance(obj, cls, msg=None):
|
||||||
|
"""Same as assert_true(isinstance(obj, cls)), with a nicer
|
||||||
|
default message."""
|
||||||
|
if not msg:
|
||||||
|
msg = '{orig} is not an instance of {test}'.format(orig=type(obj), test=cls)
|
||||||
|
assert_true(isinstance(obj, cls), msg=msg)
|
||||||
|
|
||||||
|
|
||||||
|
def assert_is_none(obj, msg=None):
|
||||||
|
"""Same as assert_true(obj is None), with a nicer default message."""
|
||||||
|
if not msg:
|
||||||
|
msg = '{orig!r} is not None'.format(orig=obj)
|
||||||
|
assert_true(obj is None, msg=msg)
|
||||||
|
|
||||||
|
|
||||||
|
def assert_is_not_none(obj, msg=None):
|
||||||
|
"""Same as assert_false(obj is None), with a nicer default message."""
|
||||||
|
if not msg:
|
||||||
|
msg = '{orig!r} is None'.format(orig=obj)
|
||||||
|
assert_false(obj is None, msg=msg)
|
||||||
|
|
||||||
|
|
||||||
|
def assert_in(member, container, msg=None):
|
||||||
|
"""Just like assert_true(a in b), but with a nicer default message."""
|
||||||
|
if not msg:
|
||||||
|
msg = '{member!r} not found in {container!r}'.format(member=member, container=container)
|
||||||
|
assert_true(member in container, msg=msg)
|
|
@ -232,24 +232,24 @@ def test_negative_must_startswith():
|
||||||
|
|
||||||
def test_generate():
|
def test_generate():
|
||||||
cases = (
|
cases = (
|
||||||
(r'foo', {'foo'}),
|
(r'foo', ['foo']),
|
||||||
(r'^sss', {'^sss'}),
|
(r'^sss', ['^sss']),
|
||||||
(r'(1)(2)(3)', {'123'}),
|
(r'(1)(2)(3)', ['123']),
|
||||||
(r'(1)((2)|(?:3))', {'12', '13'}),
|
(r'(1)((2)|(?:3))', ['12', '13']),
|
||||||
(r'(^1?2?|aa/)', {'^', '^1', '^2', '^12', 'aa/'}),
|
(r'(^1?2?|aa/)', ['^', '^1', '^2', '^12', 'aa/']),
|
||||||
(r'^https?://yandex.ru', {'^http://yandex|ru', '^https://yandex|ru'}),
|
(r'^https?://yandex.ru', ['^http://yandex|ru', '^https://yandex|ru']),
|
||||||
(r'(^bb|11)$', {'^bb$', '11$'}),
|
(r'(^bb|11)$', ['^bb$', '11$']),
|
||||||
(r'(http|https)', {'http', 'https'}),
|
(r'(http|https)', ['http', 'https']),
|
||||||
(r'1*', {'', '11111'}),
|
(r'1*', ['', '11111']),
|
||||||
(r'1*?', {'', '11111'}),
|
(r'1*?', ['', '11111']),
|
||||||
(r'1{0}?2', {'2'}),
|
(r'1[0]?2', ['102', '12']),
|
||||||
(r'1{0}2', {'2'}),
|
(r'1[0]2', ['102']),
|
||||||
(r'1+', {'11111'}),
|
(r'1+', ['11111']),
|
||||||
(r'[^/]?', {'', '|'}),
|
(r'[^/]?', ['', '|']),
|
||||||
(r'^http://(foo|bar)|baz', {'^http://foo', '^http://bar', 'baz'}),
|
(r'^http://(foo|bar)|baz', ['^http://foo', '^http://bar', 'baz']),
|
||||||
(r'[^\x00-\x7b|\x7e-\xff]', {'\x7d'}),
|
(r'[^\x00-\x7b|\x7e-\xff]', ['\x7d']),
|
||||||
(r'(a|b|c)', {'a', 'b', 'c'}),
|
(r'(a|b|c)', ['a', 'b', 'c']),
|
||||||
(r'[xyz]', {'x', 'y', 'z'})
|
(r'[xyz]', ['x', 'y', 'z'])
|
||||||
)
|
)
|
||||||
for case in cases:
|
for case in cases:
|
||||||
regexp, values = case
|
regexp, values = case
|
||||||
|
@ -258,7 +258,7 @@ def test_generate():
|
||||||
|
|
||||||
def test_strict_generate():
|
def test_strict_generate():
|
||||||
reg = Regexp('^foo|bar', strict=True)
|
reg = Regexp('^foo|bar', strict=True)
|
||||||
assert_equals(sorted(reg.generate('|', anchored=True)), sorted({'^foo', '^bar'}))
|
assert_equals(sorted(reg.generate('|', anchored=True)), sorted(['^foo', '^bar']))
|
||||||
|
|
||||||
|
|
||||||
def test_gen_anchor():
|
def test_gen_anchor():
|
||||||
|
@ -284,63 +284,63 @@ def test_group_can_contains():
|
||||||
source = '/some/(?P<action>[^/:.]+)/'
|
source = '/some/(?P<action>[^/:.]+)/'
|
||||||
reg = Regexp(source)
|
reg = Regexp(source)
|
||||||
assert_true(reg.can_contain('\n'),
|
assert_true(reg.can_contain('\n'),
|
||||||
'Whole regex "{}" can contains "{}"'.format(source, '\\n'))
|
'Whole regex "{src}" can contains {sym!r}'.format(src=source, sym='\\n'))
|
||||||
|
|
||||||
assert_true(reg.group(0).can_contain('\n'),
|
assert_true(reg.group(0).can_contain('\n'),
|
||||||
'Group 0 from regex "{}" can contains "{}"'.format(source, '\\n'))
|
'Group 0 from regex "{src}" can contains {sym!r}'.format(src=source, sym='\\n'))
|
||||||
|
|
||||||
assert_true(reg.group('action').can_contain('\n'),
|
assert_true(reg.group('action').can_contain('\n'),
|
||||||
'Group "action" from regex "{}" can contains "{}"'.format(source, '\\n'))
|
'Group "action" from regex "{src}" can contains {sym!r}'.format(src=source, sym='\\n'))
|
||||||
|
|
||||||
assert_true(reg.group(1).can_contain('\n'),
|
assert_true(reg.group(1).can_contain('\n'),
|
||||||
'Group 1 from regex "{}" can contains "{}"'.format(source, '\\n'))
|
'Group 1 from regex "{src}" can contains {sym!r}'.format(src=source, sym='\\n'))
|
||||||
|
|
||||||
assert_false(reg.group('action').can_contain('/'),
|
assert_false(reg.group('action').can_contain('/'),
|
||||||
'Group "action" from regex "{}" CAN\'T (!) contain "{}"'.format(source, '/'))
|
'Group "action" from regex "{src}" CAN\'T (!) contain {sym!r}'.format(src=source, sym='/'))
|
||||||
|
|
||||||
|
|
||||||
def check_positive_contain(regexp, char):
|
def check_positive_contain(regexp, char):
|
||||||
reg = Regexp(regexp, case_sensitive=True)
|
reg = Regexp(regexp, case_sensitive=True)
|
||||||
assert_true(reg.can_contain(char),
|
assert_true(reg.can_contain(char),
|
||||||
'"{}" should contain "{}"'.format(regexp, char))
|
'{reg!r} should contain {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
reg = Regexp(regexp, case_sensitive=False)
|
reg = Regexp(regexp, case_sensitive=False)
|
||||||
char = char.upper()
|
char = char.upper()
|
||||||
assert_true(reg.can_contain(char),
|
assert_true(reg.can_contain(char),
|
||||||
'"{}" (case insensitive) should contain "{}"'.format(regexp, char))
|
'{reg!r} (case insensitive) should contain {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
|
|
||||||
def check_negative_contain(regexp, char):
|
def check_negative_contain(regexp, char):
|
||||||
reg = Regexp(regexp, case_sensitive=True)
|
reg = Regexp(regexp, case_sensitive=True)
|
||||||
assert_false(reg.can_contain(char),
|
assert_false(reg.can_contain(char),
|
||||||
'"{}" should not contain "{}"'.format(regexp, char))
|
'{reg!r} should not contain {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
reg = Regexp(regexp, case_sensitive=False)
|
reg = Regexp(regexp, case_sensitive=False)
|
||||||
char = char.upper()
|
char = char.upper()
|
||||||
assert_false(reg.can_contain(char),
|
assert_false(reg.can_contain(char),
|
||||||
'"{}" (case insensitive) should not contain "{}"'.format(regexp, char))
|
'{reg!r} (case insensitive) should not contain {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
|
|
||||||
def check_positive_startswith(regexp, char, strict):
|
def check_positive_startswith(regexp, char, strict):
|
||||||
reg = Regexp(regexp, case_sensitive=True, strict=strict)
|
reg = Regexp(regexp, case_sensitive=True, strict=strict)
|
||||||
assert_true(reg.can_startswith(char),
|
assert_true(reg.can_startswith(char),
|
||||||
'"{}" can start\'s with "{}"'.format(regexp, char))
|
'{reg!r} can start\'s with {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
reg = Regexp(regexp, case_sensitive=False, strict=strict)
|
reg = Regexp(regexp, case_sensitive=False, strict=strict)
|
||||||
char = char.upper()
|
char = char.upper()
|
||||||
assert_true(reg.can_startswith(char),
|
assert_true(reg.can_startswith(char),
|
||||||
'"{}" (case insensitive) can start\'s with "{}"'.format(regexp, char))
|
'{reg!r} (case insensitive) can start\'s with {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
|
|
||||||
def check_negative_startswith(regexp, char, strict):
|
def check_negative_startswith(regexp, char, strict):
|
||||||
reg = Regexp(regexp, case_sensitive=True, strict=strict)
|
reg = Regexp(regexp, case_sensitive=True, strict=strict)
|
||||||
assert_false(reg.can_startswith(char),
|
assert_false(reg.can_startswith(char),
|
||||||
'"{}" can\'t start\'s with "{}"'.format(regexp, char))
|
'{reg!r} can\'t start\'s with {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
reg = Regexp(regexp, case_sensitive=False, strict=strict)
|
reg = Regexp(regexp, case_sensitive=False, strict=strict)
|
||||||
char = char.upper()
|
char = char.upper()
|
||||||
assert_false(reg.can_startswith(char),
|
assert_false(reg.can_startswith(char),
|
||||||
'"{}" (case insensitive) can\'t start\'s with "{}"'.format(regexp, char))
|
'{reg!r} (case insensitive) can\'t start\'s with {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
|
|
||||||
def check_groups_names(regexp, groups):
|
def check_groups_names(regexp, groups):
|
||||||
|
@ -356,45 +356,46 @@ def check_to_string(regexp, string):
|
||||||
def check_positive_must_contain(regexp, char):
|
def check_positive_must_contain(regexp, char):
|
||||||
reg = Regexp(regexp, case_sensitive=True)
|
reg = Regexp(regexp, case_sensitive=True)
|
||||||
assert_true(reg.must_contain(char),
|
assert_true(reg.must_contain(char),
|
||||||
'"{}" must contain with "{}"'.format(regexp, char))
|
'{reg!r} must contain with {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
reg = Regexp(regexp, case_sensitive=False)
|
reg = Regexp(regexp, case_sensitive=False)
|
||||||
char = char.upper()
|
char = char.upper()
|
||||||
assert_true(reg.must_contain(char),
|
assert_true(reg.must_contain(char),
|
||||||
'"{}" (case insensitive) must contain with "{}"'.format(regexp, char))
|
'{reg!r} (case insensitive) must contain with {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
|
|
||||||
def check_negative_must_contain(regexp, char):
|
def check_negative_must_contain(regexp, char):
|
||||||
reg = Regexp(regexp, case_sensitive=True)
|
reg = Regexp(regexp, case_sensitive=True)
|
||||||
assert_false(reg.must_contain(char),
|
assert_false(reg.must_contain(char),
|
||||||
'"{}" must NOT contain with "{}"'.format(regexp, char))
|
'{reg!r} must NOT contain with {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
reg = Regexp(regexp, case_sensitive=False)
|
reg = Regexp(regexp, case_sensitive=False)
|
||||||
char = char.upper()
|
char = char.upper()
|
||||||
assert_false(reg.must_contain(char),
|
assert_false(reg.must_contain(char),
|
||||||
'"{}" (case insensitive) must NOT contain with "{}"'.format(regexp, char))
|
'{reg!r} (case insensitive) must NOT contain with {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
|
|
||||||
def check_positive_must_startswith(regexp, char, strict):
|
def check_positive_must_startswith(regexp, char, strict):
|
||||||
reg = Regexp(regexp, case_sensitive=True, strict=strict)
|
reg = Regexp(regexp, case_sensitive=True, strict=strict)
|
||||||
assert_true(reg.must_startswith(char),
|
assert_true(reg.must_startswith(char),
|
||||||
'"{}" MUST start\'s with "{}"'.format(regexp, char))
|
'{reg!r} MUST start\'s with {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
reg = Regexp(regexp, case_sensitive=False, strict=strict)
|
reg = Regexp(regexp, case_sensitive=False, strict=strict)
|
||||||
char = char.upper()
|
char = char.upper()
|
||||||
assert_true(reg.must_startswith(char),
|
assert_true(reg.must_startswith(char),
|
||||||
'"{}" (case insensitive) MUST start\'s with "{}"'.format(regexp, char))
|
'{reg!r} (case insensitive) MUST start\'s with {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
|
|
||||||
def check_negative_must_startswith(regexp, char, strict):
|
def check_negative_must_startswith(regexp, char, strict):
|
||||||
reg = Regexp(regexp, case_sensitive=True, strict=strict)
|
reg = Regexp(regexp, case_sensitive=True, strict=strict)
|
||||||
assert_false(reg.must_startswith(char),
|
assert_false(reg.must_startswith(char),
|
||||||
'"{}" MUST NOT start\'s with "{}"'.format(regexp, char))
|
'{reg!r} MUST NOT start\'s with {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
reg = Regexp(regexp, case_sensitive=False, strict=strict)
|
reg = Regexp(regexp, case_sensitive=False, strict=strict)
|
||||||
char = char.upper()
|
char = char.upper()
|
||||||
assert_false(reg.must_startswith(char),
|
assert_false(reg.must_startswith(char),
|
||||||
'"{}" (case insensitive) MUST NOT start\'s with "{}"'.format(regexp, char))
|
'{reg!r} (case insensitive) MUST NOT start\'s with {chr!r}'.format(reg=regexp, chr=char))
|
||||||
|
|
||||||
|
|
||||||
def check_generate(regexp, values):
|
def check_generate(regexp, values):
|
||||||
reg = Regexp(regexp)
|
reg = Regexp(regexp)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from nose.tools import assert_equals, assert_is_instance, assert_is_not_none, assert_is_none, assert_true, assert_false
|
from nose.tools import assert_equals, assert_true, assert_false
|
||||||
|
from tests.asserts import assert_is_instance, assert_is_none, assert_is_not_none
|
||||||
from gixy.parser.nginx_parser import NginxParser
|
from gixy.parser.nginx_parser import NginxParser
|
||||||
from gixy.directives.block import *
|
from gixy.directives.block import *
|
||||||
|
|
||||||
|
@ -148,7 +149,7 @@ def test_block_some_flat():
|
||||||
'''
|
'''
|
||||||
|
|
||||||
directive = _get_parsed(config)
|
directive = _get_parsed(config)
|
||||||
for d in {'default_type', 'sendfile', 'keepalive_timeout'}:
|
for d in ['default_type', 'sendfile', 'keepalive_timeout']:
|
||||||
c = directive.some(d, flat=True)
|
c = directive.some(d, flat=True)
|
||||||
assert_is_not_none(c)
|
assert_is_not_none(c)
|
||||||
assert_equals(c.name, d)
|
assert_equals(c.name, d)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from nose.tools import assert_equals, assert_is_instance, assert_false, assert_true
|
from nose.tools import assert_equals, assert_false, assert_true
|
||||||
|
from tests.asserts import assert_is_instance
|
||||||
from gixy.parser.nginx_parser import NginxParser
|
from gixy.parser.nginx_parser import NginxParser
|
||||||
from gixy.directives.directive import *
|
from gixy.directives.directive import *
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from nose.tools import assert_is_instance, assert_equal
|
from nose.tools import assert_equal
|
||||||
|
from tests.asserts import assert_is_instance
|
||||||
from gixy.parser.nginx_parser import NginxParser
|
from gixy.parser.nginx_parser import NginxParser
|
||||||
from gixy.directives.directive import *
|
from gixy.directives.directive import *
|
||||||
from gixy.directives.block import *
|
from gixy.directives.block import *
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from nose.tools import assert_equals, assert_true, assert_in
|
from nose.tools import assert_equals, assert_true
|
||||||
|
from tests.asserts import assert_in
|
||||||
import os
|
import os
|
||||||
from os import path
|
from os import path
|
||||||
import json
|
import json
|
||||||
|
@ -55,9 +56,9 @@ def test_from_config():
|
||||||
for plugin in manager.plugins:
|
for plugin in manager.plugins:
|
||||||
plugin = plugin.name
|
plugin = plugin.name
|
||||||
assert_true(plugin in tested_plugins,
|
assert_true(plugin in tested_plugins,
|
||||||
'Plugin "{}" should have at least one simple test config'.format(plugin))
|
'Plugin {name!r} should have at least one simple test config'.format(name=plugin))
|
||||||
assert_true(plugin in tested_fp_plugins,
|
assert_true(plugin in tested_fp_plugins,
|
||||||
'Plugin "{}" should have at least one simple test config with false positive'.format(plugin))
|
'Plugin {name!r} should have at least one simple test config with false positive'.format(name=plugin))
|
||||||
|
|
||||||
|
|
||||||
def parse_plugin_options(config_path):
|
def parse_plugin_options(config_path):
|
||||||
|
|
4
tox.ini
4
tox.ini
|
@ -1,5 +1,5 @@
|
||||||
[tox]
|
[tox]
|
||||||
envlist = py27, py34, py35, py36, flake8
|
envlist = py26, py27, py34, py35, py36, flake8
|
||||||
skip_missing_interpreters = True
|
skip_missing_interpreters = True
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
|
@ -16,4 +16,4 @@ commands =
|
||||||
flake8 setup.py gixy
|
flake8 setup.py gixy
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
max_line_length = 120
|
max_line_length = 120
|
||||||
|
|
Loading…
Reference in New Issue