diff options
author | Thomas Kriechbaumer <Kriechi@users.noreply.github.com> | 2017-02-15 00:24:05 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-15 00:24:05 +0100 |
commit | bb2fa6dc7d871d703c6759926521d8c16aae80f1 (patch) | |
tree | 63439432d40bd5f0740000b71da0dc6df6053e3c /test/pathod/language/test_base.py | |
parent | a3436897ad8c504c08cff40bcddd7915c13a4712 (diff) | |
parent | 4d973e82959f5aecab8313b43ce1ab484f21b536 (diff) | |
download | mitmproxy-bb2fa6dc7d871d703c6759926521d8c16aae80f1.tar.gz mitmproxy-bb2fa6dc7d871d703c6759926521d8c16aae80f1.tar.bz2 mitmproxy-bb2fa6dc7d871d703c6759926521d8c16aae80f1.zip |
Merge pull request #2026 from Kriechi/filename-matching
add filename-matching linter
Diffstat (limited to 'test/pathod/language/test_base.py')
-rw-r--r-- | test/pathod/language/test_base.py | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/test/pathod/language/test_base.py b/test/pathod/language/test_base.py new file mode 100644 index 00000000..85e9e53b --- /dev/null +++ b/test/pathod/language/test_base.py @@ -0,0 +1,354 @@ +import os +import pytest + +from pathod import language +from pathod.language import base, exceptions + +from mitmproxy.test import tutils + + +def parse_request(s): + return language.parse_pathoc(s).next() + + +def test_times(): + reqs = list(language.parse_pathoc("get:/:x5")) + assert len(reqs) == 5 + assert not reqs[0].times + + +def test_caseless_literal(): + class CL(base.CaselessLiteral): + TOK = "foo" + v = CL("foo") + assert v.expr() + assert v.values(language.Settings()) + + +class TestTokValueNakedLiteral: + + def test_expr(self): + v = base.TokValueNakedLiteral("foo") + assert v.expr() + + def test_spec(self): + v = base.TokValueNakedLiteral("foo") + assert v.spec() == repr(v) == "foo" + + v = base.TokValueNakedLiteral("f\x00oo") + assert v.spec() == repr(v) == r"f\x00oo" + + +class TestTokValueLiteral: + + def test_expr(self): + v = base.TokValueLiteral("foo") + assert v.expr() + assert v.val == b"foo" + + v = base.TokValueLiteral("foo\n") + assert v.expr() + assert v.val == b"foo\n" + assert repr(v) + + def test_spec(self): + v = base.TokValueLiteral("foo") + assert v.spec() == r"'foo'" + + v = base.TokValueLiteral("f\x00oo") + assert v.spec() == repr(v) == r"'f\x00oo'" + + v = base.TokValueLiteral('"') + assert v.spec() == repr(v) == """ '"' """.strip() + + # While pyparsing has a escChar argument for QuotedString, + # escChar only performs scapes single-character escapes and does not work for e.g. r"\x02". + # Thus, we cannot use that option, which means we cannot have single quotes in strings. + # To fix this, we represent single quotes as r"\x07". + v = base.TokValueLiteral("'") + assert v.spec() == r"'\x27'" + + def roundtrip(self, spec): + e = base.TokValueLiteral.expr() + v = base.TokValueLiteral(spec) + v2 = e.parseString(v.spec()) + assert v.val == v2[0].val + assert v.spec() == v2[0].spec() + + def test_roundtrip(self): + self.roundtrip("'") + self.roundtrip(r"\'") + self.roundtrip("a") + self.roundtrip("\"") + # self.roundtrip("\\") + self.roundtrip("200:b'foo':i23,'\\''") + self.roundtrip("\a") + + +class TestTokValueGenerate: + + def test_basic(self): + v = base.TokValue.parseString("@10b")[0] + assert v.usize == 10 + assert v.unit == "b" + assert v.bytes() == 10 + v = base.TokValue.parseString("@10")[0] + assert v.unit == "b" + v = base.TokValue.parseString("@10k")[0] + assert v.bytes() == 10240 + v = base.TokValue.parseString("@10g")[0] + assert v.bytes() == 1024 ** 3 * 10 + + v = base.TokValue.parseString("@10g,digits")[0] + assert v.datatype == "digits" + g = v.get_generator({}) + assert g[:100] + + v = base.TokValue.parseString("@10,digits")[0] + assert v.unit == "b" + assert v.datatype == "digits" + + def test_spec(self): + v = base.TokValueGenerate(1, "b", "bytes") + assert v.spec() == repr(v) == "@1" + + v = base.TokValueGenerate(1, "k", "bytes") + assert v.spec() == repr(v) == "@1k" + + v = base.TokValueGenerate(1, "k", "ascii") + assert v.spec() == repr(v) == "@1k,ascii" + + v = base.TokValueGenerate(1, "b", "ascii") + assert v.spec() == repr(v) == "@1,ascii" + + def test_freeze(self): + v = base.TokValueGenerate(100, "b", "ascii") + f = v.freeze(language.Settings()) + assert len(f.val) == 100 + + +class TestTokValueFile: + + def test_file_value(self): + v = base.TokValue.parseString("<'one two'")[0] + assert str(v) + assert v.path == "one two" + + v = base.TokValue.parseString("<path")[0] + assert v.path == "path" + + def test_access_control(self): + v = base.TokValue.parseString("<path")[0] + with tutils.tmpdir() as t: + p = os.path.join(t, "path") + with open(p, "wb") as f: + f.write(b"x" * 10000) + + assert v.get_generator(language.Settings(staticdir=t)) + + v = base.TokValue.parseString("<path2")[0] + with pytest.raises(exceptions.FileAccessDenied): + v.get_generator(language.Settings(staticdir=t)) + with pytest.raises(Exception, match="access disabled"): + v.get_generator(language.Settings()) + + v = base.TokValue.parseString("</outside")[0] + with pytest.raises(Exception, match="outside"): + v.get_generator(language.Settings(staticdir=t)) + + def test_spec(self): + v = base.TokValue.parseString("<'one two'")[0] + v2 = base.TokValue.parseString(v.spec())[0] + assert v2.path == "one two" + + def test_freeze(self): + v = base.TokValue.parseString("<'one two'")[0] + v2 = v.freeze({}) + assert v2.path == v.path + + +class TestMisc: + + def test_generators(self): + v = base.TokValue.parseString("'val'")[0] + g = v.get_generator({}) + assert g[:] == b"val" + + def test_value(self): + assert base.TokValue.parseString("'val'")[0].val == b"val" + assert base.TokValue.parseString('"val"')[0].val == b"val" + assert base.TokValue.parseString('"\'val\'"')[0].val == b"'val'" + + def test_value2(self): + class TT(base.Value): + preamble = "m" + e = TT.expr() + v = e.parseString("m'msg'")[0] + assert v.value.val == b"msg" + + s = v.spec() + assert s == e.parseString(s)[0].spec() + + v = e.parseString("m@100")[0] + v2 = v.freeze({}) + v3 = v2.freeze({}) + assert v2.value.val == v3.value.val + + def test_fixedlengthvalue(self, tmpdir): + class TT(base.FixedLengthValue): + preamble = "m" + length = 4 + + e = TT.expr() + assert e.parseString("m@4") + with pytest.raises(Exception, match="Invalid value length"): + e.parseString("m@100") + with pytest.raises(Exception, match="Invalid value length"): + e.parseString("m@1") + + s = base.Settings(staticdir=str(tmpdir)) + tmpdir.join("path").write_binary(b"a" * 20, ensure=True) + v = e.parseString("m<path")[0] + with pytest.raises(Exception, match="Invalid value length"): + v.values(s) + + tmpdir.join("path2").write_binary(b"a" * 4, ensure=True) + v = e.parseString("m<path2")[0] + assert v.values(s) + + +class TKeyValue(base.KeyValue): + preamble = "h" + + def values(self, settings): + return [ + self.key.get_generator(settings), + ": ", + self.value.get_generator(settings), + "\r\n", + ] + + +class TestKeyValue: + + def test_simple(self): + e = TKeyValue.expr() + v = e.parseString("h'foo'='bar'")[0] + assert v.key.val == b"foo" + assert v.value.val == b"bar" + + v2 = e.parseString(v.spec())[0] + assert v2.key.val == v.key.val + assert v2.value.val == v.value.val + + s = v.spec() + assert s == e.parseString(s)[0].spec() + + def test_freeze(self): + e = TKeyValue.expr() + v = e.parseString("h@10=@10'")[0] + v2 = v.freeze({}) + v3 = v2.freeze({}) + assert v2.key.val == v3.key.val + assert v2.value.val == v3.value.val + + +def test_intfield(): + class TT(base.IntField): + preamble = "t" + names = { + "one": 1, + "two": 2, + "three": 3 + } + max = 4 + e = TT.expr() + + v = e.parseString("tone")[0] + assert v.value == 1 + assert v.spec() == "tone" + assert v.values(language.Settings()) + + v = e.parseString("t1")[0] + assert v.value == 1 + assert v.spec() == "t1" + + v = e.parseString("t4")[0] + assert v.value == 4 + assert v.spec() == "t4" + + with pytest.raises(Exception, match="can't exceed"): + e.parseString("t5") + + +def test_options_or_value(): + class TT(base.OptionsOrValue): + options = [ + "one", + "two", + "three" + ] + e = TT.expr() + assert e.parseString("one")[0].value.val == b"one" + assert e.parseString("'foo'")[0].value.val == b"foo" + assert e.parseString("'get'")[0].value.val == b"get" + + assert e.parseString("one")[0].spec() == "one" + assert e.parseString("'foo'")[0].spec() == "'foo'" + + s = e.parseString("one")[0].spec() + assert s == e.parseString(s)[0].spec() + + s = e.parseString("'foo'")[0].spec() + assert s == e.parseString(s)[0].spec() + + v = e.parseString("@100")[0] + v2 = v.freeze({}) + v3 = v2.freeze({}) + assert v2.value.val == v3.value.val + + +def test_integer(): + e = base.Integer.expr() + v = e.parseString("200")[0] + assert v.string() == b"200" + assert v.spec() == "200" + + assert v.freeze({}).value == v.value + + class BInt(base.Integer): + bounds = (1, 5) + + with pytest.raises(Exception, match="must be between"): + BInt(0) + with pytest.raises(Exception, match="must be between"): + BInt(6) + assert BInt(5) + assert BInt(1) + assert BInt(3) + + +class TBoolean(base.Boolean): + name = "test" + + +def test_unique_name(): + b = TBoolean(True) + assert b.unique_name + + +class test_boolean: + e = TBoolean.expr() + assert e.parseString("test")[0].value + assert not e.parseString("-test")[0].value + + def roundtrip(s): + e = TBoolean.expr() + s2 = e.parseString(s)[0].spec() + v1 = e.parseString(s)[0].value + v2 = e.parseString(s2)[0].value + assert s == s2 + assert v1 == v2 + + roundtrip("test") + roundtrip("-test") |