66- Authorization failures during operations
77- Credential rotation scenarios
88- Session invalidation due to auth changes
9+
10+ Test Organization:
11+ ==================
12+ 1. Initial Authentication - Connection-time auth failures
13+ 2. Operation Authorization - Query-time permission failures
14+ 3. Credential Rotation - Handling credential changes
15+ 4. Session Invalidation - Auth state changes during session
16+ 5. Custom Auth Providers - Advanced authentication scenarios
17+
18+ Key Testing Principles:
19+ ======================
20+ - Auth failures wrapped appropriately
21+ - Original error details preserved
22+ - Concurrent auth failures handled
23+ - Custom auth providers supported
924"""
1025
1126import asyncio
@@ -24,7 +39,12 @@ class TestAuthenticationFailures:
2439 """Test authentication failure scenarios."""
2540
2641 def create_error_future (self , exception ):
27- """Create a mock future that raises the given exception."""
42+ """
43+ Create a mock future that raises the given exception.
44+
45+ Helper method to simulate driver futures that fail with
46+ specific exceptions during callback execution.
47+ """
2848 future = Mock ()
2949 callbacks = []
3050 errbacks = []
@@ -45,7 +65,28 @@ def add_callbacks(callback=None, errback=None):
4565
4666 @pytest .mark .asyncio
4767 async def test_initial_auth_failure (self ):
48- """Test handling of authentication failure during initial connection."""
68+ """
69+ Test handling of authentication failure during initial connection.
70+
71+ What this tests:
72+ ---------------
73+ 1. Auth failure during cluster.connect()
74+ 2. NoHostAvailable with AuthenticationFailed
75+ 3. Wrapped in ConnectionError
76+ 4. Error message preservation
77+
78+ Why this matters:
79+ ----------------
80+ Initial connection auth failures indicate:
81+ - Invalid credentials
82+ - User doesn't exist
83+ - Password expired
84+
85+ Applications need clear error messages to:
86+ - Distinguish auth from network issues
87+ - Prompt for new credentials
88+ - Alert on configuration problems
89+ """
4990 with patch ("async_cassandra.cluster.Cluster" ) as mock_cluster_class :
5091 # Create mock cluster instance
5192 mock_cluster = Mock ()
@@ -73,7 +114,28 @@ async def test_initial_auth_failure(self):
73114
74115 @pytest .mark .asyncio
75116 async def test_auth_failure_during_operation (self ):
76- """Test handling of authentication failure during query execution."""
117+ """
118+ Test handling of authentication failure during query execution.
119+
120+ What this tests:
121+ ---------------
122+ 1. Unauthorized error during query
123+ 2. Permission failures on tables
124+ 3. Wrapped in QueryError
125+ 4. Original Unauthorized accessible
126+
127+ Why this matters:
128+ ----------------
129+ Authorization failures during operations indicate:
130+ - Missing table/keyspace permissions
131+ - Role changes after connection
132+ - Fine-grained access control
133+
134+ Applications need to:
135+ - Handle permission errors gracefully
136+ - Potentially retry with different user
137+ - Log security violations
138+ """
77139 with patch ("async_cassandra.cluster.Cluster" ) as mock_cluster_class :
78140 # Create mock cluster and session
79141 mock_cluster = Mock ()
@@ -104,7 +166,28 @@ async def test_auth_failure_during_operation(self):
104166
105167 @pytest .mark .asyncio
106168 async def test_credential_rotation_reconnect (self ):
107- """Test handling credential rotation requiring reconnection."""
169+ """
170+ Test handling credential rotation requiring reconnection.
171+
172+ What this tests:
173+ ---------------
174+ 1. Auth provider can be updated
175+ 2. Old credentials cause auth failures
176+ 3. AuthenticationFailed during queries
177+ 4. Wrapped appropriately
178+
179+ Why this matters:
180+ ----------------
181+ Production systems rotate credentials:
182+ - Security best practice
183+ - Compliance requirements
184+ - Automated rotation systems
185+
186+ Applications must handle:
187+ - Credential updates
188+ - Re-authentication needs
189+ - Graceful credential transitions
190+ """
108191 with patch ("async_cassandra.cluster.Cluster" ) as mock_cluster_class :
109192 # Create mock cluster and session
110193 mock_cluster = Mock ()
@@ -143,7 +226,28 @@ async def test_credential_rotation_reconnect(self):
143226
144227 @pytest .mark .asyncio
145228 async def test_authorization_failure_different_operations (self ):
146- """Test different authorization failures for various operations."""
229+ """
230+ Test different authorization failures for various operations.
231+
232+ What this tests:
233+ ---------------
234+ 1. Different permission types (SELECT, MODIFY, CREATE, etc.)
235+ 2. Each permission failure handled correctly
236+ 3. Error messages indicate specific permission
237+ 4. Consistent wrapping in QueryError
238+
239+ Why this matters:
240+ ----------------
241+ Cassandra has fine-grained permissions:
242+ - SELECT: read data
243+ - MODIFY: insert/update/delete
244+ - CREATE/DROP/ALTER: schema changes
245+
246+ Applications need to:
247+ - Understand which permission failed
248+ - Request appropriate access
249+ - Implement least-privilege principle
250+ """
147251 with patch ("async_cassandra.cluster.Cluster" ) as mock_cluster_class :
148252 # Setup mock cluster and session
149253 mock_cluster = Mock ()
@@ -182,7 +286,28 @@ async def test_authorization_failure_different_operations(self):
182286
183287 @pytest .mark .asyncio
184288 async def test_session_invalidation_on_auth_change (self ):
185- """Test session invalidation when authentication changes."""
289+ """
290+ Test session invalidation when authentication changes.
291+
292+ What this tests:
293+ ---------------
294+ 1. Session can become auth-invalid
295+ 2. Subsequent operations fail
296+ 3. Session expired errors handled
297+ 4. Clear error messaging
298+
299+ Why this matters:
300+ ----------------
301+ Sessions can be invalidated by:
302+ - Token expiration
303+ - Admin revoking access
304+ - Password changes
305+
306+ Applications must:
307+ - Detect invalid sessions
308+ - Re-authenticate if possible
309+ - Handle session lifecycle
310+ """
186311 with patch ("async_cassandra.cluster.Cluster" ) as mock_cluster_class :
187312 # Setup mock cluster and session
188313 mock_cluster = Mock ()
@@ -215,7 +340,28 @@ async def test_session_invalidation_on_auth_change(self):
215340
216341 @pytest .mark .asyncio
217342 async def test_concurrent_auth_failures (self ):
218- """Test handling of concurrent authentication failures."""
343+ """
344+ Test handling of concurrent authentication failures.
345+
346+ What this tests:
347+ ---------------
348+ 1. Multiple queries with auth failures
349+ 2. All failures handled independently
350+ 3. No error cascading or corruption
351+ 4. Consistent error types
352+
353+ Why this matters:
354+ ----------------
355+ Applications often run parallel queries:
356+ - Batch operations
357+ - Dashboard data fetching
358+ - Concurrent API requests
359+
360+ Auth failures in one query shouldn't:
361+ - Affect other queries
362+ - Cause cascading failures
363+ - Corrupt session state
364+ """
219365 with patch ("async_cassandra.cluster.Cluster" ) as mock_cluster_class :
220366 # Setup mock cluster and session
221367 mock_cluster = Mock ()
@@ -246,7 +392,29 @@ async def test_concurrent_auth_failures(self):
246392
247393 @pytest .mark .asyncio
248394 async def test_auth_error_in_prepared_statement (self ):
249- """Test authorization failure with prepared statements."""
395+ """
396+ Test authorization failure with prepared statements.
397+
398+ What this tests:
399+ ---------------
400+ 1. Prepare succeeds (metadata access)
401+ 2. Execute fails (data access)
402+ 3. Different permission requirements
403+ 4. Error handling consistency
404+
405+ Why this matters:
406+ ----------------
407+ Prepared statements have two phases:
408+ - Prepare: needs schema access
409+ - Execute: needs data access
410+
411+ Users might have permission to see schema
412+ but not to access data, leading to:
413+ - Prepare success
414+ - Execute failure
415+
416+ This split permission model must be handled.
417+ """
250418 with patch ("async_cassandra.cluster.Cluster" ) as mock_cluster_class :
251419 # Setup mock cluster and session
252420 mock_cluster = Mock ()
@@ -289,7 +457,26 @@ async def test_auth_error_in_prepared_statement(self):
289457
290458 @pytest .mark .asyncio
291459 async def test_keyspace_auth_failure (self ):
292- """Test authorization failure when switching keyspaces."""
460+ """
461+ Test authorization failure when switching keyspaces.
462+
463+ What this tests:
464+ ---------------
465+ 1. Keyspace-level permissions
466+ 2. Connection fails with no keyspace access
467+ 3. NoHostAvailable with Unauthorized
468+ 4. Wrapped in ConnectionError
469+
470+ Why this matters:
471+ ----------------
472+ Keyspace permissions control:
473+ - Which keyspaces users can access
474+ - Data isolation between tenants
475+ - Security boundaries
476+
477+ Connection failures due to keyspace access
478+ need clear error messages for debugging.
479+ """
293480 with patch ("async_cassandra.cluster.Cluster" ) as mock_cluster_class :
294481 # Create mock cluster
295482 mock_cluster = Mock ()
@@ -317,7 +504,26 @@ async def test_keyspace_auth_failure(self):
317504
318505 @pytest .mark .asyncio
319506 async def test_auth_provider_callback_handling (self ):
320- """Test custom auth provider with async callbacks."""
507+ """
508+ Test custom auth provider with async callbacks.
509+
510+ What this tests:
511+ ---------------
512+ 1. Custom auth providers accepted
513+ 2. Async credential fetching supported
514+ 3. Provider integration works
515+ 4. No interference with driver auth
516+
517+ Why this matters:
518+ ----------------
519+ Advanced auth scenarios require:
520+ - Dynamic credential fetching
521+ - Token-based authentication
522+ - External auth services
523+
524+ The async wrapper must support custom
525+ auth providers for enterprise use cases.
526+ """
321527 with patch ("async_cassandra.cluster.Cluster" ) as mock_cluster_class :
322528 # Create mock cluster
323529 mock_cluster = Mock ()
@@ -345,7 +551,26 @@ async def get_credentials(self):
345551
346552 @pytest .mark .asyncio
347553 async def test_auth_provider_refresh (self ):
348- """Test auth provider that refreshes credentials."""
554+ """
555+ Test auth provider that refreshes credentials.
556+
557+ What this tests:
558+ ---------------
559+ 1. Refreshable auth providers work
560+ 2. Credential rotation capability
561+ 3. Provider state management
562+ 4. Integration with async wrapper
563+
564+ Why this matters:
565+ ----------------
566+ Production auth often requires:
567+ - Periodic credential refresh
568+ - Token renewal before expiry
569+ - Seamless rotation without downtime
570+
571+ Supporting refreshable providers enables
572+ enterprise authentication patterns.
573+ """
349574 with patch ("async_cassandra.cluster.Cluster" ) as mock_cluster_class :
350575 # Create mock cluster
351576 mock_cluster = Mock ()
0 commit comments