diff options
| author | Sergey Fedoseev <fedoseev.sergey@gmail.com> | 2015-12-23 14:35:17 +0500 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2015-12-23 08:02:37 -0500 |
| commit | 312fc1af7b8a028611b45ee272652d59ea7bd85a (patch) | |
| tree | a5a49b814592328424257d002ae0b4022b1750fc /tests | |
| parent | febe1321dac489e2e9dc30b6a67ee3b623e0b735 (diff) | |
Fixed #25961 -- Removed handling of thread-non-safe GEOS functions.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/gis_tests/geos_tests/test_geos.py | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/tests/gis_tests/geos_tests/test_geos.py b/tests/gis_tests/geos_tests/test_geos.py index 116e8d35f8..8c67139e92 100644 --- a/tests/gis_tests/geos_tests/test_geos.py +++ b/tests/gis_tests/geos_tests/test_geos.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals import ctypes import json import random +import threading from binascii import a2b_hex, b2a_hex from io import BytesIO from unittest import skipUnless @@ -12,7 +13,7 @@ from django.contrib.gis.gdal import HAS_GDAL from django.contrib.gis.geos import ( HAS_GEOS, GeometryCollection, GEOSException, GEOSGeometry, LinearRing, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon, - fromfile, fromstr, + fromfile, fromstr, libgeos, ) from django.contrib.gis.geos.base import GEOSBase from django.contrib.gis.geos.libgeos import geos_version_info @@ -1232,6 +1233,48 @@ class GEOSTest(SimpleTestCase, TestDataMixin): self.assertEqual(m.group('version'), v_geos) self.assertEqual(m.group('capi_version'), v_capi) + def test_geos_threads(self): + pnt = Point() + context_ptrs = [] + + geos_init = libgeos.lgeos.initGEOS_r + geos_finish = libgeos.lgeos.finishGEOS_r + + def init(*args, **kwargs): + result = geos_init(*args, **kwargs) + context_ptrs.append(result) + return result + + def finish(*args, **kwargs): + result = geos_finish(*args, **kwargs) + destructor_called.set() + return result + + for i in range(2): + destructor_called = threading.Event() + patch_path = 'django.contrib.gis.geos.libgeos.lgeos' + with mock.patch.multiple(patch_path, initGEOS_r=mock.DEFAULT, finishGEOS_r=mock.DEFAULT) as mocked: + mocked['initGEOS_r'].side_effect = init + mocked['finishGEOS_r'].side_effect = finish + with mock.patch('django.contrib.gis.geos.prototypes.predicates.geos_hasz.func') as mocked_hasz: + thread = threading.Thread(target=lambda: pnt.hasz) + thread.start() + thread.join() + + # We can't be sure that members of thread locals are + # garbage collected right after `thread.join()` so + # we must wait until destructor is actually called. + # Fail if destructor wasn't called within a second. + self.assertTrue(destructor_called.wait(1)) + + context_ptr = context_ptrs[i] + self.assertIsInstance(context_ptr, libgeos.CONTEXT_PTR) + mocked_hasz.assert_called_once_with(context_ptr, pnt.ptr) + mocked['finishGEOS_r'].assert_called_once_with(context_ptr) + + # Check that different contexts were used for the different threads. + self.assertNotEqual(context_ptrs[0], context_ptrs[1]) + @ignore_warnings(category=RemovedInDjango20Warning) def test_deprecated_srid_getters_setters(self): p = Point(1, 2, srid=123) |
