Files
copyparty/tests/test_vfs.py

252 lines
8.4 KiB
Python
Raw Normal View History

2019-05-29 23:46:17 +00:00
#!/usr/bin/env python
# coding: utf-8
2019-06-12 16:39:43 +00:00
from __future__ import print_function, unicode_literals
2019-05-29 23:46:17 +00:00
import os
import json
import shutil
import unittest
2019-06-07 08:54:41 +00:00
import subprocess as sp # nosec
2019-05-29 23:46:17 +00:00
2019-05-31 18:03:44 +00:00
from textwrap import dedent
2019-05-29 23:46:17 +00:00
from argparse import Namespace
2019-06-07 08:54:41 +00:00
from copyparty.authsrv import AuthSrv
2019-06-07 18:42:15 +00:00
from copyparty import util
2019-05-29 23:46:17 +00:00
class TestVFS(unittest.TestCase):
def dump(self, vfs):
print(json.dumps(vfs, indent=4, sort_keys=True, default=lambda o: o.__dict__))
2019-05-30 13:17:45 +00:00
def unfoo(self, foo):
for k, v in {"foo": "a", "bar": "b", "baz": "c", "qux": "d"}.items():
foo = foo.replace(k, v)
return foo
def undot(self, vfs, query, response):
2019-06-07 18:42:15 +00:00
self.assertEqual(util.undot(query), response)
2019-05-30 13:17:45 +00:00
query = self.unfoo(query)
response = self.unfoo(response)
2019-06-07 18:42:15 +00:00
self.assertEqual(util.undot(query), response)
2019-05-30 13:17:45 +00:00
def absify(self, root, names):
return ["{}/{}".format(root, x).replace("//", "/") for x in names]
2019-06-10 01:23:13 +00:00
def ls(self, vfs, vpath, uname):
"""helper for resolving and listing a folder"""
vn, rem = vfs.get(vpath, uname, True, False)
return vn.ls(rem, uname)
2019-06-06 08:44:52 +02:00
def runcmd(self, *argv):
p = sp.Popen(argv, stdout=sp.PIPE, stderr=sp.PIPE)
stdout, stderr = p.communicate()
2019-06-07 08:54:41 +00:00
stdout = stdout.decode("utf-8")
stderr = stderr.decode("utf-8")
2019-06-06 08:44:52 +02:00
return [p.returncode, stdout, stderr]
def chkcmd(self, *argv):
ok, sout, serr = self.runcmd(*argv)
if ok != 0:
raise Exception(serr)
2019-06-07 08:54:41 +00:00
return sout, serr
2019-06-06 08:44:52 +02:00
def get_ramdisk(self):
2019-06-07 08:54:41 +00:00
for vol in ["/dev/shm", "/Volumes/cptd"]: # nosec (singleton test)
2019-06-06 08:44:52 +02:00
if os.path.exists(vol):
return vol
if os.path.exists("/Volumes"):
devname, _ = self.chkcmd("hdiutil", "attach", "-nomount", "ram://8192")
_, _ = self.chkcmd("diskutil", "eraseVolume", "HFS+", "cptd", devname)
return "/Volumes/cptd"
raise Exception("TODO support windows")
2019-05-29 23:46:17 +00:00
def test(self):
2019-06-06 08:44:52 +02:00
td = self.get_ramdisk() + "/vfs"
2019-05-29 23:46:17 +00:00
try:
shutil.rmtree(td)
2019-06-07 08:54:41 +00:00
except OSError:
2019-05-29 23:46:17 +00:00
pass
os.mkdir(td)
os.chdir(td)
for a in "abc":
for b in "abc":
for c in "abc":
folder = "{0}/{0}{1}/{0}{1}{2}".format(a, b, c)
os.makedirs(folder)
for d in "abc":
fn = "{}/{}{}{}{}".format(folder, a, b, c, d)
with open(fn, "w") as f:
f.write(fn)
# defaults
vfs = AuthSrv(Namespace(c=None, a=[], v=[]), None).vfs
self.assertEqual(vfs.nodes, {})
self.assertEqual(vfs.vpath, "")
self.assertEqual(vfs.realpath, td)
self.assertEqual(vfs.uread, ["*"])
self.assertEqual(vfs.uwrite, ["*"])
# single read-only rootfs (relative path)
vfs = AuthSrv(Namespace(c=None, a=[], v=["a/ab/::r"]), None).vfs
self.assertEqual(vfs.nodes, {})
self.assertEqual(vfs.vpath, "")
self.assertEqual(vfs.realpath, td + "/a/ab")
self.assertEqual(vfs.uread, ["*"])
self.assertEqual(vfs.uwrite, [])
# single read-only rootfs (absolute path)
vfs = AuthSrv(Namespace(c=None, a=[], v=[td + "//a/ac/../aa//::r"]), None).vfs
self.assertEqual(vfs.nodes, {})
self.assertEqual(vfs.vpath, "")
self.assertEqual(vfs.realpath, td + "/a/aa")
self.assertEqual(vfs.uread, ["*"])
self.assertEqual(vfs.uwrite, [])
2019-05-30 13:17:45 +00:00
# read-only rootfs with write-only subdirectory (read-write for k)
2019-05-29 23:46:17 +00:00
vfs = AuthSrv(
2019-05-30 13:17:45 +00:00
Namespace(c=None, a=["k:k"], v=[".::r:ak", "a/ac/acb:a/ac/acb:w:ak"]), None
2019-05-29 23:46:17 +00:00
).vfs
self.assertEqual(len(vfs.nodes), 1)
self.assertEqual(vfs.vpath, "")
self.assertEqual(vfs.realpath, td)
2019-05-30 13:17:45 +00:00
self.assertEqual(vfs.uread, ["*", "k"])
self.assertEqual(vfs.uwrite, ["k"])
2019-05-29 23:46:17 +00:00
n = vfs.nodes["a"]
self.assertEqual(len(vfs.nodes), 1)
self.assertEqual(n.vpath, "a")
self.assertEqual(n.realpath, td + "/a")
2019-05-30 13:17:45 +00:00
self.assertEqual(n.uread, ["*", "k"])
self.assertEqual(n.uwrite, ["k"])
2019-05-29 23:46:17 +00:00
n = n.nodes["ac"]
self.assertEqual(len(vfs.nodes), 1)
self.assertEqual(n.vpath, "a/ac")
self.assertEqual(n.realpath, td + "/a/ac")
2019-05-30 13:17:45 +00:00
self.assertEqual(n.uread, ["*", "k"])
self.assertEqual(n.uwrite, ["k"])
2019-05-29 23:46:17 +00:00
n = n.nodes["acb"]
self.assertEqual(n.nodes, {})
self.assertEqual(n.vpath, "a/ac/acb")
self.assertEqual(n.realpath, td + "/a/ac/acb")
2019-05-30 13:17:45 +00:00
self.assertEqual(n.uread, ["k"])
self.assertEqual(n.uwrite, ["*", "k"])
2019-06-10 01:23:13 +00:00
fsdir, real, virt = self.ls(vfs, "/", "*")
2019-06-07 18:42:15 +00:00
self.assertEqual(fsdir, td)
self.assertEqual(real, ["b", "c"])
2019-05-30 13:17:45 +00:00
self.assertEqual(virt, ["a"])
2019-06-10 01:23:13 +00:00
fsdir, real, virt = self.ls(vfs, "a", "*")
2019-06-07 18:42:15 +00:00
self.assertEqual(fsdir, td + "/a")
self.assertEqual(real, ["aa", "ab"])
2019-05-30 13:17:45 +00:00
self.assertEqual(virt, ["ac"])
2019-06-10 01:23:13 +00:00
fsdir, real, virt = self.ls(vfs, "a/ab", "*")
2019-06-07 18:42:15 +00:00
self.assertEqual(fsdir, td + "/a/ab")
self.assertEqual(real, ["aba", "abb", "abc"])
2019-05-30 13:17:45 +00:00
self.assertEqual(virt, [])
2019-06-10 01:23:13 +00:00
fsdir, real, virt = self.ls(vfs, "a/ac", "*")
2019-06-07 18:42:15 +00:00
self.assertEqual(fsdir, td + "/a/ac")
self.assertEqual(real, ["aca", "acc"])
2019-05-30 13:17:45 +00:00
self.assertEqual(virt, [])
2019-06-10 01:23:13 +00:00
fsdir, real, virt = self.ls(vfs, "a/ac", "k")
2019-06-07 18:42:15 +00:00
self.assertEqual(fsdir, td + "/a/ac")
self.assertEqual(real, ["aca", "acc"])
2019-05-30 13:17:45 +00:00
self.assertEqual(virt, ["acb"])
2019-06-10 01:23:13 +00:00
self.assertRaises(util.Pebkac, vfs.get, "a/ac/acb", "*", True, False)
2019-05-30 13:17:45 +00:00
2019-06-10 01:23:13 +00:00
fsdir, real, virt = self.ls(vfs, "a/ac/acb", "k")
2019-06-07 18:42:15 +00:00
self.assertEqual(fsdir, td + "/a/ac/acb")
self.assertEqual(real, ["acba", "acbb", "acbc"])
2019-05-30 13:17:45 +00:00
self.assertEqual(virt, [])
2019-05-29 23:46:17 +00:00
# breadth-first construction
vfs = AuthSrv(
Namespace(
c=None,
a=[],
v=[
"a/ac/acb:a/ac/acb:w",
"a:a:w",
".::r",
"abacdfasdq:abacdfasdq:w",
"a/ac:a/ac:w",
],
),
None,
).vfs
2019-05-30 13:17:45 +00:00
# sanitizing relative paths
self.undot(vfs, "foo/bar/../baz/qux", "foo/baz/qux")
self.undot(vfs, "foo/../bar", "bar")
self.undot(vfs, "foo/../../bar", "bar")
self.undot(vfs, "foo/../../", "")
self.undot(vfs, "./.././foo/", "foo")
self.undot(vfs, "./.././foo/..", "")
2019-05-29 23:46:17 +00:00
# shadowing
2019-05-30 13:17:45 +00:00
vfs = AuthSrv(Namespace(c=None, a=[], v=[".::r", "b:a/ac:r"]), None).vfs
2019-06-10 01:23:13 +00:00
fsp, r1, v1 = self.ls(vfs, "", "*")
2019-06-07 18:42:15 +00:00
self.assertEqual(fsp, td)
self.assertEqual(r1, ["b", "c"])
2019-05-30 13:17:45 +00:00
self.assertEqual(v1, ["a"])
2019-06-10 01:23:13 +00:00
fsp, r1, v1 = self.ls(vfs, "a", "*")
2019-06-07 18:42:15 +00:00
self.assertEqual(fsp, td + "/a")
self.assertEqual(r1, ["aa", "ab"])
2019-05-30 13:17:45 +00:00
self.assertEqual(v1, ["ac"])
2019-06-10 01:23:13 +00:00
fsp1, r1, v1 = self.ls(vfs, "a/ac", "*")
fsp2, r2, v2 = self.ls(vfs, "b", "*")
2019-06-07 18:42:15 +00:00
self.assertEqual(fsp1, td + "/b")
self.assertEqual(fsp2, td + "/b")
self.assertEqual(r1, ["ba", "bb", "bc"])
2019-05-30 13:17:45 +00:00
self.assertEqual(r1, r2)
self.assertEqual(v1, v2)
2019-05-29 23:46:17 +00:00
2019-05-31 18:03:44 +00:00
# config file parser
2019-06-06 08:44:52 +02:00
cfg_path = self.get_ramdisk() + "/test.cfg"
2019-05-31 18:03:44 +00:00
with open(cfg_path, "wb") as f:
f.write(
dedent(
"""
u a:123
u asd:fgh:jkl
./src
/dst
r a
a asd
"""
).encode("utf-8")
)
au = AuthSrv(Namespace(c=[cfg_path], a=[], v=[]), None)
self.assertEqual(au.user["a"], "123")
self.assertEqual(au.user["asd"], "fgh:jkl")
n = au.vfs
2019-06-06 08:47:01 +02:00
# root was not defined, so PWD with no access to anyone
2019-05-31 18:03:44 +00:00
self.assertEqual(n.vpath, "")
self.assertEqual(n.realpath, td)
2019-06-06 08:47:01 +02:00
self.assertEqual(n.uread, [])
self.assertEqual(n.uwrite, [])
2019-05-31 18:03:44 +00:00
self.assertEqual(len(n.nodes), 1)
n = n.nodes["dst"]
self.assertEqual(n.vpath, "dst")
self.assertEqual(n.realpath, td + "/src")
self.assertEqual(n.uread, ["a", "asd"])
self.assertEqual(n.uwrite, ["asd"])
self.assertEqual(len(n.nodes), 0)
2019-05-29 23:46:17 +00:00
shutil.rmtree(td)
2019-05-31 18:03:44 +00:00
os.unlink(cfg_path)