2014-10-25 01:24:05 +00:00
|
|
|
import os
|
2017-02-01 15:48:46 +00:00
|
|
|
import pytest
|
|
|
|
|
2016-02-16 19:59:33 +00:00
|
|
|
from pathod import language
|
|
|
|
from pathod.language import base, exceptions
|
2016-06-17 12:15:48 +00:00
|
|
|
|
2016-11-01 21:06:25 +00:00
|
|
|
from mitmproxy.test import tutils
|
2012-04-28 00:42:03 +00:00
|
|
|
|
2012-04-28 10:28:28 +00:00
|
|
|
|
2014-10-25 03:20:23 +00:00
|
|
|
def parse_request(s):
|
2015-06-07 01:18:33 +00:00
|
|
|
return language.parse_pathoc(s).next()
|
2014-10-25 03:20:23 +00:00
|
|
|
|
|
|
|
|
2015-05-17 04:42:59 +00:00
|
|
|
def test_times():
|
2015-06-07 01:18:33 +00:00
|
|
|
reqs = list(language.parse_pathoc("get:/:x5"))
|
2015-05-17 04:42:59 +00:00
|
|
|
assert len(reqs) == 5
|
|
|
|
assert not reqs[0].times
|
|
|
|
|
|
|
|
|
2015-05-02 09:27:11 +00:00
|
|
|
def test_caseless_literal():
|
|
|
|
class CL(base.CaselessLiteral):
|
|
|
|
TOK = "foo"
|
|
|
|
v = CL("foo")
|
|
|
|
assert v.expr()
|
|
|
|
assert v.values(language.Settings())
|
2015-04-23 19:35:17 +00:00
|
|
|
|
|
|
|
|
2015-05-03 00:53:28 +00:00
|
|
|
class TestTokValueNakedLiteral:
|
2015-06-18 16:12:11 +00:00
|
|
|
|
2012-10-23 22:32:53 +00:00
|
|
|
def test_expr(self):
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValueNakedLiteral("foo")
|
2012-10-23 22:32:53 +00:00
|
|
|
assert v.expr()
|
2012-04-28 00:42:03 +00:00
|
|
|
|
2012-10-23 22:32:53 +00:00
|
|
|
def test_spec(self):
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValueNakedLiteral("foo")
|
2012-10-23 22:32:53 +00:00
|
|
|
assert v.spec() == repr(v) == "foo"
|
2012-04-28 00:42:03 +00:00
|
|
|
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValueNakedLiteral("f\x00oo")
|
2012-10-23 22:32:53 +00:00
|
|
|
assert v.spec() == repr(v) == r"f\x00oo"
|
2012-04-28 00:42:03 +00:00
|
|
|
|
2012-04-28 01:16:51 +00:00
|
|
|
|
2015-05-03 00:53:28 +00:00
|
|
|
class TestTokValueLiteral:
|
2015-06-18 16:12:11 +00:00
|
|
|
|
2016-06-04 12:58:03 +00:00
|
|
|
def test_expr(self):
|
2015-05-03 00:53:28 +00:00
|
|
|
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"
|
2012-07-21 02:12:45 +00:00
|
|
|
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValueLiteral("foo\n")
|
2012-07-21 02:12:45 +00:00
|
|
|
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
|
|
|
|
2012-10-23 22:32:53 +00:00
|
|
|
def test_spec(self):
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValueLiteral("foo")
|
2014-10-25 23:56:28 +00:00
|
|
|
assert v.spec() == r"'foo'"
|
2012-10-23 22:32:53 +00:00
|
|
|
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValueLiteral("f\x00oo")
|
2014-10-25 23:56:28 +00:00
|
|
|
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'"
|
2012-10-23 22:32:53 +00:00
|
|
|
|
2014-10-26 03:27:25 +00:00
|
|
|
def roundtrip(self, spec):
|
2015-05-03 00:53:28 +00:00
|
|
|
e = base.TokValueLiteral.expr()
|
|
|
|
v = base.TokValueLiteral(spec)
|
2014-10-26 03:27:25 +00:00
|
|
|
v2 = e.parseString(v.spec())
|
2015-09-21 21:03:45 +00:00
|
|
|
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("'")
|
2016-05-26 03:11:34 +00:00
|
|
|
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,'\\''")
|
2015-05-02 22:11:51 +00:00
|
|
|
self.roundtrip("\a")
|
2012-10-30 20:32:21 +00:00
|
|
|
|
2012-10-23 22:32:53 +00:00
|
|
|
|
2015-05-03 00:53:28 +00:00
|
|
|
class TestTokValueGenerate:
|
2015-06-18 16:12:11 +00:00
|
|
|
|
2012-10-23 22:32:53 +00:00
|
|
|
def test_basic(self):
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValue.parseString("@10b")[0]
|
2012-10-23 22:32:53 +00:00
|
|
|
assert v.usize == 10
|
|
|
|
assert v.unit == "b"
|
|
|
|
assert v.bytes() == 10
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValue.parseString("@10")[0]
|
2012-10-23 22:32:53 +00:00
|
|
|
assert v.unit == "b"
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValue.parseString("@10k")[0]
|
2012-10-23 22:32:53 +00:00
|
|
|
assert v.bytes() == 10240
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValue.parseString("@10g")[0]
|
2015-05-30 05:43:01 +00:00
|
|
|
assert v.bytes() == 1024 ** 3 * 10
|
2012-06-28 22:42:15 +00:00
|
|
|
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValue.parseString("@10g,digits")[0]
|
2012-10-23 22:32:53 +00:00
|
|
|
assert v.datatype == "digits"
|
|
|
|
g = v.get_generator({})
|
|
|
|
assert g[:100]
|
|
|
|
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValue.parseString("@10,digits")[0]
|
2012-10-23 22:32:53 +00:00
|
|
|
assert v.unit == "b"
|
|
|
|
assert v.datatype == "digits"
|
|
|
|
|
|
|
|
def test_spec(self):
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValueGenerate(1, "b", "bytes")
|
2012-10-23 22:32:53 +00:00
|
|
|
assert v.spec() == repr(v) == "@1"
|
|
|
|
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValueGenerate(1, "k", "bytes")
|
2012-10-23 22:32:53 +00:00
|
|
|
assert v.spec() == repr(v) == "@1k"
|
|
|
|
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValueGenerate(1, "k", "ascii")
|
2012-10-23 22:32:53 +00:00
|
|
|
assert v.spec() == repr(v) == "@1k,ascii"
|
|
|
|
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValueGenerate(1, "b", "ascii")
|
2012-10-23 22:32:53 +00:00
|
|
|
assert v.spec() == repr(v) == "@1,ascii"
|
|
|
|
|
2012-10-30 20:32:21 +00:00
|
|
|
def test_freeze(self):
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValueGenerate(100, "b", "ascii")
|
2015-04-22 03:49:17 +00:00
|
|
|
f = v.freeze(language.Settings())
|
2012-10-30 20:32:21 +00:00
|
|
|
assert len(f.val) == 100
|
|
|
|
|
2012-10-23 22:32:53 +00:00
|
|
|
|
2015-05-03 00:53:28 +00:00
|
|
|
class TestTokValueFile:
|
2015-06-18 16:12:11 +00:00
|
|
|
|
2012-04-28 01:16:51 +00:00
|
|
|
def test_file_value(self):
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValue.parseString("<'one two'")[0]
|
2012-04-28 10:28:28 +00:00
|
|
|
assert str(v)
|
2012-04-28 01:16:51 +00:00
|
|
|
assert v.path == "one two"
|
|
|
|
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValue.parseString("<path")[0]
|
2012-04-28 01:16:51 +00:00
|
|
|
assert v.path == "path"
|
|
|
|
|
2012-10-23 22:32:53 +00:00
|
|
|
def test_access_control(self):
|
2015-05-03 00:53:28 +00:00
|
|
|
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
|
|
|
|
2015-04-22 03:49:17 +00:00
|
|
|
assert v.get_generator(language.Settings(staticdir=t))
|
2012-04-28 01:16:51 +00:00
|
|
|
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValue.parseString("<path2")[0]
|
2017-02-01 15:48:46 +00:00
|
|
|
with pytest.raises(exceptions.FileAccessDenied):
|
|
|
|
v.get_generator(language.Settings(staticdir=t))
|
|
|
|
with pytest.raises("access disabled"):
|
|
|
|
v.get_generator(language.Settings())
|
2012-07-22 11:46:56 +00:00
|
|
|
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValue.parseString("</outside")[0]
|
2017-02-01 15:48:46 +00:00
|
|
|
with pytest.raises("outside"):
|
|
|
|
v.get_generator(language.Settings(staticdir=t))
|
2012-04-28 01:16:51 +00:00
|
|
|
|
2012-10-23 22:32:53 +00:00
|
|
|
def test_spec(self):
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValue.parseString("<'one two'")[0]
|
|
|
|
v2 = base.TokValue.parseString(v.spec())[0]
|
2012-10-23 22:32:53 +00:00
|
|
|
assert v2.path == "one two"
|
2012-04-28 00:42:03 +00:00
|
|
|
|
2012-10-30 20:32:21 +00:00
|
|
|
def test_freeze(self):
|
2015-05-03 00:53:28 +00:00
|
|
|
v = base.TokValue.parseString("<'one two'")[0]
|
2012-10-30 20:32:21 +00:00
|
|
|
v2 = v.freeze({})
|
|
|
|
assert v2.path == v.path
|
|
|
|
|
2012-10-23 22:32:53 +00:00
|
|
|
|
|
|
|
class TestMisc:
|
2015-06-18 16:12:11 +00:00
|
|
|
|
2012-10-23 22:32:53 +00:00
|
|
|
def test_generators(self):
|
2015-05-03 00:53:28 +00:00
|
|
|
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'"
|
2012-10-29 03:31:35 +00:00
|
|
|
|
2016-05-29 11:33:20 +00:00
|
|
|
def test_value2(self):
|
2015-05-03 00:54:25 +00:00
|
|
|
class TT(base.Value):
|
2015-05-02 09:42:09 +00:00
|
|
|
preamble = "m"
|
|
|
|
e = TT.expr()
|
2012-10-29 03:31:35 +00:00
|
|
|
v = e.parseString("m'msg'")[0]
|
2016-05-30 19:43:50 +00:00
|
|
|
assert v.value.val == b"msg"
|
2012-10-29 03:31:35 +00:00
|
|
|
|
|
|
|
s = v.spec()
|
|
|
|
assert s == e.parseString(s)[0].spec()
|
|
|
|
|
2012-10-30 20:32:21 +00:00
|
|
|
v = e.parseString("m@100")[0]
|
|
|
|
v2 = v.freeze({})
|
|
|
|
v3 = v2.freeze({})
|
|
|
|
assert v2.value.val == v3.value.val
|
|
|
|
|
2015-05-15 21:42:47 +00:00
|
|
|
def test_fixedlengthvalue(self):
|
|
|
|
class TT(base.FixedLengthValue):
|
|
|
|
preamble = "m"
|
|
|
|
length = 4
|
|
|
|
|
|
|
|
e = TT.expr()
|
|
|
|
assert e.parseString("m@4")
|
2017-02-01 15:48:46 +00:00
|
|
|
with pytest.raises("invalid value length"):
|
|
|
|
e.parseString("m@100")
|
|
|
|
with pytest.raises("invalid value length"):
|
|
|
|
e.parseString("m@1")
|
2015-05-15 21:42:47 +00:00
|
|
|
|
|
|
|
with tutils.tmpdir() as t:
|
|
|
|
p = os.path.join(t, "path")
|
|
|
|
s = base.Settings(staticdir=t)
|
|
|
|
with open(p, "wb") as f:
|
2016-06-04 12:58:50 +00:00
|
|
|
f.write(b"a" * 20)
|
2015-05-15 21:42:47 +00:00
|
|
|
v = e.parseString("m<path")[0]
|
2017-02-01 15:48:46 +00:00
|
|
|
with pytest.raises("invalid value length"):
|
|
|
|
v.values(s)
|
2015-05-15 21:42:47 +00:00
|
|
|
|
|
|
|
p = os.path.join(t, "path")
|
|
|
|
with open(p, "wb") as f:
|
2016-06-04 12:58:50 +00:00
|
|
|
f.write(b"a" * 4)
|
2015-05-15 21:42:47 +00:00
|
|
|
v = e.parseString("m<path")[0]
|
|
|
|
assert v.values(s)
|
|
|
|
|
2012-10-29 03:31:35 +00:00
|
|
|
|
2015-05-02 10:32:57 +00:00
|
|
|
class TKeyValue(base.KeyValue):
|
|
|
|
preamble = "h"
|
2015-05-02 20:51:57 +00:00
|
|
|
|
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()
|
2012-04-28 05:28:40 +00:00
|
|
|
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
|
|
|
|
2012-10-29 03:31:35 +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
|
|
|
|
2012-10-29 03:31:35 +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()
|
2012-10-30 20:32:21 +00:00
|
|
|
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-01 15:48:46 +00:00
|
|
|
with pytest.raises("can't exceed"):
|
|
|
|
e.parseString("t5")
|
2015-05-03 01:54:52 +00:00
|
|
|
|
|
|
|
|
2015-05-02 09:27:11 +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"
|
2015-05-02 09:27:11 +00:00
|
|
|
|
|
|
|
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
|
2015-05-02 09:42:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_integer():
|
|
|
|
e = base.Integer.expr()
|
|
|
|
v = e.parseString("200")[0]
|
2016-06-05 17:51:50 +00:00
|
|
|
assert v.string() == b"200"
|
2015-05-02 09:42:09 +00:00
|
|
|
assert v.spec() == "200"
|
|
|
|
|
|
|
|
assert v.freeze({}).value == v.value
|
2015-05-03 22:48:35 +00:00
|
|
|
|
2015-05-16 23:31:02 +00:00
|
|
|
class BInt(base.Integer):
|
|
|
|
bounds = (1, 5)
|
|
|
|
|
2017-02-01 15:48:46 +00:00
|
|
|
with pytest.raises("must be between"):
|
|
|
|
BInt(0)
|
|
|
|
with pytest.raises("must be between"):
|
|
|
|
BInt(6)
|
2015-05-16 23:31:02 +00:00
|
|
|
assert BInt(5)
|
|
|
|
assert BInt(1)
|
|
|
|
assert BInt(3)
|
|
|
|
|
|
|
|
|
2015-05-03 22:48:35 +00:00
|
|
|
class TBoolean(base.Boolean):
|
|
|
|
name = "test"
|
|
|
|
|
|
|
|
|
2015-05-16 22:43:30 +00:00
|
|
|
def test_unique_name():
|
|
|
|
b = TBoolean(True)
|
|
|
|
assert b.unique_name
|
|
|
|
|
|
|
|
|
2016-10-17 04:29:45 +00:00
|
|
|
class test_boolean:
|
2015-05-03 22:48:35 +00:00
|
|
|
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")
|