blob: 02bb44632c1df0aa878ca139165f7fa4a2025280 [file] [log] [blame]
#!/usr/bin/env python
# coding=utf-8
# Copyright 2019 The LUCI Authors. All rights reserved.
# Use of this source code is governed under the Apache License, Version 2.0
# that can be found in the LICENSE file.
import os
import tempfile
import unittest
# Mutates sys.path.
import test_env
from utils import file_path
from utils import fs
def write_content(path, content):
with fs.open(path, 'wb') as f:
f.write(content)
class FSTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
if not file_path.enable_symlink():
raise Exception('Failed to enable symlink support')
def setUp(self):
super(FSTest, self).setUp()
self._tempdir = None
def tearDown(self):
try:
if self._tempdir:
file_path.rmtree(self._tempdir)
finally:
super(FSTest, self).tearDown()
@property
def tempdir(self):
if not self._tempdir:
self._tempdir = tempfile.mkdtemp(prefix=u'fs_test')
return self._tempdir
def test_symlink_relative(self):
# A symlink to a relative path is valid.
# /dir
# /dir/file
# /ld -> /dir
# /lf -> /ld/file
dirpath = os.path.join(self.tempdir, 'dir')
filepath = os.path.join(dirpath, 'file')
fs.mkdir(dirpath)
write_content(filepath, 'hello')
linkfile = os.path.join(self.tempdir, 'lf')
linkdir = os.path.join(self.tempdir, 'ld')
dstfile = os.path.join('ld', 'file')
fs.symlink(dstfile, linkfile)
fs.symlink('dir', linkdir)
self.assertEqual(True, fs.islink(linkfile))
self.assertEqual(True, fs.islink(linkdir))
self.assertEqual(dstfile, fs.readlink(linkfile))
self.assertEqual('dir', fs.readlink(linkdir))
self.assertEqual(['file'], fs.listdir(linkdir))
# /lf resolves to /dir/file.
self.assertEqual('hello', fs.open(linkfile).read())
# Ensures that followlinks is respected in walk().
expected = [
(self.tempdir, ['dir', 'ld'], ['lf']),
(dirpath, [], ['file']),
]
actual = [
(r, sorted(d), sorted(f))
for r, d, f in sorted(fs.walk(self.tempdir, followlinks=False))
]
self.assertEqual(expected, actual)
expected = [
(self.tempdir, ['dir', 'ld'], ['lf']),
(dirpath, [], ['file']),
(linkdir, [], ['file']),
]
actual = [
(r, sorted(d), sorted(f))
for r, d, f in sorted(fs.walk(self.tempdir, followlinks=True))
]
self.assertEqual(expected, actual)
def test_symlink_absolute(self):
# A symlink to an absolute path is valid.
# /dir
# /dir/file
# /ld -> /dir
# /lf -> /ld/file
dirpath = os.path.join(self.tempdir, 'dir')
filepath = os.path.join(dirpath, 'file')
fs.mkdir(dirpath)
write_content(filepath, 'hello')
linkfile = os.path.join(self.tempdir, 'lf')
linkdir = os.path.join(self.tempdir, 'ld')
dstfile = os.path.join(linkdir, 'file')
fs.symlink(dstfile, linkfile)
fs.symlink(dirpath, linkdir)
self.assertEqual(True, fs.islink(linkfile))
self.assertEqual(True, fs.islink(linkdir))
self.assertEqual(dstfile, fs.readlink(linkfile))
self.assertEqual(dirpath, fs.readlink(linkdir))
self.assertEqual(['file'], fs.listdir(linkdir))
# /lf resolves to /dir/file.
self.assertEqual('hello', fs.open(linkfile).read())
# Ensures that followlinks is respected in walk().
expected = [
(self.tempdir, ['dir', 'ld'], ['lf']),
(dirpath, [], ['file']),
]
actual = [
(r, sorted(d), sorted(f))
for r, d, f in sorted(fs.walk(self.tempdir, followlinks=False))
]
self.assertEqual(expected, actual)
expected = [
(self.tempdir, ['dir', 'ld'], ['lf']),
(dirpath, [], ['file']),
(linkdir, [], ['file']),
]
actual = [
(r, sorted(d), sorted(f))
for r, d, f in sorted(fs.walk(self.tempdir, followlinks=True))
]
self.assertEqual(expected, actual)
def test_symlink_missing_destination_rel(self):
# A symlink to a missing destination is valid and can be read back.
filepath = 'file'
linkfile = os.path.join(self.tempdir, 'lf')
fs.symlink(filepath, linkfile)
self.assertEqual(True, fs.islink(linkfile))
self.assertEqual(filepath, fs.readlink(linkfile))
def test_symlink_missing_destination_abs(self):
# A symlink to a missing destination is valid and can be read back.
filepath = os.path.join(self.tempdir, 'file')
linkfile = os.path.join(self.tempdir, 'lf')
fs.symlink(filepath, linkfile)
self.assertEqual(True, fs.islink(linkfile))
self.assertEqual(filepath, fs.readlink(linkfile))
def test_symlink_existing(self):
# Creating a symlink that overrides a file fails.
filepath = os.path.join(self.tempdir, 'file')
linkfile = os.path.join(self.tempdir, 'lf')
write_content(linkfile, 'hello')
with self.assertRaises(OSError):
fs.symlink(filepath, linkfile)
def test_readlink_fail(self):
# Reading a non-existing symlink fails. Obvious but it's to make sure the
# Windows part acts the same.
with self.assertRaises(OSError):
fs.readlink(os.path.join(self.tempdir, 'not_there'))
if __name__ == '__main__':
test_env.main()