1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7from unittest.case import TestCase
8import oe, oe.path
9import tempfile
10import os
11import errno
12import shutil
13
14class TestRealPath(TestCase):
15    DIRS = [ "a", "b", "etc", "sbin", "usr", "usr/bin", "usr/binX", "usr/sbin", "usr/include", "usr/include/gdbm" ]
16    FILES = [ "etc/passwd", "b/file" ]
17    LINKS = [
18        ( "bin",             "/usr/bin",             "/usr/bin" ),
19        ( "binX",            "usr/binX",             "/usr/binX" ),
20        ( "c",               "broken",               "/broken" ),
21        ( "etc/passwd-1",    "passwd",               "/etc/passwd" ),
22        ( "etc/passwd-2",    "passwd-1",             "/etc/passwd" ),
23        ( "etc/passwd-3",    "/etc/passwd-1",        "/etc/passwd" ),
24        ( "etc/shadow-1",    "/etc/shadow",          "/etc/shadow" ),
25        ( "etc/shadow-2",    "/etc/shadow-1",        "/etc/shadow" ),
26        ( "prog-A",          "bin/prog-A",           "/usr/bin/prog-A" ),
27        ( "prog-B",          "/bin/prog-B",          "/usr/bin/prog-B" ),
28        ( "usr/bin/prog-C",  "../../sbin/prog-C",    "/sbin/prog-C" ),
29        ( "usr/bin/prog-D",  "/sbin/prog-D",         "/sbin/prog-D" ),
30        ( "usr/binX/prog-E", "../sbin/prog-E",       None ),
31        ( "usr/bin/prog-F",  "../../../sbin/prog-F", "/sbin/prog-F" ),
32        ( "loop",            "a/loop",               None ),
33        ( "a/loop",          "../loop",              None ),
34        ( "b/test",          "file/foo",             "/b/file/foo" ),
35    ]
36
37    LINKS_PHYS = [
38        ( "./",          "/",                "" ),
39        ( "binX/prog-E", "/usr/sbin/prog-E", "/sbin/prog-E" ),
40    ]
41
42    EXCEPTIONS = [
43        ( "loop",   errno.ELOOP ),
44        ( "b/test", errno.ENOENT ),
45    ]
46
47    def setUp(self):
48        self.tmpdir = tempfile.mkdtemp(prefix = "oe-test_path")
49        self.root = os.path.join(self.tmpdir, "R")
50
51        os.mkdir(os.path.join(self.tmpdir, "_real"))
52        os.symlink("_real", self.root)
53
54        for d in self.DIRS:
55            os.mkdir(os.path.join(self.root, d))
56        for f in self.FILES:
57            open(os.path.join(self.root, f), "w")
58        for l in self.LINKS:
59            os.symlink(l[1], os.path.join(self.root, l[0]))
60
61    def tearDown(self):
62        shutil.rmtree(self.tmpdir)
63
64    def __realpath(self, file, use_physdir, assume_dir = True):
65        return oe.path.realpath(os.path.join(self.root, file), self.root,
66                                use_physdir, assume_dir = assume_dir)
67
68    def test_norm(self):
69        for l in self.LINKS:
70            if l[2] == None:
71                continue
72
73            target_p = self.__realpath(l[0], True)
74            target_l = self.__realpath(l[0], False)
75
76            if l[2] != False:
77                self.assertEqual(target_p, target_l)
78                self.assertEqual(l[2], target_p[len(self.root):])
79
80    def test_phys(self):
81        for l in self.LINKS_PHYS:
82            target_p = self.__realpath(l[0], True)
83            target_l = self.__realpath(l[0], False)
84
85            self.assertEqual(l[1], target_p[len(self.root):])
86            self.assertEqual(l[2], target_l[len(self.root):])
87
88    def test_loop(self):
89        for e in self.EXCEPTIONS:
90            self.assertRaisesRegex(OSError, r'\[Errno %u\]' % e[1],
91                                    self.__realpath, e[0], False, False)
92