sapling/eden/integration/rename_test.py
John Reese 9fd86a4fae apply upgraded black 21.4b2 formatting to fbsource
Summary:
This applies the formatting changes from black v21.4b2 to all covered
projects in fbsource. Most changes are to single line docstrings, as black
will now remove leading and trailing whitespace to match PEP8. Any other
formatting changes are likely due to files that landed without formatting,
or files that previously triggered errors in black.

Any changes to code should be AST identical. Any test failures are likely
due to bad tests, or testing against the output of pyfmt.

Reviewed By: thatch

Differential Revision: D28204910

fbshipit-source-id: 804725bcd14f763e90c5ddff1d0418117c15809a
2021-05-04 22:16:51 -07:00

184 lines
6.3 KiB
Python

#!/usr/bin/env python3
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2.
import errno
import os
import time
from .lib import testcase
@testcase.eden_repo_test
class RenameTest(testcase.EdenRepoTest):
def populate_repo(self) -> None:
self.repo.write_file("hello", "hola\n")
self.repo.write_file("adir/file", "foo!\n")
self.repo.symlink("slink", "hello")
self.repo.commit("Initial commit.")
def test_rename_errors(self) -> None:
"""Test some error cases"""
with self.assertRaises(OSError) as context:
os.rename(
os.path.join(self.mount, "not-exist"),
os.path.join(self.mount, "also-not-exist"),
)
self.assertEqual(
errno.ENOENT, context.exception.errno, msg="Renaming a bogus file -> ENOENT"
)
def test_rename_dir(self) -> None:
filename = os.path.join(self.mount, "adir")
targetname = os.path.join(self.mount, "a-new-target")
os.rename(filename, targetname)
with self.assertRaises(OSError) as context:
os.lstat(filename)
self.assertEqual(
errno.ENOENT, context.exception.errno, msg="no longer visible as old name"
)
os.lstat(targetname)
# Check that adir/file is now visible in the new location
targetfile = os.path.join(targetname, "file")
with open(targetfile, "r") as f:
self.assertEqual("foo!\n", f.read())
def test_rename_away_tree_entry(self) -> None:
"""Rename a tree entry away and back again"""
# We should be able to rename files that are in the Tree
hello = os.path.join(self.mount, "hello")
targetname = os.path.join(self.mount, "a-new-target")
os.rename(hello, targetname)
with self.assertRaises(OSError) as context:
os.lstat(hello)
self.assertEqual(
errno.ENOENT, context.exception.errno, msg="no longer visible as old name"
)
self.assert_checkout_root_entries({".eden", "a-new-target", "adir", "slink"})
with open(targetname, "r") as f:
self.assertEqual("hola\n", f.read(), msg="materialized correct data")
# Now, while we hold this file open, check that a rename
# leaves the handle connected to the file contents when
# we rename it back to its old name.
os.rename(targetname, hello)
self.assert_checkout_root_entries({".eden", "adir", "hello", "slink"})
with open(hello, "r+") as write_f:
write_f.seek(0, os.SEEK_END)
write_f.write("woot")
f.seek(0)
self.assertEqual("hola\nwoot", f.read())
def test_rename_overlay_only(self) -> None:
"""Create a local/overlay only file and rename it"""
# We should be able to rename files that are in the Tree
from_name = os.path.join(self.mount, "overlay-a")
to_name = os.path.join(self.mount, "overlay-b")
with open(from_name, "w") as f:
f.write("overlay-a\n")
os.rename(from_name, to_name)
with self.assertRaises(OSError) as context:
os.lstat(from_name)
self.assertEqual(
errno.ENOENT, context.exception.errno, msg="no longer visible as old name"
)
self.assert_checkout_root_entries(
{".eden", "adir", "hello", "overlay-b", "slink"}
)
with open(to_name, "r") as f:
self.assertEqual("overlay-a\n", f.read(), msg="holds correct data")
# Now, while we hold this file open, check that a rename
# leaves the handle connected to the file contents when
# we rename it back to its old name.
os.rename(to_name, from_name)
self.assert_checkout_root_entries(
{".eden", "adir", "hello", "overlay-a", "slink"}
)
with open(from_name, "r+") as write_f:
write_f.seek(0, os.SEEK_END)
write_f.write("woot")
f.seek(0)
self.assertEqual("overlay-a\nwoot", f.read())
def test_rename_overlay_over_tree(self) -> None:
"""Make an overlay file and overwrite a tree entry with it"""
from_name = os.path.join(self.mount, "overlay-a")
to_name = os.path.join(self.mount, "hello")
with open(from_name, "w") as f:
f.write("overlay-a\n")
os.rename(from_name, to_name)
with self.assertRaises(OSError) as context:
os.lstat(from_name)
self.assertEqual(
errno.ENOENT, context.exception.errno, msg="no longer visible as old name"
)
self.assert_checkout_root_entries({".eden", "adir", "hello", "slink"})
with open(to_name, "r") as f:
self.assertEqual("overlay-a\n", f.read(), msg="holds correct data")
def test_rename_between_different_dirs(self) -> None:
adir = os.path.join(self.mount, "adir")
bdir = os.path.join(self.mount, "bdir")
os.mkdir(bdir)
os.rename(os.path.join(adir, "file"), os.path.join(bdir, "FILE"))
self.assertEqual([], sorted(os.listdir(adir)))
self.assertEqual(["FILE"], sorted(os.listdir(bdir)))
# Restart to ensure that our serialized state is correct
self.eden.shutdown()
self.eden.start()
self.assertEqual([], sorted(os.listdir(adir)))
self.assertEqual(["FILE"], sorted(os.listdir(bdir)))
def test_rename_dir_over_empty_dir(self) -> None:
subdir = os.path.join(self.mount, "sub")
dir1 = os.path.join(subdir, "dir1")
dir2 = os.path.join(subdir, "dir2")
os.mkdir(subdir)
os.mkdir(dir1)
os.mkdir(dir2)
os.rename(dir1, dir2)
self.assertEqual(["dir2"], os.listdir(subdir))
def test_rename_updates_mtime(self) -> None:
adir_path = os.path.join(self.mount, "adir")
mtime_root = os.lstat(self.mount).st_mtime
mtime_adir = os.lstat(adir_path).st_mtime
while time.time() < max(mtime_root, mtime_adir):
time.sleep(0.01)
os.rename(os.path.join(self.mount, "hello"), os.path.join(adir_path, "hello"))
self.assertLess(mtime_root, os.lstat(self.mount).st_mtime)
self.assertLess(mtime_adir, os.lstat(adir_path).st_mtime)