mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Rewrapped long docstrings and block comments to 79 characters + newline using script from https://github.com/medmunds/autofix-w505.
		
			
				
	
	
		
			74 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			74 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import ctypes
 | |
| from unittest import mock
 | |
| 
 | |
| from django.contrib.gis.ptr import CPointerBase
 | |
| from django.test import SimpleTestCase
 | |
| 
 | |
| 
 | |
| class CPointerBaseTests(SimpleTestCase):
 | |
|     def test(self):
 | |
|         destructor_mock = mock.Mock()
 | |
| 
 | |
|         class NullPointerException(Exception):
 | |
|             pass
 | |
| 
 | |
|         class FakeGeom1(CPointerBase):
 | |
|             null_ptr_exception_class = NullPointerException
 | |
| 
 | |
|         class FakeGeom2(FakeGeom1):
 | |
|             ptr_type = ctypes.POINTER(ctypes.c_float)
 | |
|             destructor = destructor_mock
 | |
| 
 | |
|         fg1 = FakeGeom1()
 | |
|         fg2 = FakeGeom2()
 | |
| 
 | |
|         # These assignments are OK. None is allowed because it's equivalent
 | |
|         # to the NULL pointer.
 | |
|         fg1.ptr = fg1.ptr_type()
 | |
|         fg1.ptr = None
 | |
|         fg2.ptr = fg2.ptr_type(ctypes.c_float(5.23))
 | |
|         fg2.ptr = None
 | |
| 
 | |
|         # Because pointers have been set to NULL, an exception is raised on
 | |
|         # access. Raising an exception is preferable to a segmentation fault
 | |
|         # that commonly occurs when a C method is given a NULL reference.
 | |
|         for fg in (fg1, fg2):
 | |
|             with self.assertRaises(NullPointerException):
 | |
|                 fg.ptr
 | |
| 
 | |
|         # Anything that's either not None or the acceptable pointer type
 | |
|         # results in a TypeError when trying to assign it to the `ptr`
 | |
|         # property. Thus, memory addresses (integers) and pointers of the
 | |
|         # incorrect type (in `bad_ptrs`) aren't allowed.
 | |
|         bad_ptrs = (5, ctypes.c_char_p(b"foobar"))
 | |
|         for bad_ptr in bad_ptrs:
 | |
|             for fg in (fg1, fg2):
 | |
|                 with self.assertRaisesMessage(TypeError, "Incompatible pointer type"):
 | |
|                     fg.ptr = bad_ptr
 | |
| 
 | |
|         # Object can be deleted without a destructor set.
 | |
|         fg = FakeGeom1()
 | |
|         fg.ptr = fg.ptr_type(1)
 | |
|         del fg
 | |
| 
 | |
|         # A NULL pointer isn't passed to the destructor.
 | |
|         fg = FakeGeom2()
 | |
|         fg.ptr = None
 | |
|         del fg
 | |
|         self.assertFalse(destructor_mock.called)
 | |
| 
 | |
|         # The destructor is called if set.
 | |
|         fg = FakeGeom2()
 | |
|         ptr = fg.ptr_type(ctypes.c_float(1.0))
 | |
|         fg.ptr = ptr
 | |
|         del fg
 | |
|         destructor_mock.assert_called_with(ptr)
 | |
| 
 | |
|     def test_destructor_catches_importerror(self):
 | |
|         class FakeGeom(CPointerBase):
 | |
|             destructor = mock.Mock(side_effect=ImportError)
 | |
| 
 | |
|         fg = FakeGeom()
 | |
|         fg.ptr = fg.ptr_type(1)
 | |
|         del fg
 |