mitmproxy/test/pathod/language/test_base.py

355 lines
9.4 KiB
Python
Raw Normal View History

2014-10-25 01:24:05 +00:00
import os
import pytest
2016-02-16 19:59:33 +00:00
from pathod import language
from pathod.language import base, exceptions
from mitmproxy.test import tutils
2012-04-28 00:42:03 +00:00
def parse_request(s):
return language.parse_pathoc(s).next()
2015-05-17 04:42:59 +00:00
def test_times():
reqs = list(language.parse_pathoc("get:/:x5"))
2015-05-17 04:42:59 +00:00
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:
2015-06-18 16:12:11 +00:00
def test_expr(self):
v = base.TokValueNakedLiteral("foo")
assert v.expr()
2012-04-28 00:42:03 +00:00
def test_spec(self):
v = base.TokValueNakedLiteral("foo")
assert v.spec() == repr(v) == "foo"
2012-04-28 00:42:03 +00:00
v = base.TokValueNakedLiteral("f\x00oo")
assert v.spec() == repr(v) == r"f\x00oo"
2012-04-28 00:42:03 +00:00
2012-04-28 01:16:51 +00:00
class TestTokValueLiteral:
2015-06-18 16:12:11 +00:00
2016-06-04 12:58:03 +00:00
def test_expr(self):
v = base.TokValueLiteral("foo")
2012-04-28 00:42:03 +00:00
assert v.expr()
2016-05-30 19:43:50 +00:00
assert v.val == b"foo"
v = base.TokValueLiteral("foo\n")
assert v.expr()
2016-05-30 19:43:50 +00:00
assert v.val == b"foo\n"
2012-07-23 07:25:57 +00:00
assert repr(v)
2012-04-28 00:42:03 +00:00
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'"
2016-06-06 20:31:44 +00:00
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'"
2014-10-26 03:27:25 +00:00
def roundtrip(self, spec):
e = base.TokValueLiteral.expr()
v = base.TokValueLiteral(spec)
2014-10-26 03:27:25 +00:00
v2 = e.parseString(v.spec())
assert v.val == v2[0].val
assert v.spec() == v2[0].spec()
2014-10-26 03:27:25 +00:00
def test_roundtrip(self):
self.roundtrip("'")
self.roundtrip(r"\'")
2014-10-26 03:27:25 +00:00
self.roundtrip("a")
self.roundtrip("\"")
2015-05-30 00:03:13 +00:00
# self.roundtrip("\\")
2014-10-26 03:27:25 +00:00
self.roundtrip("200:b'foo':i23,'\\''")
self.roundtrip("\a")
class TestTokValueGenerate:
2015-06-18 16:12:11 +00:00
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:
2015-06-18 16:12:11 +00:00
2012-04-28 01:16:51 +00:00
def test_file_value(self):
v = base.TokValue.parseString("<'one two'")[0]
assert str(v)
2012-04-28 01:16:51 +00:00
assert v.path == "one two"
v = base.TokValue.parseString("<path")[0]
2012-04-28 01:16:51 +00:00
assert v.path == "path"
def test_access_control(self):
v = base.TokValue.parseString("<path")[0]
2012-06-09 03:08:51 +00:00
with tutils.tmpdir() as t:
p = os.path.join(t, "path")
2013-12-16 03:47:29 +00:00
with open(p, "wb") as f:
2016-06-04 12:58:50 +00:00
f.write(b"x" * 10000)
2012-04-28 01:16:51 +00:00
assert v.get_generator(language.Settings(staticdir=t))
2012-04-28 01:16:51 +00:00
v = base.TokValue.parseString("<path2")[0]
with pytest.raises(exceptions.FileAccessDenied):
v.get_generator(language.Settings(staticdir=t))
2017-02-06 16:48:44 +00:00
with pytest.raises(Exception, match="access disabled"):
v.get_generator(language.Settings())
v = base.TokValue.parseString("</outside")[0]
2017-02-06 16:48:44 +00:00
with pytest.raises(Exception, match="outside"):
v.get_generator(language.Settings(staticdir=t))
2012-04-28 01:16:51 +00:00
def test_spec(self):
v = base.TokValue.parseString("<'one two'")[0]
v2 = base.TokValue.parseString(v.spec())[0]
assert v2.path == "one two"
2012-04-28 00:42:03 +00:00
def test_freeze(self):
v = base.TokValue.parseString("<'one two'")[0]
v2 = v.freeze({})
assert v2.path == v.path
class TestMisc:
2015-06-18 16:12:11 +00:00
def test_generators(self):
v = base.TokValue.parseString("'val'")[0]
2012-04-28 00:42:03 +00:00
g = v.get_generator({})
2016-05-30 19:43:50 +00:00
assert g[:] == b"val"
2012-04-28 00:42:03 +00:00
def test_value(self):
2016-05-30 19:43:50 +00:00
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'"
2016-05-29 11:33:20 +00:00
def test_value2(self):
2015-05-03 00:54:25 +00:00
class TT(base.Value):
preamble = "m"
e = TT.expr()
v = e.parseString("m'msg'")[0]
2016-05-30 19:43:50 +00:00
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
2017-02-06 16:48:44 +00:00
def test_fixedlengthvalue(self, tmpdir):
class TT(base.FixedLengthValue):
preamble = "m"
length = 4
e = TT.expr()
assert e.parseString("m@4")
2017-02-06 16:48:44 +00:00
with pytest.raises(Exception, match="Invalid value length"):
e.parseString("m@100")
2017-02-06 16:48:44 +00:00
with pytest.raises(Exception, match="Invalid value length"):
e.parseString("m@1")
2017-02-06 16:48:44 +00:00
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)
2017-02-06 16:48:44 +00:00
tmpdir.join("path2").write_binary(b"a" * 4, ensure=True)
v = e.parseString("m<path2")[0]
assert v.values(s)
2015-05-02 10:32:57 +00:00
class TKeyValue(base.KeyValue):
preamble = "h"
2015-05-02 10:32:57 +00:00
def values(self, settings):
return [
self.key.get_generator(settings),
": ",
self.value.get_generator(settings),
"\r\n",
]
class TestKeyValue:
2015-06-18 16:12:11 +00:00
2015-05-02 10:32:57 +00:00
def test_simple(self):
e = TKeyValue.expr()
v = e.parseString("h'foo'='bar'")[0]
2016-05-30 19:43:50 +00:00
assert v.key.val == b"foo"
assert v.value.val == b"bar"
2012-04-28 00:42:03 +00:00
v2 = e.parseString(v.spec())[0]
assert v2.key.val == v.key.val
assert v2.value.val == v.value.val
2012-04-28 00:42:03 +00:00
s = v.spec()
assert s == e.parseString(s)[0].spec()
2012-04-28 00:42:03 +00:00
2015-05-02 10:32:57 +00:00
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
2012-04-28 00:42:03 +00:00
2015-05-03 01:54:52 +00:00
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"
2017-02-06 16:48:44 +00:00
with pytest.raises(Exception, match="can't exceed"):
e.parseString("t5")
2015-05-03 01:54:52 +00:00
def test_options_or_value():
class TT(base.OptionsOrValue):
options = [
"one",
"two",
"three"
]
e = TT.expr()
2016-05-30 19:43:50 +00:00
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)
2017-02-06 16:48:44 +00:00
with pytest.raises(Exception, match="must be between"):
BInt(0)
2017-02-06 16:48:44 +00:00
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
2016-10-17 04:29:45 +00:00
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")