|
1 """ |
|
2 A limited test module is used for a limited spatial database. |
|
3 """ |
|
4 import os, unittest |
|
5 from models import Country, City, State, Feature |
|
6 from django.contrib.gis import gdal |
|
7 from django.contrib.gis.geos import * |
|
8 from django.core.exceptions import ImproperlyConfigured |
|
9 |
|
10 class GeoModelTest(unittest.TestCase): |
|
11 |
|
12 def test01_initial_sql(self): |
|
13 "Testing geographic initial SQL." |
|
14 # Ensuring that data was loaded from initial SQL. |
|
15 self.assertEqual(2, Country.objects.count()) |
|
16 self.assertEqual(8, City.objects.count()) |
|
17 self.assertEqual(2, State.objects.count()) |
|
18 |
|
19 def test02_proxy(self): |
|
20 "Testing Lazy-Geometry support (using the GeometryProxy)." |
|
21 #### Testing on a Point |
|
22 pnt = Point(0, 0) |
|
23 nullcity = City(name='NullCity', point=pnt) |
|
24 nullcity.save() |
|
25 |
|
26 # Making sure TypeError is thrown when trying to set with an |
|
27 # incompatible type. |
|
28 for bad in [5, 2.0, LineString((0, 0), (1, 1))]: |
|
29 try: |
|
30 nullcity.point = bad |
|
31 except TypeError: |
|
32 pass |
|
33 else: |
|
34 self.fail('Should throw a TypeError') |
|
35 |
|
36 # Now setting with a compatible GEOS Geometry, saving, and ensuring |
|
37 # the save took, notice no SRID is explicitly set. |
|
38 new = Point(5, 23) |
|
39 nullcity.point = new |
|
40 |
|
41 # Ensuring that the SRID is automatically set to that of the |
|
42 # field after assignment, but before saving. |
|
43 self.assertEqual(4326, nullcity.point.srid) |
|
44 nullcity.save() |
|
45 |
|
46 # Ensuring the point was saved correctly after saving |
|
47 self.assertEqual(new, City.objects.get(name='NullCity').point) |
|
48 |
|
49 # Setting the X and Y of the Point |
|
50 nullcity.point.x = 23 |
|
51 nullcity.point.y = 5 |
|
52 # Checking assignments pre & post-save. |
|
53 self.assertNotEqual(Point(23, 5), City.objects.get(name='NullCity').point) |
|
54 nullcity.save() |
|
55 self.assertEqual(Point(23, 5), City.objects.get(name='NullCity').point) |
|
56 nullcity.delete() |
|
57 |
|
58 #### Testing on a Polygon |
|
59 shell = LinearRing((0, 0), (0, 100), (100, 100), (100, 0), (0, 0)) |
|
60 inner = LinearRing((40, 40), (40, 60), (60, 60), (60, 40), (40, 40)) |
|
61 |
|
62 # Creating a State object using a built Polygon |
|
63 ply = Polygon(shell, inner) |
|
64 nullstate = State(name='NullState', poly=ply) |
|
65 self.assertEqual(4326, nullstate.poly.srid) # SRID auto-set from None |
|
66 nullstate.save() |
|
67 |
|
68 ns = State.objects.get(name='NullState') |
|
69 self.assertEqual(ply, ns.poly) |
|
70 |
|
71 # Testing the `ogr` and `srs` lazy-geometry properties. |
|
72 if gdal.HAS_GDAL: |
|
73 self.assertEqual(True, isinstance(ns.poly.ogr, gdal.OGRGeometry)) |
|
74 self.assertEqual(ns.poly.wkb, ns.poly.ogr.wkb) |
|
75 self.assertEqual(True, isinstance(ns.poly.srs, gdal.SpatialReference)) |
|
76 self.assertEqual('WGS 84', ns.poly.srs.name) |
|
77 |
|
78 # Changing the interior ring on the poly attribute. |
|
79 new_inner = LinearRing((30, 30), (30, 70), (70, 70), (70, 30), (30, 30)) |
|
80 ns.poly[1] = new_inner |
|
81 ply[1] = new_inner |
|
82 self.assertEqual(4326, ns.poly.srid) |
|
83 ns.save() |
|
84 self.assertEqual(ply, State.objects.get(name='NullState').poly) |
|
85 ns.delete() |
|
86 |
|
87 def test03_contains_contained(self): |
|
88 "Testing the 'contained', 'contains', and 'bbcontains' lookup types." |
|
89 # Getting Texas, yes we were a country -- once ;) |
|
90 texas = Country.objects.get(name='Texas') |
|
91 |
|
92 # Seeing what cities are in Texas, should get Houston and Dallas, |
|
93 # and Oklahoma City because MySQL 'within' only checks on the |
|
94 # _bounding box_ of the Geometries. |
|
95 qs = City.objects.filter(point__within=texas.mpoly) |
|
96 self.assertEqual(3, qs.count()) |
|
97 cities = ['Houston', 'Dallas', 'Oklahoma City'] |
|
98 for c in qs: self.assertEqual(True, c.name in cities) |
|
99 |
|
100 # Pulling out some cities. |
|
101 houston = City.objects.get(name='Houston') |
|
102 wellington = City.objects.get(name='Wellington') |
|
103 pueblo = City.objects.get(name='Pueblo') |
|
104 okcity = City.objects.get(name='Oklahoma City') |
|
105 lawrence = City.objects.get(name='Lawrence') |
|
106 |
|
107 # Now testing contains on the countries using the points for |
|
108 # Houston and Wellington. |
|
109 tx = Country.objects.get(mpoly__contains=houston.point) # Query w/GEOSGeometry |
|
110 nz = Country.objects.get(mpoly__contains=wellington.point.hex) # Query w/EWKBHEX |
|
111 ks = State.objects.get(poly__contains=lawrence.point) |
|
112 self.assertEqual('Texas', tx.name) |
|
113 self.assertEqual('New Zealand', nz.name) |
|
114 self.assertEqual('Kansas', ks.name) |
|
115 |
|
116 # Pueblo is not contained in Texas or New Zealand. |
|
117 self.assertEqual(0, len(Country.objects.filter(mpoly__contains=pueblo.point))) # Query w/GEOSGeometry object |
|
118 |
|
119 # OK City is contained w/in bounding box of Texas. |
|
120 qs = Country.objects.filter(mpoly__bbcontains=okcity.point) |
|
121 self.assertEqual(1, len(qs)) |
|
122 self.assertEqual('Texas', qs[0].name) |
|
123 |
|
124 def test04_disjoint(self): |
|
125 "Testing the `disjoint` lookup type." |
|
126 ptown = City.objects.get(name='Pueblo') |
|
127 qs1 = City.objects.filter(point__disjoint=ptown.point) |
|
128 self.assertEqual(7, qs1.count()) |
|
129 # TODO: This query should work in MySQL, but it appears the |
|
130 # `MBRDisjoint` function doesn't work properly (I went down |
|
131 # to the SQL level for debugging and still got bogus answers). |
|
132 #qs2 = State.objects.filter(poly__disjoint=ptown.point) |
|
133 #self.assertEqual(1, qs2.count()) |
|
134 #self.assertEqual('Kansas', qs2[0].name) |
|
135 |
|
136 def test05_equals(self): |
|
137 "Testing the 'same_as' and 'equals' lookup types." |
|
138 pnt = fromstr('POINT (-95.363151 29.763374)', srid=4326) |
|
139 c1 = City.objects.get(point=pnt) |
|
140 c2 = City.objects.get(point__same_as=pnt) |
|
141 c3 = City.objects.get(point__equals=pnt) |
|
142 for c in [c1, c2, c3]: self.assertEqual('Houston', c.name) |
|
143 |
|
144 def test06_geometryfield(self): |
|
145 "Testing GeometryField." |
|
146 f1 = Feature(name='Point', geom=Point(1, 1)) |
|
147 f2 = Feature(name='LineString', geom=LineString((0, 0), (1, 1), (5, 5))) |
|
148 f3 = Feature(name='Polygon', geom=Polygon(LinearRing((0, 0), (0, 5), (5, 5), (5, 0), (0, 0)))) |
|
149 f4 = Feature(name='GeometryCollection', |
|
150 geom=GeometryCollection(Point(2, 2), LineString((0, 0), (2, 2)), |
|
151 Polygon(LinearRing((0, 0), (0, 5), (5, 5), (5, 0), (0, 0))))) |
|
152 f1.save() |
|
153 f2.save() |
|
154 f3.save() |
|
155 f4.save() |
|
156 |
|
157 f_1 = Feature.objects.get(name='Point') |
|
158 self.assertEqual(True, isinstance(f_1.geom, Point)) |
|
159 self.assertEqual((1.0, 1.0), f_1.geom.tuple) |
|
160 f_2 = Feature.objects.get(name='LineString') |
|
161 self.assertEqual(True, isinstance(f_2.geom, LineString)) |
|
162 self.assertEqual(((0.0, 0.0), (1.0, 1.0), (5.0, 5.0)), f_2.geom.tuple) |
|
163 |
|
164 f_3 = Feature.objects.get(name='Polygon') |
|
165 self.assertEqual(True, isinstance(f_3.geom, Polygon)) |
|
166 f_4 = Feature.objects.get(name='GeometryCollection') |
|
167 self.assertEqual(True, isinstance(f_4.geom, GeometryCollection)) |
|
168 self.assertEqual(f_3.geom, f_4.geom[2]) |
|
169 |
|
170 def test07_mysql_limitations(self): |
|
171 "Testing that union(), kml(), gml() raise exceptions." |
|
172 self.assertRaises(ImproperlyConfigured, City.objects.union, Point(5, 23), field_name='point') |
|
173 self.assertRaises(ImproperlyConfigured, State.objects.all().kml, field_name='poly') |
|
174 self.assertRaises(ImproperlyConfigured, Country.objects.all().gml, field_name='mpoly') |
|
175 |
|
176 from test_feeds import GeoFeedTest |
|
177 from test_sitemaps import GeoSitemapTest |
|
178 def suite(): |
|
179 s = unittest.TestSuite() |
|
180 s.addTest(unittest.makeSuite(GeoModelTest)) |
|
181 s.addTest(unittest.makeSuite(GeoFeedTest)) |
|
182 s.addTest(unittest.makeSuite(GeoSitemapTest)) |
|
183 return s |