/[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 1966 - (show annotations)
Thu Nov 20 18:15:57 2003 UTC (21 years, 3 months ago) by bh
Original Path: trunk/thuban/test/test_proj.py
File MIME type: text/x-python
File size: 17368 byte(s)
(ProjFileReadTests.test_read_unreadable_file):
Skip this test if run under non-posix systems since it only works
there

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