1#!/usr/bin/env python3 2 3if __name__ == '__main__': 4 import pytest 5 import sys 6 sys.exit(pytest.main([__file__] + sys.argv[1:])) 7 8import subprocess 9import pytest 10import platform 11import sys 12from looseversion import LooseVersion 13from util import (wait_for_mount, umount, cleanup, base_cmdline, 14 safe_sleep, basename, fuse_test_marker, fuse_caps, 15 fuse_proto) 16from os.path import join as pjoin 17import os.path 18 19pytestmark = fuse_test_marker() 20 21@pytest.mark.skipif('FUSE_CAP_WRITEBACK_CACHE' not in fuse_caps, 22 reason='not supported by running kernel') 23@pytest.mark.parametrize("writeback", (False, True)) 24def test_write_cache(tmpdir, writeback, output_checker): 25 if writeback and LooseVersion(platform.release()) < '3.14': 26 pytest.skip('Requires kernel 3.14 or newer') 27 # This test hangs under Valgrind when running close(fd) 28 # test_write_cache.c:test_fs(). Most likely this is because of an internal 29 # deadlock in valgrind, it probably assumes that until close() returns, 30 # control does not come to the program. 31 mnt_dir = str(tmpdir) 32 cmdline = [ pjoin(basename, 'test', 'test_write_cache'), 33 mnt_dir ] 34 if writeback: 35 cmdline.append('-owriteback_cache') 36 elif LooseVersion(platform.release()) >= '5.16': 37 # Test that close(rofd) does not block waiting for pending writes. 38 # This test requires kernel commit a390ccb316be ("fuse: add FOPEN_NOFLUSH") 39 # so opt-in for this test from kernel 5.16. 40 cmdline.append('--delay_ms=200') 41 subprocess.check_call(cmdline, stdout=output_checker.fd, stderr=output_checker.fd) 42 43 44names = [ 'notify_inval_inode', 'invalidate_path' ] 45if fuse_proto >= (7,15): 46 names.append('notify_store_retrieve') 47@pytest.mark.skipif(fuse_proto < (7,12), 48 reason='not supported by running kernel') 49@pytest.mark.parametrize("name", names) 50@pytest.mark.parametrize("notify", (True, False)) 51def test_notify1(tmpdir, name, notify, output_checker): 52 mnt_dir = str(tmpdir) 53 cmdline = base_cmdline + \ 54 [ pjoin(basename, 'example', name), 55 '-f', '--update-interval=1', mnt_dir ] 56 if not notify: 57 cmdline.append('--no-notify') 58 mount_process = subprocess.Popen(cmdline, stdout=output_checker.fd, 59 stderr=output_checker.fd) 60 try: 61 wait_for_mount(mount_process, mnt_dir) 62 filename = pjoin(mnt_dir, 'current_time') 63 with open(filename, 'r') as fh: 64 read1 = fh.read() 65 safe_sleep(2) 66 with open(filename, 'r') as fh: 67 read2 = fh.read() 68 if notify: 69 assert read1 != read2 70 else: 71 assert read1 == read2 72 except: 73 cleanup(mount_process, mnt_dir) 74 raise 75 else: 76 umount(mount_process, mnt_dir) 77 78@pytest.mark.skipif(fuse_proto < (7,12), 79 reason='not supported by running kernel') 80@pytest.mark.parametrize("notify", (True, False)) 81def test_notify_file_size(tmpdir, notify, output_checker): 82 mnt_dir = str(tmpdir) 83 cmdline = base_cmdline + \ 84 [ pjoin(basename, 'example', 'invalidate_path'), 85 '-f', '--update-interval=1', mnt_dir ] 86 if not notify: 87 cmdline.append('--no-notify') 88 mount_process = subprocess.Popen(cmdline, stdout=output_checker.fd, 89 stderr=output_checker.fd) 90 try: 91 wait_for_mount(mount_process, mnt_dir) 92 filename = pjoin(mnt_dir, 'growing') 93 size = os.path.getsize(filename) 94 safe_sleep(2) 95 new_size = os.path.getsize(filename) 96 if notify: 97 assert new_size > size 98 else: 99 assert new_size == size 100 except: 101 cleanup(mount_process, mnt_dir) 102 raise 103 else: 104 umount(mount_process, mnt_dir) 105