#!/usr/bin/env python3 # # Copyright (c) 2016-present, Facebook, Inc. # All rights reserved. # # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. An additional grant # of patent rights can be found in the PATENTS file in the same directory. from .lib import testcase import errno import os import stat import subprocess import time import unittest @testcase.eden_repo_test class SetAttrTest: def populate_repo(self): self.repo.write_file('hello', 'hola\n') self.repo.commit('Initial commit.') # mtime should not get changed on permission changes # to the file but currently its changing in Edenfs @unittest.expectedFailure def test_chmod(self): filename = os.path.join(self.mount, 'hello') st = os.lstat(filename) os.chmod(filename, st.st_mode | stat.S_IROTH) new_st = os.lstat(filename) self.assertGreaterEqual(new_st.st_atime, st.st_atime) self.assertEqual(new_st.st_mtime, st.st_mtime) self.assertEqual(new_st.st_atime, st.st_atime) self.assertGreaterEqual(new_st.st_ctime, st.st_ctime) self.assertEqual(new_st.st_mode, st.st_mode | stat.S_IROTH) def test_chown(self): filename = os.path.join(self.mount, 'hello') # Chown should fail with EPERM unless we are setting it # to the same current ownership st = os.lstat(filename) os.chown(filename, st.st_uid, st.st_gid) with self.assertRaises(OSError) as context: os.chown(filename, st.st_uid + 1, st.st_gid) self.assertEqual(errno.EPERM, context.exception.errno, msg="changing uid of a file should raise EPERM") with self.assertRaises(OSError) as context: os.chown(filename, st.st_uid, st.st_gid + 1) self.assertEqual(errno.EPERM, context.exception.errno, msg="changing gid of a file should raise EPERM") def test_truncate(self): filename = os.path.join(self.mount, 'hello') st = os.lstat(filename) with open(filename, 'r+') as f: f.truncate(0) self.assertEqual('', f.read()) new_st = os.lstat(filename) self.assertEqual(new_st.st_size, 0) self.assertGreaterEqual(new_st.st_atime, st.st_atime) self.assertGreaterEqual(new_st.st_ctime, st.st_ctime) self.assertGreaterEqual(new_st.st_mtime, st.st_mtime) def test_utime(self): filename = os.path.join(self.mount, 'hello') # Update the atime and mtime to a time 5 seconds in the past. # # We round to the nearest second to avoid timestamp granularity issues. # (Eden currently uses the underlying overlay filesystem to store the # timestamps, and it might not necessarily support high resolution # timestamps.) timestamp = int(time.time() - 5) os.utime(filename, (timestamp, timestamp)) st = os.lstat(filename) self.assertEqual(st.st_atime, timestamp) self.assertEqual(st.st_mtime, timestamp) def test_touch(self): filename = os.path.join(self.mount, 'hello') now = time.time() subprocess.check_call(['touch', filename]) st = os.lstat(filename) self.assertGreaterEqual(st.st_atime, now) self.assertGreaterEqual(st.st_mtime, now) newfile = os.path.join(self.mount, 'touched-new-file') now = time.time() subprocess.check_call(['touch', newfile]) st = os.lstat(newfile) self.assertGreaterEqual(st.st_atime, now) self.assertGreaterEqual(st.st_mtime, now) def test_dir_addfile(self): dirname = os.path.join(self.mount, 'test_dir') self.mkdir('test_dir') st = os.lstat(dirname) self.write_file('test_file', 'test string') new_st = os.lstat(dirname) self.assertEqual(new_st.st_atime, st.st_atime) self.assertGreaterEqual(new_st.st_ctime, st.st_ctime) self.assertGreaterEqual(new_st.st_mtime, st.st_mtime) def test_dir_delfile(self): dirname = os.path.join(self.mount, 'test_dir') self.mkdir('test_dir') self.write_file('test_file', 'test string') st = os.lstat(dirname) self.rm('test_file') new_st = os.lstat(dirname) self.assertEqual(new_st.st_atime, st.st_atime) self.assertGreaterEqual(new_st.st_ctime, st.st_ctime) self.assertGreaterEqual(new_st.st_mtime, st.st_mtime) def test_dir_change_filecontents(self): dirname = os.path.join(self.mount, 'test_dir') self.mkdir('test_dir') self.write_file('test_file', 'test string') st = os.lstat(dirname) self.write_file('test_file', 'test string 1') new_st = os.lstat(dirname) self.assertEqual(new_st.st_mtime, st.st_mtime) self.assertEqual(new_st.st_ctime, st.st_ctime) self.assertEqual(new_st.st_mtime, st.st_mtime) # Changing permisssions of directory should change # only ctime of the directory, but currently chmod # is not implemented for directories in edenfs @unittest.expectedFailure def test_dir_change_perm(self): dirname = os.path.join(self.mount, 'test_dir') self.mkdir('test_dir') st = os.lstat(dirname) os.chmod(dirname, st.st_mode | stat.S_IROTH) new_st = os.lstat(dirname) self.assertEqual(new_st.st_mtime, st.st_mtime) self.assertEqual(new_st.st_atime, st.st_atime) self.assertGreaterEqual(new_st.st_ctime, st.st_ctime) # Opening the file in read mode should update the atime # But it is not being updated in Edenfs @unittest.expectedFailure def test_timestamp_openfiles(self): filename = os.path.join(self.mount, 'hello') st = os.lstat(filename) with open(filename, 'r') as f: f.read() new_st = os.lstat(filename) self.assertEqual(new_st.st_mtime, st.st_mtime) self.assertEqual(new_st.st_atime, st.st_atime) self.assertEqual(new_st.st_ctime, st.st_ctime) f.close() new_st = os.lstat(filename) self.assertEqual(new_st.st_mtime, st.st_mtime) self.assertGreater(new_st.st_atime, st.st_atime) self.assertEqual(new_st.st_ctime, st.st_ctime)