/[thuban]/branches/WIP-pyshapelib-bramz/test/test_proj.py
ViewVC logotype

Contents of /branches/WIP-pyshapelib-bramz/test/test_proj.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2696 - (show annotations)
Sun Sep 17 23:19:21 2006 UTC (18 years, 5 months ago) by bernhard
Original Path: trunk/thuban/test/test_proj.py
File MIME type: text/x-python
File size: 18770 byte(s)
test/test_proj.py: new test_lc_numeric_robustness()

1 # Copyright (c) 2002, 2003 by Intevation GmbH
2 # Authors:
3 # Bernhard Herzog <[email protected]>
4 #
5 # This program is free software under the GPL (>=v2)
6 # Read the file COPYING coming with Thuban for details.
7
8 """
9 Test the Thuban-specific Projection class
10 """
11
12 __version__ = "$Revision$"
13 # $Source$
14 # $Id$
15
16 import unittest
17 import locale
18 import os
19
20 import localessupport
21 import xmlsupport
22 import support
23 support.initthuban()
24
25 from Thuban import _
26 from Thuban.Model.proj import Projection, ProjFile, \
27 PROJ_UNITS_METERS, PROJ_UNITS_DEGREES
28 from Thuban.Model.messages import PROJECTION_ADDED, PROJECTION_REMOVED, \
29 PROJECTION_REPLACED
30 import Thuban.Model.resource as resource
31
32 from xmlsupport import sax_eventlist
33
34 from xml.sax import SAXParseException
35
36
37 class TestProjection(unittest.TestCase, support.FloatComparisonMixin):
38
39 """Test cases for the Thuban-specific Projection class
40 """
41
42 def test(self):
43 """Test Projection"""
44 params = ["zone=26", "proj=utm", "ellps=clrk66"]
45 proj = Projection(params)
46 self.assertEquals(proj.params, params)
47
48 # It's not clear whether this value is really the correct one
49 # but a test failure here probably still means a bug somewhere
50 self.assertFloatSeqEqual(proj.Forward(0, 0),
51 [3623101.8103431347, 0.0],
52 epsilon = 1e-5)
53 self.assertFloatSeqEqual(proj.Inverse(3623101.8103431347, 0.0),
54 [-0.00065775699878736467, 0])
55
56 self.assertFloatSeqEqual(proj.ForwardBBox((0, 0, 2, 2)),
57 (3620891.3077618643, 0.0,
58 3875381.8535437919, 252962.10480170773),
59 epsilon = 1e-5)
60 self.assertFloatSeqEqual(proj.InverseBBox((3620891.3077618643, 0.0,
61 3875381.8535437919,
62 252962.10480170773)),
63 (-0.018341599754143501, 0.0,
64 2.017992992681688, 2.0377390677846736),
65 epsilon = 1e-5)
66
67 # GetName()
68 self.assertEquals(proj.GetName(), _("Unknown"))
69
70 # GetParameter()
71 self.assertEquals(proj.GetParameter("zone"), "26")
72 self.assertEquals(proj.GetParameter("proj"), "utm")
73 self.assertEquals(proj.GetParameter("ellps"), "clrk66")
74 self.assertEquals(proj.GetParameter("hallo"), "")
75
76 # GetAllParameters()
77 self.assertEquals(proj.GetAllParameters(), params)
78
79 # GetName()
80 proj = Projection(params, "MyName")
81 self.assertEquals(proj.GetName(), "MyName")
82
83 def test_get_parameter_without_equals_sign(self):
84 """Test Projection.GetParameter() for a parameter without '=' sign"""
85 proj = Projection(["proj=utm", "zone=34", "south", "ellps=clrk66"])
86 # The Projection class pretends that for parameters specified
87 # without a value the value is the same as the parameter name.
88 self.assertEquals(proj.GetParameter("south"), "south")
89
90 def test_get_projection_units_geo(self):
91 """Test Projection.GetProjectedUnits() for geographic projection.
92 Test for the alias 'longlat' as well.
93 """
94 proj = Projection(["proj=latlong", "to_meter=0.017453292519943295",
95 "ellps=clrk66"])
96 self.assertEquals(proj.GetProjectedUnits(), PROJ_UNITS_DEGREES)
97 proj = Projection(["proj=longlat", "to_meter=0.017453292519943295",
98 "ellps=clrk66"])
99 self.assertEquals(proj.GetProjectedUnits(), PROJ_UNITS_DEGREES)
100
101 def test_lc_numeric_robustness(self):
102 """Test if an LC_NUMERIC local with comma as decimal_point will work.
103
104 Some versions of proj are not robust against this.
105 Starting with Python 2.4 there is a different behaviour when
106 calling C extensions and now they will see changes locales settings
107 which might tickle the bug in proj.
108 """
109 params = ["proj=latlong", "to_meter=0.01745", "ellps=clrk66"]
110
111 oldlocale = localessupport.setdecimalcommalocale()
112 if oldlocale == None:
113 raise support.SkipTest(
114 "No locale with comma as decimal_point found.")
115
116 proj = Projection(params)
117 result1 = proj.Forward(1,1)
118
119 locale.setlocale(locale.LC_NUMERIC, "C")
120 proj = Projection(params)
121 result2= proj.Forward(1,1)
122
123 locale.setlocale(locale.LC_NUMERIC, oldlocale)
124 self.assertFloatSeqEqual(result1, result2, epsilon = 1e-5 )
125
126 def test_get_projection_units_normal(self):
127 """Test Projection.GetProjectedUnits() for normal projection"""
128 proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
129 self.assertEquals(proj.GetProjectedUnits(), PROJ_UNITS_METERS)
130
131 def test_label(self):
132 """Test Projection.Label() without epsg"""
133 proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"],
134 name = "My Projection")
135 self.assertEquals(proj.Label(), "My Projection")
136
137 def test_label_epsg(self):
138 """Test Projection.Label() with epsg"""
139 proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"],
140 name = "My Projection", epsg="42")
141 self.assertEquals(proj.Label(), "EPSG 42 My Projection")
142
143 def test_epsgcode_for_non_epsg_projection(self):
144 """Test Projection.EPSGCode() without epsg"""
145 proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"],
146 name = "My Projection")
147 self.assertEquals(proj.EPSGCode(), None)
148
149 def test_epsgcode_for_real_epsg_projection(self):
150 """Test Projection.EPSGCode() with epsg"""
151 proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"],
152 name = "My Projection", epsg="42")
153 self.assertEquals(proj.EPSGCode(), "42")
154
155
156
157 class TestProjFileSimple:
158
159 def test_init(self):
160 """Test ProjFile coinstructor"""
161 proj_file = ProjFile("some_filename")
162 self.assertEquals(proj_file.GetFilename(), "some_filename")
163 self.assertEquals(len(proj_file.GetProjections()), 0)
164
165 def test_set_filename(self):
166 """Test ProjFile.SetFilename()"""
167 proj_file = ProjFile("some_filename")
168 proj.SetFilename("other_name")
169 self.assertEquals(proj_file.GetFilename(), "other_name")
170
171
172 class TestProjFile(unittest.TestCase, support.SubscriberMixin):
173
174 """Test cases for ProjFile objects"""
175
176 def setUp(self):
177 self.clear_messages()
178 self.proj0 = Projection(["proj=tmerc", "ellps=clrk66"])
179 self.proj1 = Projection(["proj=utm", "ellps=clrk66"])
180 self.proj2 = Projection(["proj=lcc", "ellps=clrk66",
181 "lat_1=0", "lat_2=20"])
182 self.proj_file = ProjFile("some_filename")
183 for msg in [PROJECTION_ADDED, PROJECTION_REMOVED, PROJECTION_REPLACED]:
184 self.proj_file.Subscribe(msg, self.subscribe_with_params, msg)
185
186 def tearDown(self):
187 self.clear_messages()
188 self.proj_file.Destroy()
189
190 def test_add_remove(self):
191 """Test ProjFile.Add() and ProjFile.Remove()"""
192 self.proj_file.Add(self.proj0)
193 self.proj_file.Add(self.proj1)
194 self.assertEquals(self.proj_file.GetProjections(),
195 [self.proj0, self.proj1])
196 self.check_messages([(self.proj0, PROJECTION_ADDED),
197 (self.proj1, PROJECTION_ADDED)])
198 self.clear_messages()
199
200 self.proj_file.Remove(self.proj0)
201 self.assertEquals(self.proj_file.GetProjections(), [self.proj1])
202 self.check_messages([(self.proj0, PROJECTION_REMOVED)])
203
204 def test_remove_non_existing(self):
205 """Test ProjFile.Remove(<proj not in projfile>)"""
206 self.assertRaises(ValueError, self.proj_file.Remove, self.proj0)
207 # Nothing happened, so no messages should have been sent
208 self.check_messages([])
209
210 def test_replace(self):
211 """Test ProjFile.Replace()"""
212 self.proj_file.Add(self.proj0)
213 self.proj_file.Add(self.proj1)
214 self.clear_messages()
215
216 # Replace()
217 self.proj_file.Replace(self.proj0, self.proj2)
218 self.assertEquals(self.proj_file.GetProjections(),
219 [self.proj2, self.proj1])
220 self.check_messages([(self.proj0, self.proj2, PROJECTION_REPLACED)])
221
222 def test_replace_non_existing(self):
223 """Test ProjFile.Replace(<proj not in projfile>, <some proj>)"""
224 self.proj_file.Add(self.proj0)
225 self.proj_file.Add(self.proj1)
226 self.clear_messages()
227 self.assertRaises(ValueError,
228 self.proj_file.Replace, self.proj2, self.proj0)
229 # All projections should still be there
230 self.assertEquals(self.proj_file.GetProjections(),
231 [self.proj0, self.proj1])
232 # Nothing happened, so no messages should have been sent
233 self.check_messages([])
234
235
236 class ProjFileTest(unittest.TestCase, support.FileTestMixin,
237 xmlsupport.ValidationTest):
238
239 """Base class for the proj file tests that read or write files"""
240
241 def filename(self):
242 """Return the filename for the test"""
243 return self.temp_file_name(self.id() + ".proj")
244
245
246 class ProjFileReadTests(ProjFileTest):
247
248 """Test read ProjFile objects from files
249
250 The files only cover error handling and the system projection file.
251 """
252
253 def test_read_non_existing_file(self):
254 """Test read_proj_file with non-existing file"""
255 self.assertRaises(IOError,
256 resource.read_proj_file,
257 self.temp_file_name("nonexistent.proj"))
258
259 def test_read_unreadable_file(self):
260 """Test read_proj_file with unreadable file
261
262 As currently written this only works on unix-like systems and
263 not e.g. on MS Windows.
264 """
265 if os.name != "posix":
266 raise support.SkipTest("Test only works on posix systems")
267 filename = self.filename()
268 file = open(filename, "w")
269 file.close()
270 os.chmod(filename, 0200) # write-only
271 self.assertRaises(IOError, resource.read_proj_file, filename)
272
273 def test_read_empty_file(self):
274 """Test read_proj_file with empty file"""
275 filename = self.filename()
276 file = open(filename, "w")
277 file.close()
278
279 self.assertRaises(SAXParseException, resource.read_proj_file, filename)
280
281 def test_get_system_proj_file(self):
282 """Test resource.get_system_proj_file(DEFAULT_PROJ_FILE)
283
284 This is primarily to test whether the system proj file contains
285 invalid projection paramers and whether the proj file is not
286 empty
287 """
288 projfile, warnings\
289 = resource.get_system_proj_file(resource.DEFAULT_PROJ_FILE)
290 self.assertEquals(warnings, [])
291 self.assert_(len(projfile.GetProjections()) > 0)
292
293 # see whether it got cached and we get the same projfile object
294 # when we read the file again
295 projfile2, warnings \
296 = resource.get_system_proj_file(resource.DEFAULT_PROJ_FILE)
297 self.assert_(projfile is projfile2)
298
299
300 class WriteProjFileTests(ProjFileTest):
301
302 """Test cases for writing proj files"""
303
304 def compare_xml(self, xml1, xml2):
305 self.assertEquals(sax_eventlist(xml1), sax_eventlist(xml2))
306
307 def doTestWrite(self, projfile, expected):
308 filename = self.filename()
309
310 resource.write_proj_file(projfile)
311
312 file = open(filename)
313 written_contents = file.read()
314 file.close()
315 self.compare_xml(written_contents, expected)
316 self.validate_data(written_contents)
317 self.validate_data(expected)
318
319 def test_write(self):
320 """Test write_proj_file"""
321 pf = ProjFile(self.filename())
322 pf.Add(Projection(['proj=tmerc', 'ellps=clrk66',
323 'lat_0=90w', 'lon_0=90w', 'k=1'],
324 "Transverse Mercator",))
325 pf.Add(Projection(["proj=tmerc",
326 "lat_0=0.000000000", "lon_0=-62.000000000",
327 "k=0.999500", "x_0=400000.000", "y_0=0.000",
328 "ellps=clrk80", "units=m"],
329 "Anguilla 1957 / British West Indies Grid",
330 epsg="200"))
331 file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
332 <!DOCTYPE projectionlist SYSTEM "projfile.dtd">
333 <projectionlist>
334 <projection name="Transverse Mercator">
335 <parameter value="proj=tmerc"/>
336 <parameter value="ellps=clrk66"/>
337 <parameter value="lat_0=90w"/>
338 <parameter value="lon_0=90w"/>
339 <parameter value="k=1"/>
340 </projection>
341 <projection epsg="200"
342 name="Anguilla 1957 / British West Indies Grid">
343 <parameter value="proj=tmerc"/>
344 <parameter value="lat_0=0.000000000"/>
345 <parameter value="lon_0=-62.000000000"/>
346 <parameter value="k=0.999500"/>
347 <parameter value="x_0=400000.000"/>
348 <parameter value="y_0=0.000"/>
349 <parameter value="ellps=clrk80"/>
350 <parameter value="units=m"/>
351 </projection>
352 </projectionlist>
353 '''
354 self.doTestWrite(pf, file_contents)
355
356 def test_write_empty_file(self):
357 """Test write empty ProjFile"""
358 pf = ProjFile(self.filename())
359 file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
360 <!DOCTYPE projectionlist SYSTEM "projfile.dtd">
361 <projectionlist>
362 </projectionlist>
363 '''
364 self.doTestWrite(pf, file_contents)
365
366
367 class ProjFileLoadTestCase(support.FileLoadTestCase):
368
369 """Base class for the test cases that read specific test files"""
370
371 file_extension = ".proj"
372
373 def tearDown(self):
374 """Clear the cache explicitly"""
375 resource.clear_proj_file_cache()
376
377
378 class TestLoadingProjFile(ProjFileLoadTestCase):
379
380 file_contents = '''\
381 <?xml version="1.0" encoding="UTF-8"?>
382 <!DOCTYPE projectionlist SYSTEM "projfile.dtd">
383 <projectionlist>
384 <projection name="Transverse Mercator">
385 <parameter value="proj=tmerc"/>
386 <parameter value="ellps=clrk66"/>
387 <parameter value="lat_0=90w"/>
388 <parameter value="lon_0=90w"/>
389 <parameter value="k=1"/>
390 </projection>
391 <projection epsg="200" name="Anguilla 1957 / British West Indies Grid">
392 <parameter value="proj=tmerc"/>
393 <parameter value="lat_0=0.000000000"/>
394 <parameter value="lon_0=-62.000000000"/>
395 <parameter value="k=0.999500"/>
396 <parameter value="x_0=400000.000"/>
397 <parameter value="y_0=0.000"/>
398 <parameter value="ellps=clrk80"/>
399 <parameter value="units=m"/>
400 </projection>
401 </projectionlist>
402 '''
403
404 def check_projection(self, proj, label, parameters):
405 """Check the values of the proj's label and parameters"""
406 self.assertEquals(proj.Label(), label)
407 params = proj.GetAllParameters()[:]
408 params.sort()
409 self.assertEquals(params, parameters)
410
411 def test(self):
412 projfile, warnings = resource.read_proj_file(self.filename())
413 # no warnings
414 self.assertEquals(warnings, [])
415
416 # There are two projections
417 projs = projfile.GetProjections()
418 self.assertEquals(len(projs), 2)
419
420 self.check_projection(projs[0],
421 "Transverse Mercator",
422 ['ellps=clrk66', 'k=1', 'lat_0=90w', 'lon_0=90w',
423 'proj=tmerc'])
424 self.check_projection(projs[1],
425 "EPSG 200 Anguilla 1957 / British West Indies Grid",
426 ["ellps=clrk80", "k=0.999500",
427 "lat_0=0.000000000", "lon_0=-62.000000000",
428 "proj=tmerc", "units=m",
429 "x_0=400000.000", "y_0=0.000"])
430
431 def test_caching(self):
432 # test whether the projfile cache works
433 projfile, warnings = resource.read_proj_file(self.filename())
434 projfile2, warnings = resource.read_proj_file(self.filename())
435
436 # Both projfiles should be the same object
437 self.assert_(projfile2 is projfile)
438
439 # If we clear the cache we should get a new one.
440 resource.clear_proj_file_cache()
441 projfile3, warnings = resource.read_proj_file(self.filename())
442 self.assert_(projfile3 is not projfile)
443
444
445 class TestLoadingProjFileWithEmptyProjectionlist(ProjFileLoadTestCase):
446
447 file_contents = '''\
448 <?xml version="1.0" encoding="UTF-8"?>
449 <!DOCTYPE projectionlist SYSTEM "projfile.dtd">
450 <projectionlist>
451 </projectionlist>
452 '''
453
454 def test(self):
455 projfile, warnings = resource.read_proj_file(self.filename())
456 # no warnings
457 self.assertEquals(warnings, [])
458
459 # There are no projections
460 self.assertEquals(len(projfile.GetProjections()), 0)
461
462
463 class TestProjFileWithInvalidParameters(ProjFileLoadTestCase):
464
465 file_contents = '''\
466 <?xml version="1.0" encoding="UTF-8"?>
467 <!DOCTYPE projectionlist SYSTEM "projfile.dtd">
468 <projectionlist>
469 <projection name="Universal Transverse Mercator">
470 <parameter value="proj=utm"/>
471 <parameter value="ellps=clrk66"/>
472 <!-- an invalid zone number to trigger the parameter checking
473 in the proj library -->
474 <parameter value="zone=1000"/>
475 </projection>
476 <projection name="Transverse Mercator">
477 <parameter value="proj=tmerc"/>
478 <parameter value="ellps=clrk66"/>
479 <parameter value="lat_0=90w"/>
480 <parameter value="lon_0=90w"/>
481 <parameter value="k=1"/>
482 </projection>
483 </projectionlist>
484 '''
485
486 def setUp(self):
487 support.FileLoadTestCase.setUp(self)
488
489 def test(self):
490 """Test reading a proj file with invalid parameters"""
491 projfile, warnings = resource.read_proj_file(self.filename())
492 projs = projfile.GetProjections()
493 self.assertEquals(len(projs), 1)
494 params = projs[0].GetAllParameters()[:]
495 params.sort()
496 self.assertEquals(params, ['ellps=clrk66', 'k=1', 'lat_0=90w',
497 'lon_0=90w', 'proj=tmerc'])
498 self.assertEquals(warnings,
499 ['Error in projection "Universal Transverse Mercator":'
500 ' invalid UTM zone number'])
501
502
503 if __name__ == "__main__":
504 support.run_tests()

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26