2020-12-06 16:13:37 +01:00
import datetime
2020-12-08 21:08:44 +01:00
import hashlib
2020-11-08 13:00:45 +01:00
import os
2020-12-08 21:08:44 +01:00
import random
2021-08-22 19:31:50 +02:00
import tempfile
2020-12-08 21:08:44 +01:00
import uuid
2020-11-08 13:00:45 +01:00
from pathlib import Path
2020-11-29 15:47:56 +01:00
from unittest import mock
2020-11-08 13:00:45 +01:00
2020-11-12 21:09:45 +01:00
from django . conf import settings
2020-11-29 15:47:56 +01:00
from django . db import DatabaseError
2020-11-08 13:00:45 +01:00
from django . test import TestCase , override_settings
2020-12-16 13:49:48 +01:00
from django . utils import timezone
2020-11-08 13:00:45 +01:00
2020-12-01 14:15:43 +01:00
from . utils import DirectoriesMixin
2020-12-08 21:08:44 +01:00
from . . file_handling import generate_filename , create_source_path_directory , delete_empty_directories , \
generate_unique_filename
2020-12-19 14:48:42 +01:00
from . . models import Document , Correspondent , Tag , DocumentType
2020-11-11 14:38:41 +01:00
2020-11-08 13:00:45 +01:00
2020-12-01 14:15:43 +01:00
class TestFileHandling ( DirectoriesMixin , TestCase ) :
2020-11-08 13:00:45 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " " )
def test_generate_source_filename ( self ) :
document = Document ( )
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-08 13:00:45 +01:00
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
2020-11-11 14:21:33 +01:00
self . assertEqual ( generate_filename ( document ) , " {:07d} .pdf " . format ( document . pk ) )
2020-11-08 13:00:45 +01:00
document . storage_type = Document . STORAGE_TYPE_GPG
2020-11-11 14:21:33 +01:00
self . assertEqual ( generate_filename ( document ) ,
" {:07d} .pdf.gpg " . format ( document . pk ) )
2020-11-08 13:00:45 +01:00
2020-11-11 14:21:33 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {correspondent} / {correspondent} " )
2020-11-08 13:00:45 +01:00
def test_file_renaming ( self ) :
document = Document ( )
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-08 13:00:45 +01:00
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
2020-11-11 14:21:33 +01:00
# Test default source_path
self . assertEqual ( document . source_path , settings . ORIGINALS_DIR + " / {:07d} .pdf " . format ( document . pk ) )
2020-11-08 13:00:45 +01:00
2020-11-11 14:21:33 +01:00
document . filename = generate_filename ( document )
# Ensure that filename is properly generated
2020-12-08 13:54:35 +01:00
self . assertEqual ( document . filename , " none/none.pdf " )
2020-11-08 13:00:45 +01:00
# Enable encryption and check again
document . storage_type = Document . STORAGE_TYPE_GPG
2020-11-11 14:21:33 +01:00
document . filename = generate_filename ( document )
self . assertEqual ( document . filename ,
2020-12-08 13:54:35 +01:00
" none/none.pdf.gpg " )
2020-11-11 14:21:33 +01:00
2020-11-08 13:00:45 +01:00
document . save ( )
2020-11-11 14:21:33 +01:00
# test that creating dirs for the source_path creates the correct directory
create_source_path_directory ( document . source_path )
Path ( document . source_path ) . touch ( )
2020-11-12 21:09:45 +01:00
self . assertEqual ( os . path . isdir ( settings . ORIGINALS_DIR + " /none " ) , True )
2020-11-08 13:00:45 +01:00
# Set a correspondent and save the document
2020-11-12 21:09:45 +01:00
document . correspondent = Correspondent . objects . get_or_create ( name = " test " ) [ 0 ]
2020-11-08 13:00:45 +01:00
document . save ( )
# Check proper handling of files
2020-11-12 21:09:45 +01:00
self . assertEqual ( os . path . isdir ( settings . ORIGINALS_DIR + " /test " ) , True )
self . assertEqual ( os . path . isdir ( settings . ORIGINALS_DIR + " /none " ) , False )
2020-12-08 13:54:35 +01:00
self . assertEqual ( os . path . isfile ( settings . ORIGINALS_DIR + " /test/test.pdf.gpg " ) , True )
2020-11-12 21:09:45 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {correspondent} / {correspondent} " )
2020-11-08 13:00:45 +01:00
def test_file_renaming_missing_permissions ( self ) :
document = Document ( )
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-08 13:00:45 +01:00
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
# Ensure that filename is properly generated
2020-11-11 14:21:33 +01:00
document . filename = generate_filename ( document )
self . assertEqual ( document . filename ,
2020-12-08 13:54:35 +01:00
" none/none.pdf " )
2020-11-11 14:21:33 +01:00
create_source_path_directory ( document . source_path )
2020-11-08 13:00:45 +01:00
Path ( document . source_path ) . touch ( )
# Test source_path
2020-12-08 13:54:35 +01:00
self . assertEqual ( document . source_path , settings . ORIGINALS_DIR + " /none/none.pdf " )
2020-11-08 13:00:45 +01:00
# Make the folder read- and execute-only (no writing and no renaming)
2020-11-11 14:21:33 +01:00
os . chmod ( settings . ORIGINALS_DIR + " /none " , 0o555 )
2020-11-08 13:00:45 +01:00
# Set a correspondent and save the document
2020-11-12 21:09:45 +01:00
document . correspondent = Correspondent . objects . get_or_create ( name = " test " ) [ 0 ]
2020-11-08 13:00:45 +01:00
document . save ( )
# Check proper handling of files
2020-12-08 13:54:35 +01:00
self . assertEqual ( os . path . isfile ( settings . ORIGINALS_DIR + " /none/none.pdf " ) , True )
self . assertEqual ( document . filename , " none/none.pdf " )
2020-11-11 14:21:33 +01:00
os . chmod ( settings . ORIGINALS_DIR + " /none " , 0o777 )
2020-11-08 13:00:45 +01:00
2020-11-12 21:09:45 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {correspondent} / {correspondent} " )
2020-11-11 14:38:41 +01:00
def test_file_renaming_database_error ( self ) :
2020-11-20 13:31:03 +01:00
document1 = Document . objects . create ( mime_type = " application/pdf " , storage_type = Document . STORAGE_TYPE_UNENCRYPTED , checksum = " AAAAA " )
2020-11-11 14:38:41 +01:00
document = Document ( )
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-11 14:38:41 +01:00
document . checksum = " BBBBB "
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
# Ensure that filename is properly generated
document . filename = generate_filename ( document )
self . assertEqual ( document . filename ,
2020-12-08 13:54:35 +01:00
" none/none.pdf " )
2020-11-11 14:38:41 +01:00
create_source_path_directory ( document . source_path )
Path ( document . source_path ) . touch ( )
# Test source_path
self . assertTrue ( os . path . isfile ( document . source_path ) )
# Set a correspondent and save the document
document . correspondent = Correspondent . objects . get_or_create (
name = " test " ) [ 0 ]
2020-11-29 15:47:56 +01:00
with mock . patch ( " documents.signals.handlers.Document.objects.filter " ) as m :
m . side_effect = DatabaseError ( )
document . save ( )
2020-11-11 14:38:41 +01:00
2020-11-29 15:47:56 +01:00
# Check proper handling of files
self . assertTrue ( os . path . isfile ( document . source_path ) )
2020-12-08 13:54:35 +01:00
self . assertEqual ( os . path . isfile ( settings . ORIGINALS_DIR + " /none/none.pdf " ) , True )
self . assertEqual ( document . filename , " none/none.pdf " )
2020-11-08 13:00:45 +01:00
2020-11-12 21:09:45 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {correspondent} / {correspondent} " )
2020-11-08 13:00:45 +01:00
def test_document_delete ( self ) :
document = Document ( )
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-08 13:00:45 +01:00
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
# Ensure that filename is properly generated
2020-11-11 14:21:33 +01:00
document . filename = generate_filename ( document )
self . assertEqual ( document . filename ,
2020-12-08 13:54:35 +01:00
" none/none.pdf " )
2020-11-11 14:21:33 +01:00
create_source_path_directory ( document . source_path )
2020-11-08 13:00:45 +01:00
Path ( document . source_path ) . touch ( )
# Ensure file deletion after delete
2020-11-11 14:21:33 +01:00
pk = document . pk
2020-11-08 13:00:45 +01:00
document . delete ( )
2020-12-08 13:54:35 +01:00
self . assertEqual ( os . path . isfile ( settings . ORIGINALS_DIR + " /none/none.pdf " ) , False )
2020-11-12 21:09:45 +01:00
self . assertEqual ( os . path . isdir ( settings . ORIGINALS_DIR + " /none " ) , False )
2020-11-08 13:00:45 +01:00
2021-08-22 19:31:50 +02:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {correspondent} / {correspondent} " , TRASH_DIR = tempfile . mkdtemp ( ) )
def test_document_delete_trash ( self ) :
document = Document ( )
document . mime_type = " application/pdf "
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
# Ensure that filename is properly generated
document . filename = generate_filename ( document )
self . assertEqual ( document . filename ,
" none/none.pdf " )
create_source_path_directory ( document . source_path )
Path ( document . source_path ) . touch ( )
# Ensure file was moved to trash after delete
self . assertEqual ( os . path . isfile ( settings . TRASH_DIR + " /none/none.pdf " ) , False )
document . delete ( )
self . assertEqual ( os . path . isfile ( settings . ORIGINALS_DIR + " /none/none.pdf " ) , False )
self . assertEqual ( os . path . isdir ( settings . ORIGINALS_DIR + " /none " ) , False )
self . assertEqual ( os . path . isfile ( settings . TRASH_DIR + " /none.pdf " ) , True )
self . assertEqual ( os . path . isfile ( settings . TRASH_DIR + " /none_01.pdf " ) , False )
# Create an identical document and ensure it is trashed under a new name
document = Document ( )
document . mime_type = " application/pdf "
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
document . filename = generate_filename ( document )
create_source_path_directory ( document . source_path )
Path ( document . source_path ) . touch ( )
document . delete ( )
self . assertEqual ( os . path . isfile ( settings . TRASH_DIR + " /none_01.pdf " ) , True )
2020-11-12 21:09:45 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {correspondent} / {correspondent} " )
2020-11-08 13:00:45 +01:00
def test_document_delete_nofile ( self ) :
document = Document ( )
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-08 13:00:45 +01:00
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
document . delete ( )
2020-11-12 21:09:45 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {correspondent} / {correspondent} " )
2020-11-08 13:00:45 +01:00
def test_directory_not_empty ( self ) :
document = Document ( )
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-08 13:00:45 +01:00
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
# Ensure that filename is properly generated
2020-11-11 14:21:33 +01:00
document . filename = generate_filename ( document )
self . assertEqual ( document . filename ,
2020-12-08 13:54:35 +01:00
" none/none.pdf " )
2020-11-11 14:21:33 +01:00
create_source_path_directory ( document . source_path )
2020-11-08 13:00:45 +01:00
Path ( document . source_path ) . touch ( )
2020-11-11 14:21:33 +01:00
important_file = document . source_path + " test "
Path ( important_file ) . touch ( )
2020-11-08 13:00:45 +01:00
# Set a correspondent and save the document
2020-11-12 21:09:45 +01:00
document . correspondent = Correspondent . objects . get_or_create ( name = " test " ) [ 0 ]
2020-11-08 13:00:45 +01:00
document . save ( )
# Check proper handling of files
2020-12-01 14:15:43 +01:00
self . assertEqual ( os . path . isdir ( settings . ORIGINALS_DIR + " /test " ) , True )
self . assertEqual ( os . path . isdir ( settings . ORIGINALS_DIR + " /none " ) , True )
2020-11-11 14:21:33 +01:00
self . assertTrue ( os . path . isfile ( important_file ) )
2020-11-08 13:00:45 +01:00
2020-12-19 14:48:42 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {document_type} - {title} " )
def test_document_type ( self ) :
dt = DocumentType . objects . create ( name = " my_doc_type " )
d = Document . objects . create ( title = " the_doc " , mime_type = " application/pdf " )
self . assertEqual ( generate_filename ( d ) , " none - the_doc.pdf " )
d . document_type = dt
self . assertEqual ( generate_filename ( d ) , " my_doc_type - the_doc.pdf " )
2021-02-09 23:03:07 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {asn} - {title} " )
def test_asn ( self ) :
d1 = Document . objects . create ( title = " the_doc " , mime_type = " application/pdf " , archive_serial_number = 652 , checksum = " A " )
d2 = Document . objects . create ( title = " the_doc " , mime_type = " application/pdf " , archive_serial_number = None , checksum = " B " )
self . assertEqual ( generate_filename ( d1 ) , " 652 - the_doc.pdf " )
self . assertEqual ( generate_filename ( d2 ) , " none - the_doc.pdf " )
2020-11-08 13:00:45 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {tags[type]} " )
def test_tags_with_underscore ( self ) :
document = Document ( )
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-08 13:00:45 +01:00
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
# Add tag to document
document . tags . create ( name = " type_demo " )
document . tags . create ( name = " foo_bar " )
document . save ( )
# Ensure that filename is properly generated
2020-11-11 14:21:33 +01:00
self . assertEqual ( generate_filename ( document ) ,
2020-12-08 13:54:35 +01:00
" demo.pdf " )
2020-11-08 13:00:45 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {tags[type]} " )
def test_tags_with_dash ( self ) :
document = Document ( )
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-08 13:00:45 +01:00
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
# Add tag to document
document . tags . create ( name = " type-demo " )
document . tags . create ( name = " foo-bar " )
document . save ( )
# Ensure that filename is properly generated
2020-11-11 14:21:33 +01:00
self . assertEqual ( generate_filename ( document ) ,
2020-12-08 13:54:35 +01:00
" demo.pdf " )
2020-11-08 13:00:45 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {tags[type]} " )
def test_tags_malformed ( self ) :
document = Document ( )
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-08 13:00:45 +01:00
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
# Add tag to document
document . tags . create ( name = " type:demo " )
document . tags . create ( name = " foo:bar " )
document . save ( )
# Ensure that filename is properly generated
2020-11-11 14:21:33 +01:00
self . assertEqual ( generate_filename ( document ) ,
2020-12-08 13:54:35 +01:00
" none.pdf " )
2020-11-08 13:00:45 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {tags[0]} " )
def test_tags_all ( self ) :
document = Document ( )
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-08 13:00:45 +01:00
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
# Add tag to document
document . tags . create ( name = " demo " )
document . save ( )
# Ensure that filename is properly generated
2020-11-11 14:21:33 +01:00
self . assertEqual ( generate_filename ( document ) ,
2020-12-08 13:54:35 +01:00
" demo.pdf " )
2020-11-08 13:00:45 +01:00
2020-11-11 14:21:33 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {tags[1]} " )
def test_tags_out_of_bounds ( self ) :
2020-11-08 13:00:45 +01:00
document = Document ( )
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-08 13:00:45 +01:00
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
2020-11-11 14:21:33 +01:00
# Add tag to document
document . tags . create ( name = " demo " )
2020-11-08 13:00:45 +01:00
document . save ( )
# Ensure that filename is properly generated
2020-11-11 14:21:33 +01:00
self . assertEqual ( generate_filename ( document ) ,
2020-12-08 13:54:35 +01:00
" none.pdf " )
2020-11-08 13:00:45 +01:00
2020-12-14 03:01:50 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {tags} " )
def test_tags_without_args ( self ) :
document = Document ( )
document . mime_type = " application/pdf "
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
self . assertEqual ( generate_filename ( document ) , f " { document . pk : 07 } .pdf " )
2020-12-14 02:19:53 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {title} {tag_list} " )
def test_tag_list ( self ) :
doc = Document . objects . create ( title = " doc1 " , mime_type = " application/pdf " )
doc . tags . create ( name = " tag2 " )
doc . tags . create ( name = " tag1 " )
self . assertEqual ( generate_filename ( doc ) , " doc1 tag1,tag2.pdf " )
doc = Document . objects . create ( title = " doc2 " , checksum = " B " , mime_type = " application/pdf " )
self . assertEqual ( generate_filename ( doc ) , " doc2.pdf " )
@override_settings ( PAPERLESS_FILENAME_FORMAT = " //etc/something/ {title} " )
def test_filename_relative ( self ) :
doc = Document . objects . create ( title = " doc1 " , mime_type = " application/pdf " )
doc . filename = generate_filename ( doc )
doc . save ( )
self . assertEqual ( doc . source_path , os . path . join ( settings . ORIGINALS_DIR , " etc " , " something " , " doc1.pdf " ) )
2020-12-14 02:46:46 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {created_year} - {created_month} - {created_day} " )
def test_created_year_month_day ( self ) :
2020-12-16 13:49:48 +01:00
d1 = timezone . make_aware ( datetime . datetime ( 2020 , 3 , 6 , 1 , 1 , 1 ) )
2020-12-14 02:46:46 +01:00
doc1 = Document . objects . create ( title = " doc1 " , mime_type = " application/pdf " , created = d1 )
self . assertEqual ( generate_filename ( doc1 ) , " 2020-03-06.pdf " )
2020-12-16 13:49:48 +01:00
doc1 . created = timezone . make_aware ( datetime . datetime ( 2020 , 11 , 16 , 1 , 1 , 1 ) )
2020-12-14 02:46:46 +01:00
self . assertEqual ( generate_filename ( doc1 ) , " 2020-11-16.pdf " )
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {added_year} - {added_month} - {added_day} " )
def test_added_year_month_day ( self ) :
2020-12-16 13:49:48 +01:00
d1 = timezone . make_aware ( datetime . datetime ( 232 , 1 , 9 , 1 , 1 , 1 ) )
2020-12-14 02:46:46 +01:00
doc1 = Document . objects . create ( title = " doc1 " , mime_type = " application/pdf " , added = d1 )
self . assertEqual ( generate_filename ( doc1 ) , " 232-01-09.pdf " )
2020-12-16 13:49:48 +01:00
doc1 . added = timezone . make_aware ( datetime . datetime ( 2020 , 11 , 16 , 1 , 1 , 1 ) )
2020-12-14 02:46:46 +01:00
self . assertEqual ( generate_filename ( doc1 ) , " 2020-11-16.pdf " )
2020-11-12 21:09:45 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {correspondent} / {correspondent} / {correspondent} " )
2020-11-08 13:00:45 +01:00
def test_nested_directory_cleanup ( self ) :
document = Document ( )
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-08 13:00:45 +01:00
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
document . save ( )
# Ensure that filename is properly generated
2020-11-11 14:21:33 +01:00
document . filename = generate_filename ( document )
2020-12-08 13:54:35 +01:00
self . assertEqual ( document . filename , " none/none/none.pdf " )
2020-11-11 14:21:33 +01:00
create_source_path_directory ( document . source_path )
2020-11-08 13:00:45 +01:00
Path ( document . source_path ) . touch ( )
# Check proper handling of files
2020-11-12 21:09:45 +01:00
self . assertEqual ( os . path . isdir ( settings . ORIGINALS_DIR + " /none/none " ) , True )
2020-11-08 13:00:45 +01:00
2020-11-11 14:21:33 +01:00
pk = document . pk
2020-11-08 13:00:45 +01:00
document . delete ( )
2020-12-08 13:54:35 +01:00
self . assertEqual ( os . path . isfile ( settings . ORIGINALS_DIR + " /none/none/none.pdf " ) , False )
2020-11-12 21:09:45 +01:00
self . assertEqual ( os . path . isdir ( settings . ORIGINALS_DIR + " /none/none " ) , False )
self . assertEqual ( os . path . isdir ( settings . ORIGINALS_DIR + " /none " ) , False )
2020-11-11 14:21:33 +01:00
self . assertEqual ( os . path . isdir ( settings . ORIGINALS_DIR ) , True )
2020-11-08 13:00:45 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = None )
def test_format_none ( self ) :
document = Document ( )
2020-11-11 14:21:33 +01:00
document . pk = 1
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-08 13:00:45 +01:00
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
2020-11-11 14:21:33 +01:00
self . assertEqual ( generate_filename ( document ) , " 0000001.pdf " )
2020-11-08 13:00:45 +01:00
def test_try_delete_empty_directories ( self ) :
# Create our working directory
2020-11-11 14:21:33 +01:00
tmp = os . path . join ( settings . ORIGINALS_DIR , " test_delete_empty " )
2020-11-08 13:00:45 +01:00
os . makedirs ( tmp )
os . makedirs ( os . path . join ( tmp , " notempty " ) )
Path ( os . path . join ( tmp , " notempty " , " file " ) ) . touch ( )
os . makedirs ( os . path . join ( tmp , " notempty " , " empty " ) )
2020-11-30 21:38:21 +01:00
delete_empty_directories ( os . path . join ( tmp , " notempty " , " empty " ) , root = settings . ORIGINALS_DIR )
2020-11-08 13:00:45 +01:00
self . assertEqual ( os . path . isdir ( os . path . join ( tmp , " notempty " ) ) , True )
self . assertEqual ( os . path . isfile (
os . path . join ( tmp , " notempty " , " file " ) ) , True )
self . assertEqual ( os . path . isdir (
os . path . join ( tmp , " notempty " , " empty " ) ) , False )
2020-11-13 20:31:51 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " { created/[title] " )
def test_invalid_format ( self ) :
document = Document ( )
document . pk = 1
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-13 20:31:51 +01:00
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
self . assertEqual ( generate_filename ( document ) , " 0000001.pdf " )
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {created__year} " )
def test_invalid_format_key ( self ) :
document = Document ( )
document . pk = 1
2020-11-20 13:31:03 +01:00
document . mime_type = " application/pdf "
2020-11-13 20:31:51 +01:00
document . storage_type = Document . STORAGE_TYPE_UNENCRYPTED
self . assertEqual ( generate_filename ( document ) , " 0000001.pdf " )
2020-12-01 14:15:43 +01:00
2020-12-08 13:54:35 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {title} " )
def test_duplicates ( self ) :
document = Document . objects . create ( mime_type = " application/pdf " , title = " qwe " , checksum = " A " , pk = 1 )
document2 = Document . objects . create ( mime_type = " application/pdf " , title = " qwe " , checksum = " B " , pk = 2 )
Path ( document . source_path ) . touch ( )
Path ( document2 . source_path ) . touch ( )
document . filename = " 0000001.pdf "
document . save ( )
self . assertTrue ( os . path . isfile ( document . source_path ) )
self . assertEqual ( document . filename , " qwe.pdf " )
document2 . filename = " 0000002.pdf "
document2 . save ( )
self . assertTrue ( os . path . isfile ( document . source_path ) )
self . assertEqual ( document2 . filename , " qwe_01.pdf " )
# saving should not change the file names.
document . save ( )
self . assertTrue ( os . path . isfile ( document . source_path ) )
self . assertEqual ( document . filename , " qwe.pdf " )
document2 . save ( )
self . assertTrue ( os . path . isfile ( document . source_path ) )
self . assertEqual ( document2 . filename , " qwe_01.pdf " )
document . delete ( )
self . assertFalse ( os . path . isfile ( document . source_path ) )
# filename free, should remove _01 suffix
document2 . save ( )
self . assertTrue ( os . path . isfile ( document . source_path ) )
self . assertEqual ( document2 . filename , " qwe.pdf " )
2021-02-11 13:47:17 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {title} " )
@mock.patch ( " documents.signals.handlers.Document.objects.filter " )
def test_no_update_without_change ( self , m ) :
doc = Document . objects . create ( title = " document " , filename = " document.pdf " , archive_filename = " document.pdf " , checksum = " A " , archive_checksum = " B " , mime_type = " application/pdf " )
Path ( doc . source_path ) . touch ( )
Path ( doc . archive_path ) . touch ( )
doc . save ( )
m . assert_not_called ( )
2020-12-01 14:15:43 +01:00
class TestFileHandlingWithArchive ( DirectoriesMixin , TestCase ) :
@override_settings ( PAPERLESS_FILENAME_FORMAT = None )
def test_create_no_format ( self ) :
original = os . path . join ( settings . ORIGINALS_DIR , " 0000001.pdf " )
archive = os . path . join ( settings . ARCHIVE_DIR , " 0000001.pdf " )
Path ( original ) . touch ( )
Path ( archive ) . touch ( )
2021-02-09 19:51:16 +01:00
doc = Document . objects . create ( mime_type = " application/pdf " , filename = " 0000001.pdf " , checksum = " A " , archive_filename = " 0000001.pdf " , archive_checksum = " B " )
2020-12-01 14:15:43 +01:00
self . assertTrue ( os . path . isfile ( original ) )
self . assertTrue ( os . path . isfile ( archive ) )
self . assertTrue ( os . path . isfile ( doc . source_path ) )
self . assertTrue ( os . path . isfile ( doc . archive_path ) )
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {correspondent} / {title} " )
def test_create_with_format ( self ) :
original = os . path . join ( settings . ORIGINALS_DIR , " 0000001.pdf " )
archive = os . path . join ( settings . ARCHIVE_DIR , " 0000001.pdf " )
Path ( original ) . touch ( )
Path ( archive ) . touch ( )
2021-02-09 19:51:16 +01:00
doc = Document . objects . create ( mime_type = " application/pdf " , title = " my_doc " , filename = " 0000001.pdf " , checksum = " A " , archive_checksum = " B " , archive_filename = " 0000001.pdf " )
2020-12-01 14:15:43 +01:00
self . assertFalse ( os . path . isfile ( original ) )
self . assertFalse ( os . path . isfile ( archive ) )
self . assertTrue ( os . path . isfile ( doc . source_path ) )
self . assertTrue ( os . path . isfile ( doc . archive_path ) )
2020-12-08 13:54:35 +01:00
self . assertEqual ( doc . source_path , os . path . join ( settings . ORIGINALS_DIR , " none " , " my_doc.pdf " ) )
self . assertEqual ( doc . archive_path , os . path . join ( settings . ARCHIVE_DIR , " none " , " my_doc.pdf " ) )
2020-12-01 14:15:43 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {correspondent} / {title} " )
def test_move_archive_gone ( self ) :
original = os . path . join ( settings . ORIGINALS_DIR , " 0000001.pdf " )
archive = os . path . join ( settings . ARCHIVE_DIR , " 0000001.pdf " )
Path ( original ) . touch ( )
2021-02-09 19:51:16 +01:00
doc = Document . objects . create ( mime_type = " application/pdf " , title = " my_doc " , filename = " 0000001.pdf " , checksum = " A " , archive_checksum = " B " , archive_filename = " 0000001.pdf " )
2020-12-01 14:15:43 +01:00
self . assertTrue ( os . path . isfile ( original ) )
self . assertFalse ( os . path . isfile ( archive ) )
self . assertTrue ( os . path . isfile ( doc . source_path ) )
self . assertFalse ( os . path . isfile ( doc . archive_path ) )
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {correspondent} / {title} " )
def test_move_archive_exists ( self ) :
original = os . path . join ( settings . ORIGINALS_DIR , " 0000001.pdf " )
archive = os . path . join ( settings . ARCHIVE_DIR , " 0000001.pdf " )
2021-02-09 19:51:16 +01:00
existing_archive_file = os . path . join ( settings . ARCHIVE_DIR , " none " , " my_doc.pdf " )
2020-12-01 14:15:43 +01:00
Path ( original ) . touch ( )
Path ( archive ) . touch ( )
os . makedirs ( os . path . join ( settings . ARCHIVE_DIR , " none " ) )
2021-02-09 19:51:16 +01:00
Path ( existing_archive_file ) . touch ( )
doc = Document . objects . create ( mime_type = " application/pdf " , title = " my_doc " , filename = " 0000001.pdf " , checksum = " A " , archive_checksum = " B " , archive_filename = " 0000001.pdf " )
2020-12-01 14:15:43 +01:00
2021-02-09 19:51:16 +01:00
self . assertFalse ( os . path . isfile ( original ) )
self . assertFalse ( os . path . isfile ( archive ) )
2020-12-01 14:15:43 +01:00
self . assertTrue ( os . path . isfile ( doc . source_path ) )
self . assertTrue ( os . path . isfile ( doc . archive_path ) )
2021-02-09 19:51:16 +01:00
self . assertTrue ( os . path . isfile ( existing_archive_file ) )
self . assertEqual ( doc . archive_filename , " none/my_doc_01.pdf " )
2020-12-01 14:15:43 +01:00
2021-02-10 23:53:48 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {title} " )
def test_move_original_only ( self ) :
original = os . path . join ( settings . ORIGINALS_DIR , " document_01.pdf " )
archive = os . path . join ( settings . ARCHIVE_DIR , " document.pdf " )
Path ( original ) . touch ( )
Path ( archive ) . touch ( )
doc = Document . objects . create ( mime_type = " application/pdf " , title = " document " , filename = " document_01.pdf " , checksum = " A " ,
archive_checksum = " B " , archive_filename = " document.pdf " )
self . assertEqual ( doc . filename , " document.pdf " )
self . assertEqual ( doc . archive_filename , " document.pdf " )
self . assertTrue ( os . path . isfile ( doc . source_path ) )
self . assertTrue ( os . path . isfile ( doc . archive_path ) )
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {title} " )
def test_move_archive_only ( self ) :
original = os . path . join ( settings . ORIGINALS_DIR , " document.pdf " )
archive = os . path . join ( settings . ARCHIVE_DIR , " document_01.pdf " )
Path ( original ) . touch ( )
Path ( archive ) . touch ( )
doc = Document . objects . create ( mime_type = " application/pdf " , title = " document " , filename = " document.pdf " , checksum = " A " ,
archive_checksum = " B " , archive_filename = " document_01.pdf " )
self . assertEqual ( doc . filename , " document.pdf " )
self . assertEqual ( doc . archive_filename , " document.pdf " )
self . assertTrue ( os . path . isfile ( doc . source_path ) )
self . assertTrue ( os . path . isfile ( doc . archive_path ) )
2020-12-01 14:15:43 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {correspondent} / {title} " )
@mock.patch ( " documents.signals.handlers.os.rename " )
def test_move_archive_error ( self , m ) :
def fake_rename ( src , dst ) :
if " archive " in src :
raise OSError ( )
else :
os . remove ( src )
Path ( dst ) . touch ( )
m . side_effect = fake_rename
original = os . path . join ( settings . ORIGINALS_DIR , " 0000001.pdf " )
archive = os . path . join ( settings . ARCHIVE_DIR , " 0000001.pdf " )
Path ( original ) . touch ( )
Path ( archive ) . touch ( )
2021-02-09 19:51:16 +01:00
doc = Document . objects . create ( mime_type = " application/pdf " , title = " my_doc " , filename = " 0000001.pdf " , checksum = " A " , archive_checksum = " B " , archive_filename = " 0000001.pdf " )
2020-12-01 14:15:43 +01:00
2021-02-11 13:47:17 +01:00
m . assert_called ( )
2020-12-01 14:15:43 +01:00
self . assertTrue ( os . path . isfile ( original ) )
self . assertTrue ( os . path . isfile ( archive ) )
self . assertTrue ( os . path . isfile ( doc . source_path ) )
self . assertTrue ( os . path . isfile ( doc . archive_path ) )
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {correspondent} / {title} " )
def test_move_file_gone ( self ) :
original = os . path . join ( settings . ORIGINALS_DIR , " 0000001.pdf " )
archive = os . path . join ( settings . ARCHIVE_DIR , " 0000001.pdf " )
#Path(original).touch()
Path ( archive ) . touch ( )
2021-02-09 19:51:16 +01:00
doc = Document . objects . create ( mime_type = " application/pdf " , title = " my_doc " , filename = " 0000001.pdf " , archive_filename = " 0000001.pdf " , checksum = " A " , archive_checksum = " B " )
2020-12-01 14:15:43 +01:00
self . assertFalse ( os . path . isfile ( original ) )
self . assertTrue ( os . path . isfile ( archive ) )
self . assertFalse ( os . path . isfile ( doc . source_path ) )
self . assertTrue ( os . path . isfile ( doc . archive_path ) )
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {correspondent} / {title} " )
@mock.patch ( " documents.signals.handlers.os.rename " )
def test_move_file_error ( self , m ) :
def fake_rename ( src , dst ) :
if " original " in src :
raise OSError ( )
else :
os . remove ( src )
Path ( dst ) . touch ( )
m . side_effect = fake_rename
original = os . path . join ( settings . ORIGINALS_DIR , " 0000001.pdf " )
archive = os . path . join ( settings . ARCHIVE_DIR , " 0000001.pdf " )
Path ( original ) . touch ( )
Path ( archive ) . touch ( )
2021-02-09 19:51:16 +01:00
doc = Document . objects . create ( mime_type = " application/pdf " , title = " my_doc " , filename = " 0000001.pdf " , archive_filename = " 0000001.pdf " , checksum = " A " , archive_checksum = " B " )
2020-12-01 14:15:43 +01:00
2021-02-11 13:47:17 +01:00
m . assert_called ( )
2020-12-01 14:15:43 +01:00
self . assertTrue ( os . path . isfile ( original ) )
self . assertTrue ( os . path . isfile ( archive ) )
self . assertTrue ( os . path . isfile ( doc . source_path ) )
self . assertTrue ( os . path . isfile ( doc . archive_path ) )
2021-02-09 00:00:46 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " " )
2020-12-01 14:15:43 +01:00
def test_archive_deleted ( self ) :
original = os . path . join ( settings . ORIGINALS_DIR , " 0000001.pdf " )
archive = os . path . join ( settings . ARCHIVE_DIR , " 0000001.pdf " )
Path ( original ) . touch ( )
Path ( archive ) . touch ( )
2021-02-09 19:51:16 +01:00
doc = Document . objects . create ( mime_type = " application/pdf " , title = " my_doc " , filename = " 0000001.pdf " , checksum = " A " , archive_checksum = " B " , archive_filename = " 0000001.pdf " )
2020-12-01 14:15:43 +01:00
self . assertTrue ( os . path . isfile ( original ) )
self . assertTrue ( os . path . isfile ( archive ) )
self . assertTrue ( os . path . isfile ( doc . source_path ) )
self . assertTrue ( os . path . isfile ( doc . archive_path ) )
doc . delete ( )
self . assertFalse ( os . path . isfile ( original ) )
self . assertFalse ( os . path . isfile ( archive ) )
self . assertFalse ( os . path . isfile ( doc . source_path ) )
self . assertFalse ( os . path . isfile ( doc . archive_path ) )
2021-02-09 19:51:16 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {title} " )
def test_archive_deleted2 ( self ) :
original = os . path . join ( settings . ORIGINALS_DIR , " document.png " )
original2 = os . path . join ( settings . ORIGINALS_DIR , " 0000001.pdf " )
archive = os . path . join ( settings . ARCHIVE_DIR , " 0000001.pdf " )
Path ( original ) . touch ( )
Path ( original2 ) . touch ( )
Path ( archive ) . touch ( )
doc1 = Document . objects . create ( mime_type = " image/png " , title = " document " , filename = " document.png " , checksum = " A " , archive_checksum = " B " , archive_filename = " 0000001.pdf " )
doc2 = Document . objects . create ( mime_type = " application/pdf " , title = " 0000001 " , filename = " 0000001.pdf " , checksum = " C " )
self . assertTrue ( os . path . isfile ( doc1 . source_path ) )
self . assertTrue ( os . path . isfile ( doc1 . archive_path ) )
self . assertTrue ( os . path . isfile ( doc2 . source_path ) )
doc2 . delete ( )
self . assertTrue ( os . path . isfile ( doc1 . source_path ) )
self . assertTrue ( os . path . isfile ( doc1 . archive_path ) )
self . assertFalse ( os . path . isfile ( doc2 . source_path ) )
2020-12-01 14:15:43 +01:00
@override_settings ( PAPERLESS_FILENAME_FORMAT = " {correspondent} / {title} " )
def test_database_error ( self ) :
original = os . path . join ( settings . ORIGINALS_DIR , " 0000001.pdf " )
archive = os . path . join ( settings . ARCHIVE_DIR , " 0000001.pdf " )
Path ( original ) . touch ( )
Path ( archive ) . touch ( )
2021-02-09 19:51:16 +01:00
doc = Document ( mime_type = " application/pdf " , title = " my_doc " , filename = " 0000001.pdf " , checksum = " A " , archive_filename = " 0000001.pdf " , archive_checksum = " B " )
2020-12-01 14:15:43 +01:00
with mock . patch ( " documents.signals.handlers.Document.objects.filter " ) as m :
m . side_effect = DatabaseError ( )
doc . save ( )
self . assertTrue ( os . path . isfile ( original ) )
self . assertTrue ( os . path . isfile ( archive ) )
self . assertTrue ( os . path . isfile ( doc . source_path ) )
self . assertTrue ( os . path . isfile ( doc . archive_path ) )
2020-12-06 16:13:37 +01:00
2021-02-09 19:51:16 +01:00
2020-12-06 16:13:37 +01:00
class TestFilenameGeneration ( TestCase ) :
@override_settings (
PAPERLESS_FILENAME_FORMAT = " {title} "
)
def test_invalid_characters ( self ) :
doc = Document . objects . create ( title = " This. is the title. " , mime_type = " application/pdf " , pk = 1 , checksum = " 1 " )
2020-12-08 13:54:35 +01:00
self . assertEqual ( generate_filename ( doc ) , " This. is the title.pdf " )
2020-12-06 16:13:37 +01:00
doc = Document . objects . create ( title = " my \\ invalid/../title:yay " , mime_type = " application/pdf " , pk = 2 , checksum = " 2 " )
2020-12-08 13:54:35 +01:00
self . assertEqual ( generate_filename ( doc ) , " my-invalid-..-title-yay.pdf " )
2020-12-06 16:13:37 +01:00
@override_settings (
PAPERLESS_FILENAME_FORMAT = " {created} "
)
def test_date ( self ) :
2020-12-16 13:49:48 +01:00
doc = Document . objects . create ( title = " does not matter " , created = timezone . make_aware ( datetime . datetime ( 2020 , 5 , 21 , 7 , 36 , 51 , 153 ) ) , mime_type = " application/pdf " , pk = 2 , checksum = " 2 " )
2020-12-08 13:54:35 +01:00
self . assertEqual ( generate_filename ( doc ) , " 2020-05-21.pdf " )
2020-12-08 21:08:44 +01:00
def run ( ) :
doc = Document . objects . create ( checksum = str ( uuid . uuid4 ( ) ) , title = str ( uuid . uuid4 ( ) ) , content = " wow " )
2021-02-09 19:51:16 +01:00
doc . filename = generate_unique_filename ( doc )
2020-12-08 21:08:44 +01:00
Path ( doc . thumbnail_path ) . touch ( )
with open ( doc . source_path , " w " ) as f :
f . write ( str ( uuid . uuid4 ( ) ) )
with open ( doc . source_path , " rb " ) as f :
doc . checksum = hashlib . md5 ( f . read ( ) ) . hexdigest ( )
with open ( doc . archive_path , " w " ) as f :
f . write ( str ( uuid . uuid4 ( ) ) )
with open ( doc . archive_path , " rb " ) as f :
doc . archive_checksum = hashlib . md5 ( f . read ( ) ) . hexdigest ( )
doc . save ( )
for i in range ( 30 ) :
doc . title = str ( random . randrange ( 1 , 5 ) )
doc . save ( )