import os import tempfile import unittest import time import shutil from blinker import signal import utils.filesystem from system.diskchecker import DiskChecker from system.drive_monitor import DriveMonitor from utils.settings_manager import SETTINGS from defaults import DEFAULT_OPTIONS class TestSDCardManager(unittest.TestCase): """deps: fusefat, fuse2fs, ntfs utils, ntfs3g""" LONG_SLEEP = 0.5 SHORT_SLEEP = 0.1 BASE_MOUNTPOINT = os.path.join("/", "media", "videostitch") VFAT_DEVICE = os.path.join(tempfile.gettempdir(), "vfatdev") VFAT_MOUNTPOINT = os.path.join(BASE_MOUNTPOINT, "vfat_mp") NTFS_DEVICE = os.path.join(tempfile.gettempdir(), "ntfsdev") NTFS_MOUNTPOINT = os.path.join(BASE_MOUNTPOINT, "ntfs_mp") VFAT_RO_DEVICE = os.path.join(tempfile.gettempdir(), "vfatrodev") VFAT_RO_MOUNTPOINT = os.path.join(BASE_MOUNTPOINT, "vfatro_mp") def setUp(self): # self.tearDown() SETTINGS.recording_safety_margin = 15 utils.filesystem.create_block_device(self.VFAT_DEVICE, "vfat") utils.filesystem.create_block_device(self.VFAT_RO_DEVICE, "vfat") # TODO: have ntfs on buildbot behave the same way it behaves on SB image # then "ntfs" could be used instead of "exfat" for invalid device" # utils.filesystem.create_block_device(self.NTFS_DEVICE, "ntfs", additional_params=["-F"]) utils.filesystem.create_block_device(self.NTFS_DEVICE, "exfat") if not os.path.exists(self.VFAT_MOUNTPOINT): os.mkdir(self.VFAT_MOUNTPOINT) if not os.path.exists(self.VFAT_RO_MOUNTPOINT): os.mkdir(self.VFAT_RO_MOUNTPOINT) if not os.path.exists(self.NTFS_MOUNTPOINT): os.mkdir(self.NTFS_MOUNTPOINT) if self.VFAT_MOUNTPOINT not in utils.filesystem.MOUNTPOINT_WHITELIST: utils.filesystem.MOUNTPOINT_WHITELIST.add(self.VFAT_MOUNTPOINT) if self.VFAT_RO_MOUNTPOINT not in utils.filesystem.MOUNTPOINT_WHITELIST: utils.filesystem.MOUNTPOINT_WHITELIST.add(self.VFAT_RO_MOUNTPOINT) if self.NTFS_MOUNTPOINT not in utils.filesystem.MOUNTPOINT_WHITELIST: utils.filesystem.MOUNTPOINT_WHITELIST.add(self.NTFS_MOUNTPOINT) # reduce time spent on test DriveMonitor.CHECK_INTERVAL = 0.01 DiskChecker.CHECK_INTERVAL = 0.01 def tearDown(self): #restore defaults SETTINGS.recording_safety_margin = DEFAULT_OPTIONS["recording_safety_margin"] #leave a bit of time for DriveMonitor to be properly destroyed time.sleep(self.SHORT_SLEEP) """umount, remove devices and mountpoints""" utils.filesystem.unmount(self.VFAT_MOUNTPOINT) utils.filesystem.unmount(self.NTFS_MOUNTPOINT) utils.filesystem.unmount(self.VFAT_RO_MOUNTPOINT) shutil.rmtree(self.VFAT_MOUNTPOINT, ignore_errors=True) shutil.rmtree(self.NTFS_MOUNTPOINT, ignore_errors=True) shutil.rmtree(self.VFAT_RO_MOUNTPOINT, ignore_errors=True) os.remove(self.VFAT_DEVICE) os.remove(self.NTFS_DEVICE) if os.path.exists(self.VFAT_RO_DEVICE): os.remove(self.VFAT_RO_DEVICE) def test_nodevice(self): test_manager = DriveMonitor("/tmp/tmountpoint", "/tmp/nodev") time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_NoDeviceDetected()) test_manager.stop() def test_invalid_device(self): test_manager = DriveMonitor("/tmp/tmountpoint", self.NTFS_DEVICE) time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_InvalidDevice(), msg="Current state: {}".format(test_manager.state)) test_manager.stop() def test_device_not_compatible(self): utils.filesystem.mount(self.NTFS_DEVICE, self.NTFS_MOUNTPOINT) test_manager = DriveMonitor(self.NTFS_MOUNTPOINT, self.NTFS_DEVICE) time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_DeviceNotCompatible(), msg="Current state: {}".format(test_manager.state)) test_manager.stop() def test_device_ok(self): utils.filesystem.mount(self.VFAT_DEVICE, self.VFAT_MOUNTPOINT) test_manager = DriveMonitor(self.VFAT_MOUNTPOINT, self.VFAT_DEVICE) time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_DeviceOk(), msg="Current state: {}".format(test_manager.state)) test_manager.stop() def test_no_space_left(self): utils.filesystem.mount(self.VFAT_DEVICE, self.VFAT_MOUNTPOINT) utils.filesystem.create_file(os.path.join(self.VFAT_MOUNTPOINT, "tfile"), 5) test_manager = DriveMonitor(self.VFAT_MOUNTPOINT, self.VFAT_DEVICE) time.sleep(self.LONG_SLEEP) self.assertTrue(test_manager.is_NotEnoughMemory(), msg="Current state: {}".format(test_manager.state)) test_manager.stop() def test_remove_device(self): utils.filesystem.mount(self.VFAT_DEVICE, self.VFAT_MOUNTPOINT) test_manager = DriveMonitor(self.VFAT_MOUNTPOINT, self.VFAT_DEVICE) time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_DeviceOk(), msg="Current state: {}".format(test_manager.state)) utils.filesystem.unmount(self.VFAT_MOUNTPOINT) time.sleep(self.LONG_SLEEP) self.assertTrue(test_manager.is_InvalidDevice(), msg="Current state: {}".format(test_manager.state)) test_manager.stop() def format_invalid(self, test_manager): test_manager.format_drive() time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_DeviceOk(), msg="Current state: {}".format(test_manager.state)) utils.filesystem.create_file(os.path.join(self.NTFS_MOUNTPOINT,"writetest"), size=1) test_manager.stop() def test_format_invalid_unmounted(self): test_manager = DriveMonitor(self.NTFS_MOUNTPOINT, self.NTFS_DEVICE) time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_InvalidDevice(), msg="Current state: {}".format(test_manager.state)) self.format_invalid(test_manager) test_manager.stop() def test_format_notcompatible_mounted(self): utils.filesystem.mount(self.NTFS_DEVICE, self.NTFS_MOUNTPOINT) test_manager = DriveMonitor(self.NTFS_MOUNTPOINT, self.NTFS_DEVICE) time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_DeviceNotCompatible(), msg="Current state: {}".format(test_manager.state)) self.format_invalid(test_manager) test_manager.stop() def test_format_exfat(self): test_manager = DriveMonitor(self.NTFS_MOUNTPOINT, self.NTFS_DEVICE) time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_InvalidDevice(), msg="Current state: {}".format(test_manager.state)) test_manager.format_drive("exfat") time.sleep(self.SHORT_SLEEP) if 'fuseblk' in test_manager.SUPPORTED_FILESYSTEMS: self.assertTrue(test_manager.is_DeviceOk(), msg="Current state: {}".format(test_manager.state)) else: self.assertTrue(test_manager.is_DeviceNotCompatible(), msg="Current state: {}".format(test_manager.state)) test_manager.stop() def test_format_full(self): utils.filesystem.mount(self.VFAT_DEVICE, self.VFAT_MOUNTPOINT) utils.filesystem.create_file(os.path.join(self.VFAT_MOUNTPOINT, "tfile"), 19.9) test_manager = DriveMonitor(self.VFAT_MOUNTPOINT, self.VFAT_DEVICE) time.sleep(self.LONG_SLEEP) self.assertTrue(test_manager.is_NotEnoughMemory(), msg="Current state: {}".format(test_manager.state)) test_manager.format_drive() time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_DeviceOk(), msg="Current state: {}".format(test_manager.state)) test_manager.stop() def test_format_then_full(self): utils.filesystem.mount(self.VFAT_DEVICE, self.VFAT_MOUNTPOINT) test_manager = DriveMonitor(self.VFAT_MOUNTPOINT, self.VFAT_DEVICE) time.sleep(self.LONG_SLEEP) self.assertTrue(test_manager.is_Ok(), msg="Current state: {}".format(test_manager.state)) test_manager.format_drive() time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_Ok(), msg="Current state: {}".format(test_manager.state)) try: utils.filesystem.create_file(os.path.join(self.VFAT_MOUNTPOINT, "tfile"), 19.9) except: pass time.sleep(self.LONG_SLEEP) self.assertTrue(test_manager.is_NotEnoughMemory(), msg="Current state: {}".format(test_manager.state)) test_manager.stop() def test_format_nodev(self): test_manager = DriveMonitor("/tmp/tmountpoint", "/tmp/nodev") self.assertTrue(test_manager.is_NoDeviceDetected()) self.assertRaises(IOError, test_manager.format_drive, SETTINGS.sdcard_filesystem) test_manager.stop() def warn_cluster(self, sender): self.cluster_size = sender.cluster_size def test_small_cluster_size(self): utils.filesystem.create_block_device(self.VFAT_DEVICE, "vfat", additional_params=["-F", "32", "-s", "1", "-S", "512"]) self.cluster_size = 0 signal("device_warn_cluster{}".format(self.VFAT_MOUNTPOINT)).connect(self.warn_cluster) test_manager = DriveMonitor(self.VFAT_MOUNTPOINT, self.VFAT_DEVICE) time.sleep(self.SHORT_SLEEP) utils.filesystem.mount(self.VFAT_DEVICE, self.VFAT_MOUNTPOINT) time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_DeviceOk(), msg="Current state: {}".format(test_manager.state)) self.assertTrue((self.cluster_size == 512), msg="Small Cluster size (512) should be detected: {}".format(self.cluster_size)) signal("device_warn_cluster{}".format(self.VFAT_MOUNTPOINT)).disconnect(self.warn_cluster) test_manager.stop() def test_good_cluster_size(self): utils.filesystem.create_block_device(self.VFAT_DEVICE, "vfat", additional_params=["-F", "32", "-s", "64", "-S", "512"]) self.cluster_size = 0 signal("device_warn_cluster{}".format(self.VFAT_MOUNTPOINT)).connect(self.warn_cluster) test_manager = DriveMonitor(self.VFAT_MOUNTPOINT, self.VFAT_DEVICE) time.sleep(self.SHORT_SLEEP) utils.filesystem.mount(self.VFAT_DEVICE, self.VFAT_MOUNTPOINT) time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_DeviceOk(), msg="Current state: {}".format(test_manager.state)) self.assertTrue((self.cluster_size == 0), msg="Small Cluster size should not be detected: {}".format(self.cluster_size)) signal("device_warn_cluster{}".format(self.VFAT_MOUNTPOINT)).disconnect(self.warn_cluster) test_manager.stop() def test_read_only_fs(self): test_manager = DriveMonitor(self.VFAT_RO_MOUNTPOINT, self.VFAT_RO_DEVICE) time.sleep(self.SHORT_SLEEP) utils.filesystem.mount(self.VFAT_RO_DEVICE, self.VFAT_RO_MOUNTPOINT) time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_DeviceReadOnly(), msg="Current state: {}".format(test_manager.state)) test_manager.stop() def test_format_read_only_fs(self): os.chmod(self.VFAT_RO_DEVICE,0o444) test_manager = DriveMonitor(self.VFAT_RO_MOUNTPOINT, self.VFAT_RO_DEVICE) time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_InvalidDevice(), msg="Current state: {}".format(test_manager.state)) time.sleep(self.SHORT_SLEEP) test_manager.format_drive() time.sleep(self.LONG_SLEEP) self.assertTrue(test_manager.is_DeviceReadOnly(), msg="Current state: {}".format(test_manager.state)) utils.filesystem.unmount(self.VFAT_RO_MOUNTPOINT) os.remove(self.VFAT_RO_DEVICE) time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_NoDeviceDetected(), msg="Current state: {}".format(test_manager.state)) test_manager.stop() def test_eject(self): utils.filesystem.mount(self.VFAT_DEVICE, self.VFAT_MOUNTPOINT) test_manager = DriveMonitor(self.VFAT_MOUNTPOINT, self.VFAT_DEVICE) time.sleep(self.SHORT_SLEEP) self.assertTrue(test_manager.is_DeviceOk(), msg="Current state: {}".format(test_manager.state)) test_manager.eject_drive() time.sleep(self.LONG_SLEEP) self.assertTrue(test_manager.is_DeviceRemovable(), msg="Current state: {}".format(test_manager.state)) test_manager.stop()