def test_file_storage_prevents_directory_traversal(tmpdir): """ File storage prevents directory traversal (files can only be accessed if they're below the storage location). """ storage = FileSystemStorage(location=str(tmpdir)) with pytest.raises(SuspiciousOperation): storage.exists("..") with pytest.raises(SuspiciousOperation): storage.exists("/etc/passwd")
def test_file_save_with_path(tmpdir): """ Saving a pathname should create intermediate directories as necessary. """ storage = FileSystemStorage(location=str(tmpdir)) assert not storage.exists("path/to") storage.save("path/to/test.file", io.StringIO("file saved with path")) assert storage.exists("path/to") assert storage.open("path/to/test.file").read() == "file saved with path" assert os.path.exists(os.path.join(str(tmpdir), "path", "to", "test.file"))
def test_listdir(tmpdir): """ File storage returns a tuple containing directories and files. """ storage = FileSystemStorage(location=str(tmpdir)) assert not storage.exists("storage_test_1") assert not storage.exists("storage_test_2") assert not storage.exists("storage_dir_1") storage.save("storage_test_1", io.StringIO("custom content")) storage.save("storage_test_2", io.StringIO("custom content")) os.mkdir(os.path.join(str(tmpdir), 'storage_dir_1')) dirs, files = storage.listdir("") assert set(dirs) == set(["storage_dir_1"]) assert set(files) == set(["storage_test_1", "storage_test_2"])
def test_file_access_options(tmpdir): """ Standard file access options are available, and work as expected. """ storage = FileSystemStorage(location=str(tmpdir)) assert not storage.exists("storage_test") f = storage.open("storage_test", "w") f.write("storage contents") f.close() assert storage.exists("storage_test") f = storage.open("storage_test", "r") assert f.read() == "storage contents" f.close() storage.delete("storage_test") assert not storage.exists("storage_test")
def test_file_path(tmpdir): """ File storage returns the full path of a file """ storage = FileSystemStorage(location=str(tmpdir)) assert not storage.exists("test.file") f = io.StringIO("custom contents") f_name = storage.save("test.file", f) assert storage.path(f_name) == os.path.join(str(tmpdir), f_name)
def test_remove_race_handling(tmpdir, monkeypatch): """ File storage should be robust against file removal race conditions. """ real_remove = os.remove # Monkey-patch os.remove, to simulate a normal call, a raced call, # and an error. def fake_remove(path): if path == os.path.join(str(tmpdir), "normal.file"): real_remove(path) elif path == os.path.join(str(tmpdir), "raced.file"): real_remove(path) raise OSError(errno.ENOENT, "simulated ENOENT") elif path == os.path.join(str(tmpdir), "error.file"): raise OSError(errno.EACCES, "simulated EACCES") else: pytest.fail("unexpected argument %r" % path) monkeypatch.setattr(os, "remove", fake_remove) storage = FileSystemStorage(location=str(tmpdir)) storage.save("normal.file", io.StringIO("delete normally")) storage.delete("normal.file") assert not storage.exists("normal.file") storage.save("raced.file", io.StringIO("delete with race")) storage.delete("raced.file") assert not storage.exists("normal.file") # Check that OSErrors aside from ENOENT are still raised. storage.save("error.file", io.StringIO("delete with error")) with pytest.raises(OSError): storage.delete("error.file")
def test_file_modified_time(tmpdir): """ File storage returns a Datetime object for the last modified time of a file. """ storage = FileSystemStorage(location=str(tmpdir)) assert not storage.exists("test.file") f = io.StringIO("custom contents") f_name = storage.save("test.file", f) mtime = storage.modified_time(f_name) assert mtime == datetime.datetime.fromtimestamp(os.path.getmtime(storage.path(f_name))) assert datetime.datetime.now() - storage.modified_time(f_name) < datetime.timedelta(seconds=2)
def test_file_save_without_name(tmpdir): """ File storage extracts the filename from the content object if no name is given explicitly. """ storage = FileSystemStorage(location=str(tmpdir)) assert not storage.exists("test.file") class NamedStringIO(io.StringIO): name = "test.file" f = NamedStringIO("custom contents") storage_f_name = storage.save(None, f) assert storage_f_name == f.name assert os.path.exists(os.path.join(str(tmpdir), f.name))