class SimplePDFUploadTest
A test class for validating PDF upload functionality to reMarkable cloud, including raw content upload and complete document creation with metadata.
/tf/active/vicechatdev/e-ink-llm/cloudtest/test_simple_pdf_upload.py
18 - 249
moderate
Purpose
This class provides a focused testing framework for reMarkable PDF upload operations. It handles authentication, creates test PDFs (using reportlab or manual PDF generation as fallback), tests raw content upload to cloud storage, and validates complete document creation with metadata. The class is designed to diagnose upload issues by testing incrementally from basic raw uploads to full document creation with database integration.
Source Code
class SimplePDFUploadTest:
"""Focused test for basic PDF upload functionality"""
def __init__(self):
self.base_dir = Path(__file__).parent
# Load auth session
from auth import RemarkableAuth
auth = RemarkableAuth()
self.session = auth.get_authenticated_session()
if not self.session:
raise RuntimeError("Failed to authenticate with reMarkable")
# Load upload manager
from upload_manager import RemarkableUploadManager
database_path = self.base_dir / "remarkable_replica_v2" / "replica_database.json"
self.uploader = RemarkableUploadManager(self.session, database_path)
print("๐งช Simple PDF Upload Test Initialized")
def create_test_pdf(self) -> Path:
"""Create a minimal test PDF"""
test_pdf_path = self.base_dir / "test_uploads" / "simple_test.pdf"
test_pdf_path.parent.mkdir(exist_ok=True)
try:
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
# Create simple PDF with reportlab
c = canvas.Canvas(str(test_pdf_path), pagesize=letter)
c.drawString(100, 750, f"Simple PDF Upload Test")
c.drawString(100, 720, f"Timestamp: {time.strftime('%Y-%m-%d %H:%M:%S')}")
c.drawString(100, 690, f"UUID: {uuid.uuid4()}")
c.showPage()
c.save()
print(f"๐ Created PDF with reportlab: {test_pdf_path}")
except ImportError:
# Fallback: create a minimal PDF manually
pdf_content = """%PDF-1.4
1 0 obj
<<
/Type /Catalog
/Pages 2 0 R
>>
endobj
2 0 obj
<<
/Type /Pages
/Kids [3 0 R]
/Count 1
>>
endobj
3 0 obj
<<
/Type /Page
/Parent 2 0 R
/MediaBox [0 0 612 792]
/Contents 4 0 R
>>
endobj
4 0 obj
<<
/Length 44
>>
stream
BT
/F1 12 Tf
100 700 Td
(Simple PDF Test) Tj
ET
endstream
endobj
xref
0 5
0000000000 65535 f
0000000009 00000 n
0000000058 00000 n
0000000115 00000 n
0000000206 00000 n
trailer
<<
/Size 5
/Root 1 0 R
>>
startxref
300
%%EOF"""
with open(test_pdf_path, 'w') as f:
f.write(pdf_content)
print(f"๐ Created minimal PDF manually: {test_pdf_path}")
return test_pdf_path
def test_raw_content_upload(self) -> bool:
"""Test uploading raw PDF content directly"""
try:
print("\n๐ง Testing Raw PDF Content Upload")
# Create test PDF
test_pdf_path = self.create_test_pdf()
# Read PDF content
with open(test_pdf_path, 'rb') as f:
pdf_content = f.read()
print(f"๐ PDF size: {len(pdf_content)} bytes")
print(f"๐ PDF SHA256: {hashlib.sha256(pdf_content).hexdigest()[:16]}...")
# Generate document UUID (like the logs show)
doc_uuid = str(uuid.uuid4())
print(f"๐ Document UUID: {doc_uuid}")
# Set the document UUID for proper rm-filename header
self.uploader._current_document_uuid = doc_uuid
# Upload PDF content
filename = f"{doc_uuid}.pdf"
print(f"๐ Uploading as: {filename}")
result_hash = self.uploader.upload_raw_content(
content=pdf_content,
content_type='application/pdf',
filename=filename
)
if result_hash:
print(f"โ
Upload successful! Hash: {result_hash[:16]}...")
return True
else:
print("โ Upload failed - no hash returned")
return False
except Exception as e:
print(f"โ Upload failed with exception: {e}")
import traceback
traceback.print_exc()
return False
def test_document_creation(self) -> bool:
"""Test creating a complete document with metadata"""
try:
print("\n๐ Testing Complete Document Creation")
# Create test PDF
test_pdf_path = self.create_test_pdf()
document_name = f"SimpleTest_{int(time.time())}"
print(f"๐ Creating document: {document_name}")
print(f"๐ PDF file: {test_pdf_path}")
# Get initial document count
initial_count = len([n for n in self.uploader.database['nodes'].values()
if n['node_type'] == 'document'])
print(f"๐ Initial document count: {initial_count}")
# Upload document
success = self.uploader.upload_pdf_document(str(test_pdf_path), document_name)
if success:
# Check if document was added
new_count = len([n for n in self.uploader.database['nodes'].values()
if n['node_type'] == 'document'])
print(f"๐ New document count: {new_count}")
if new_count > initial_count:
print(f"โ
Document created successfully!")
# Find the new document
for node in self.uploader.database['nodes'].values():
if node.get('name') == document_name:
print(f"๐ Found document: {node['uuid'][:8]}... '{node['name']}'")
return True
print("โ ๏ธ Document created but not found in database")
return True # Still count as success if upload worked
else:
print("โ Document count unchanged")
return False
else:
print("โ Document creation failed")
return False
except Exception as e:
print(f"โ Document creation failed with exception: {e}")
import traceback
traceback.print_exc()
return False
def run_test(self):
"""Run the focused upload tests"""
print("๐ Starting Simple PDF Upload Test")
print("=" * 50)
# Test 1: Raw content upload
print("\n1๏ธโฃ Raw Content Upload Test")
raw_success = self.test_raw_content_upload()
# Test 2: Complete document creation (only if raw upload works)
print("\n2๏ธโฃ Complete Document Creation Test")
if raw_success:
doc_success = self.test_document_creation()
else:
print("โญ๏ธ Skipping document creation test (raw upload failed)")
doc_success = False
# Summary
print("\n" + "=" * 50)
print("๐ TEST SUMMARY")
print(f"Raw Upload: {'โ
PASS' if raw_success else 'โ FAIL'}")
print(f"Document Creation: {'โ
PASS' if doc_success else 'โ FAIL'}")
if raw_success:
print("\n๐ Basic upload functionality is working!")
if doc_success:
print("๐ Complete document creation is working!")
else:
print("โ ๏ธ Document creation needs investigation")
else:
print("\nโ Basic upload functionality needs to be fixed first")
print("๐ก Check headers, authentication, and checksum calculation")
return raw_success and doc_success
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
bases |
- | - |
Parameter Details
__init__: No parameters required. The constructor automatically initializes authentication, loads the upload manager, and sets up the base directory structure. It will raise RuntimeError if authentication fails.
Return Value
Instantiation returns a SimplePDFUploadTest object. The run_test() method returns a boolean indicating overall test success (True if both raw upload and document creation succeed). Individual test methods (test_raw_content_upload, test_document_creation) return boolean success indicators.
Class Interface
Methods
__init__(self)
Purpose: Initialize the test class with authentication and upload manager setup
Returns: None. Raises RuntimeError if authentication fails.
create_test_pdf(self) -> Path
Purpose: Create a minimal test PDF file using reportlab or manual PDF generation as fallback
Returns: Path object pointing to the created test PDF file in the test_uploads directory
test_raw_content_upload(self) -> bool
Purpose: Test uploading raw PDF content directly to reMarkable cloud storage without metadata
Returns: Boolean indicating success (True) or failure (False) of the raw upload operation
test_document_creation(self) -> bool
Purpose: Test creating a complete document with metadata and verifying it appears in the database
Returns: Boolean indicating success (True) or failure (False) of document creation and database integration
run_test(self)
Purpose: Execute the complete test suite including raw upload and document creation tests with summary reporting
Returns: Boolean indicating overall test success (True if both raw upload and document creation succeed)
Attributes
| Name | Type | Description | Scope |
|---|---|---|---|
base_dir |
Path | Base directory path where the test script is located, used for resolving relative paths | instance |
session |
requests.Session or similar | Authenticated session object obtained from RemarkableAuth for making API requests | instance |
uploader |
RemarkableUploadManager | Upload manager instance configured with the authenticated session and database path for handling PDF uploads | instance |
Dependencies
pathlibtimeuuidhashlibjsonostypingreportlabtraceback
Required Imports
from pathlib import Path
import time
import uuid
import hashlib
from auth import RemarkableAuth
from upload_manager import RemarkableUploadManager
Conditional/Optional Imports
These imports are only needed under specific conditions:
from reportlab.pdfgen import canvas
Condition: only if reportlab is available for PDF generation; falls back to manual PDF creation if not installed
Optionalfrom reportlab.lib.pagesizes import letter
Condition: only if reportlab is available for PDF generation
Optionalimport traceback
Condition: used for exception handling and debugging in test methods
Required (conditional)Usage Example
# Basic usage
try:
test = SimplePDFUploadTest()
success = test.run_test()
if success:
print('All tests passed')
else:
print('Some tests failed')
except RuntimeError as e:
print(f'Authentication failed: {e}')
# Run individual tests
test = SimplePDFUploadTest()
raw_upload_ok = test.test_raw_content_upload()
if raw_upload_ok:
doc_creation_ok = test.test_document_creation()
# Create test PDF only
test = SimplePDFUploadTest()
pdf_path = test.create_test_pdf()
print(f'Test PDF created at: {pdf_path}')
Best Practices
- Always instantiate within a try-except block to handle authentication failures gracefully
- Run test_raw_content_upload() before test_document_creation() as the latter depends on the former working
- Use run_test() for comprehensive testing as it handles proper test sequencing and provides detailed output
- Ensure the remarkable_replica_v2/replica_database.json file exists and is accessible before instantiation
- The class creates test files in 'test_uploads' directory - ensure cleanup after testing if needed
- Monitor console output as the class provides extensive logging with emoji indicators for test progress
- The class modifies uploader._current_document_uuid during raw upload tests - this is intentional for proper header generation
- Test PDFs are timestamped and include UUIDs to ensure uniqueness across test runs
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function main_v15 83.1% similar
-
class FixedUploadTest 81.1% similar
-
function main_v6 80.8% similar
-
class RemarkablePDFUploader_v1 77.6% similar
-
function test_quick_upload_v1 77.3% similar