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

Annotation of /branches/WIP-pyshapelib-bramz/test/test_load.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2620 - (hide annotations)
Fri May 6 14:19:23 2005 UTC (19 years, 10 months ago) by jonathan
Original Path: trunk/thuban/test/test_load.py
File MIME type: text/x-python
File size: 43066 byte(s)
(TestRasterLayer): Change file_contents to include opacity and masktype
variables.
(TestRasterLayer.test): Include tests for opacity and masktype changes.

1 bh 2104 # Copyright (c) 2002, 2003, 2004 by Intevation GmbH
2 bh 292 # 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 loading a thuban session from a file
10 bh 1247
11     The tests in this file (test_load.py) are always be the tests for the
12     current version of the thuban file format. Tests for older versions can
13     be found in the version specific test modules, e.g. test_load_0_2 for
14     files created by Thuban 0.2.
15    
16     Maintenance of the test cases:
17    
18     When during a development period the file format is changed with respect
19 bh 2104 to the last released version for the first time, the tests here should
20     be copied to the version specific test file. The round-trip tests which
21 bh 1257 save the session again and compare the XML files should not be copied
22     over as they only make sense here to make sure th that the files checked
23     here are actually ones that may have been written by the current thuban
24     version.
25 bh 292 """
26    
27     __version__ = "$Revision$"
28     # $Source$
29     # $Id$
30    
31     import os
32     import unittest
33    
34     import support
35     support.initthuban()
36    
37 bh 1646 import postgissupport
38 bh 1257 from xmlsupport import sax_eventlist
39 bh 1268
40     import dbflib
41 bh 1970 import shapelib
42 bh 1268
43 bh 1257 from Thuban.Model.save import save_session
44 bh 1646 from Thuban.Model.load import load_session, parse_color, LoadError, \
45     LoadCancelled
46 jonathan 1350 from Thuban.Model.color import Transparent
47 jonathan 684 from Thuban.Model.classification import ClassGroupProperties, ClassGroupRange,\
48     ClassGroupSingleton, ClassGroupDefault
49 bh 1646 from Thuban.Model.postgisdb import ConnectionError
50 bh 1970 from Thuban.Model.table import DBFTable, MemoryTable, \
51     FIELDTYPE_DOUBLE, FIELDTYPE_INT, FIELDTYPE_STRING, \
52     table_to_dbf
53 bh 2034 from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \
54     ALIGN_LEFT, ALIGN_RIGHT, ALIGN_BASELINE
55 jonathan 684
56 bh 292 def filenames_equal(name1, name2):
57     """Return true if the filenames name1 and name2 are equal.
58    
59     On systems where it is available, simply use os.path.samefile,
60     otherwise return whether the normalized versions of the filenames
61     according to os.path.normpath are equal.
62     """
63     if hasattr(os.path, "samefile"):
64     return os.path.samefile(name1, name2)
65     return os.path.normpath(name1) == os.path.normpath(name2)
66    
67    
68 bh 957
69     class LoadSessionTest(support.FileLoadTestCase):
70    
71     """Base class for .thuban file loading tests
72    
73     Basically the same as the FileLoadTestCase, except that all tests
74     use the '.thuban' extension by default and that setUp and tearDown
75     handle sessions.
76     """
77    
78     file_extension = ".thuban"
79    
80     def setUp(self):
81     """Create the test files"""
82     support.FileLoadTestCase.setUp(self)
83     self.session = None
84    
85     def tearDown(self):
86     if self.session is not None:
87     self.session.Destroy()
88     self.session = None
89    
90 bh 1268
91 bh 2104 dtd = "http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
92 bh 1268 thubanids = [((dtd, n), (None, "id")) for n in
93     ["fileshapesource", "filetable", "jointable",
94     "derivedshapesource"]]
95     thubanidrefs = [((dtd, n), (None, m)) for n, m in
96     [("layer", "shapestore"),
97     ("jointable", "left"),
98     ("jointable", "right"),
99     ("derivedshapesource", "table"),
100     ("derivedshapesource", "shapesource")]]
101 bh 1989
102     # The filenames in the tests should be understandable on all
103     # currently supported platforms so filenames is an empty list
104     filenames = []
105    
106 bh 1268 del n, m, dtd
107    
108 bh 1257 def check_format(self):
109     """Check whether the file we loaded from matches the one that
110     would be written. Call this from each test case after loading
111     the session
112     """
113     filename = self.temp_file_name(self.id() + ".roundtrip.thuban")
114     save_session(self.session, filename)
115 bh 1268 el1 = sax_eventlist(filename = filename, ids = self.thubanids,
116 bh 1683 idrefs = self.thubanidrefs,
117     filenames = self.filenames)
118 bh 1268 el2 = sax_eventlist(filename = self.filename(), ids = self.thubanids,
119 bh 1683 idrefs = self.thubanidrefs,
120     filenames = self.filenames)
121 bh 1268 if 0:
122     for a, b in zip(el1, el2):
123     print a != b and "***************" or ""
124     print a
125     print b
126 jonathan 2551
127 bh 1268 self.assertEquals(el1, el2,
128     "loaded file not equivalent to the saved file")
129 bh 957
130 bh 1257
131 bh 957 class ClassificationTest(LoadSessionTest):
132    
133     """
134     Base class for tests that do some detailed checking of classifications
135     """
136    
137     def TestLayers(self, layers, expected):
138     TITLE = 0
139     NUM_GROUPS = 1
140     CLASSES = 2
141     GROUP_TYPE = 0
142     GROUP_DATA = 1
143     GROUP_LABEL = 2
144     GROUP_PROPS = 3
145    
146     eq = self.assertEquals
147    
148     eq(len(layers), len(expected))
149    
150     for layer, data in zip(layers, expected):
151     eq(layer.Title(), data[TITLE])
152    
153     clazz = layer.GetClassification()
154     eq(clazz.GetNumGroups(), data[NUM_GROUPS])
155     eq(clazz.GetNumGroups() + 1, len(data[CLASSES]))
156    
157     i = 0
158     for group in clazz:
159     props = ClassGroupProperties()
160     props.SetLineColor(
161     parse_color(data[CLASSES][i][GROUP_PROPS][0]))
162     props.SetLineWidth(data[CLASSES][i][GROUP_PROPS][1])
163     props.SetFill(
164     parse_color(data[CLASSES][i][GROUP_PROPS][2]))
165 jan 2373 if len(data[CLASSES][i][GROUP_PROPS]) > 3:
166     props.SetSize(data[CLASSES][i][GROUP_PROPS][3])
167 bh 957
168     if data[CLASSES][i][GROUP_TYPE] == "default":
169     g = ClassGroupDefault(props, data[CLASSES][i][GROUP_LABEL])
170     elif data[CLASSES][i][GROUP_TYPE] == "range":
171 jonathan 1357 g = ClassGroupRange((data[CLASSES][i][GROUP_DATA][0],
172     data[CLASSES][i][GROUP_DATA][1]),
173 bh 957 props, data[CLASSES][i][GROUP_LABEL])
174     elif data[CLASSES][i][GROUP_TYPE] == "single":
175     g = ClassGroupSingleton(data[CLASSES][i][GROUP_DATA],
176     props, data[CLASSES][i][GROUP_LABEL])
177    
178     eq(group, g)
179    
180     i += 1
181    
182    
183    
184     class TestSingleLayer(LoadSessionTest):
185    
186 bh 1846 # Note: The use of &amp; and non-ascii characters is deliberate. We
187     # want to test whether the loading code handles that correctly.
188 bh 957 file_contents = '''\
189 bh 292 <?xml version="1.0" encoding="UTF-8"?>
190 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
191     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
192 bh 1848 title="Stra\xc3\x9fen &amp; Landmarken">
193 bh 1268 <fileshapesource filetype="shapefile" id="D1"
194     filename="../../Data/iceland/political.shp"/>
195 bh 1848 <map title="\xc3\x9cbersicht">
196 bh 1846 <projection epsg="32627" name="WGS 84 / UTM zone 27N">
197     <parameter value="datum=WGS84"/>
198     <parameter value="ellps=WGS84"/>
199 bh 1268 <parameter value="proj=utm"/>
200 bh 1846 <parameter value="units=m"/>
201     <parameter value="zone=27"/>
202 bh 1268 </projection>
203     <layer shapestore="D1" visible="true"
204 bh 1848 stroke="#000000" title="K\xc3\xbcste" stroke_width="1"
205 bh 1268 fill="None"/>
206     </map>
207 bh 292 </session>
208     '''
209    
210 bh 957 def test(self):
211     """Load a session with a single map with a single layer"""
212     eq = self.assertEquals
213     session = load_session(self.filename())
214     self.session = session
215    
216     # Check the title
217 bh 1848 eq(session.Title(), "Stra\xdfen & Landmarken")
218 bh 957
219     # the session has one map.
220     maps = session.Maps()
221     eq(len(maps), 1)
222    
223     # Check the map's attributes
224     map = maps[0]
225 bh 1848 eq(map.Title(), "\xdcbersicht")
226 bh 1846 proj = map.GetProjection()
227     eq(proj.GetName(), "WGS 84 / UTM zone 27N")
228     eq(proj.EPSGCode(), "32627")
229     params = proj.GetAllParameters()
230     params.sort()
231     eq(params, ["datum=WGS84", "ellps=WGS84", "proj=utm", "units=m",
232     "zone=27"])
233 bh 957
234     # the map has a single layer
235     layers = map.Layers()
236     eq(len(layers), 1)
237    
238     # Check the layer attributes
239     layer = layers[0]
240 bh 1848 eq(layer.Title(), "K\xfcste")
241 bh 1219 self.failUnless(filenames_equal(layer.ShapeStore().FileName(),
242 bh 957 os.path.join(self.temp_dir(),
243     os.pardir, os.pardir,
244     "Data", "iceland",
245     "political.shp")))
246 jonathan 1347 eq(layer.GetClassification().GetDefaultFill(), Transparent)
247 bh 957 eq(layer.GetClassification().GetDefaultLineColor().hex(), "#000000")
248     eq(layer.Visible(), True)
249    
250 bh 1257 self.check_format()
251    
252 bh 957 self.session.Destroy()
253     self.session = None
254    
255 bh 1931 def test_leak(self):
256     """Test load_session for resource leaks
257 bh 957
258 bh 1931 The load_session function had a resource leak in that it created
259     cyclic references. The objects would have been eventually
260     collected by the garbage collector but too late. One symptom is
261     that when layers are removed so that the last normal reference
262     owned indirectly by the session to a shape store goes away, the
263     shape store is not actually removed from the session even though
264     the session only keeps weak references because there are still
265     references owned by the cyclic garbage.
266     """
267     session = load_session(self.filename())
268     self.session = session
269    
270     # sanity check
271     self.assertEquals(len(session.ShapeStores()), 1)
272    
273     # remove the map. The shapestore should go away too
274     session.RemoveMap(session.Maps()[0])
275     self.assertEquals(len(session.ShapeStores()), 0)
276    
277    
278 bh 1970 class TestNonAsciiColumnName(LoadSessionTest):
279    
280     file_contents = '''\
281     <?xml version="1.0" encoding="UTF-8"?>
282 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
283     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
284 bh 1970 title="Non ASCII column name test">
285     <fileshapesource filetype="shapefile" id="D1"
286     filename="TestNonAsciiColumnName.shp"/>
287     <map title="map">
288     <projection name="Some Projection">
289     <parameter value="datum=WGS84"/>
290     <parameter value="ellps=WGS84"/>
291     <parameter value="proj=utm"/>
292     <parameter value="units=m"/>
293     <parameter value="zone=27"/>
294     </projection>
295     <layer shapestore="D1" visible="true"
296     stroke="#000000" title="layer" stroke_width="1"
297     fill="None">
298     <classification field="Fl\xc3\xa4che" field_type="double">
299     <clnull label="">
300     <cldata stroke="#000000" stroke_width="1" fill="None"/>
301     </clnull>
302     </classification>
303     </layer>
304     </map>
305     </session>
306     '''
307    
308     def test(self):
309     """Load a session with a single map with a single layer"""
310    
311     # Create a shapefile and a dbffile with a non-ascii column name
312     dbffile = self.temp_file_name("TestNonAsciiColumnName.dbf")
313     shpfile = self.temp_file_name("TestNonAsciiColumnName.shp")
314     dbf = dbflib.create(dbffile)
315     dbf.add_field('Fl\xe4che', dbflib.FTDouble, 10, 5)
316     dbf.write_record(0, (0.0,))
317     dbf.close()
318     shp = shapelib.create(shpfile, shapelib.SHPT_POLYGON)
319     shp.write_object(-1, shapelib.SHPObject(shapelib.SHPT_POLYGON, 1,
320     [[(0,0), (10, 10), (10, 0),
321     (0, 0)]]))
322     shp.close()
323    
324     try:
325     session = load_session(self.filename())
326     except ValueError, v:
327     # Usually if the field name is not decoded properly the
328     # loading fails because the field type mentioned in the file
329     # is not None as returned from the layer for a non-existing
330     # column name so we check for that and report it as failure.
331     # Other exceptions are errors in the test case.
332     if str(v) == "xml field type differs from database!":
333     self.fail("Cannot load file with non-ascii column names")
334     else:
335     raise
336     self.session = session
337    
338     # In case Thuban could load the file anyway (i.e. no ValueError
339     # exception in load_session()), check explicitly whether the
340     # field name was decoded properly. The test will probably lead
341     # to a UnicodeError instead of a test failure so we check that
342     # too
343     layer = session.Maps()[0].Layers()[0]
344     try:
345     self.assertEquals(layer.GetClassificationColumn(), 'Fl\xe4che')
346     except UnicodeError:
347     # FIXME: Obviously this will have to change if Thuban ever
348     # supports unicode properly.
349     self.fail("Column name was not converted to a bytestring")
350    
351     # roundtrip check
352     self.check_format()
353    
354    
355 bh 957 class TestLayerVisibility(LoadSessionTest):
356    
357     file_contents = '''\
358 jonathan 690 <?xml version="1.0" encoding="UTF-8"?>
359 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
360     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
361 bh 1268 title="single map&amp;layer">
362     <fileshapesource filetype="shapefile" id="D1"
363     filename="../../Data/iceland/political.shp"/>
364     <map title="Test Map">
365     <projection name="Unknown">
366     <parameter value="zone=26"/>
367     <parameter value="proj=utm"/>
368     <parameter value="ellps=clrk66"/>
369     </projection>
370     <layer shapestore="D1" visible="false" stroke="#000000"
371     title="My Layer" stroke_width="1" fill="None"/>
372 bh 957 </map>
373     </session>
374     '''
375    
376     def test(self):
377     """Test that the visible flag is correctly loaded for a layer."""
378     eq = self.assertEquals
379     session = load_session(self.filename())
380     self.session = session
381     maps = session.Maps()
382     eq(len(maps), 1)
383     map = maps[0]
384     layers = map.Layers()
385     eq(len(layers), 1)
386     layer = layers[0]
387    
388     eq(layer.Visible(), False)
389    
390 bh 1257 self.check_format()
391 bh 957
392    
393 jan 2373 class TestSymbolSize(ClassificationTest):
394    
395     file_contents = '''\
396     <?xml version="1.0" encoding="UTF-8"?>
397     <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
398     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd" title="Thuban sample session">
399     <fileshapesource filetype="shapefile" id="D813968480" filename="../../Data/iceland/cultural_landmark-point.shp"/>
400     <map title="Iceland map">
401     <layer title="cultural_landmark-point" stroke_width="1" shapestore="D813968480" visible="true" stroke="#000000" fill="#000000">
402     <classification field="CLPTLABEL" field_type="string">
403     <clnull label="">
404     <cldata stroke="#000000" stroke_width="1" size="3" fill="#000000"/>
405     </clnull>
406     <clpoint label="" value="RUINS">
407     <cldata stroke="#000000" stroke_width="1" size="6" fill="#ffffff"/>
408     </clpoint>
409     <clpoint label="" value="FARM">
410     <cldata stroke="#000000" stroke_width="1" size="9" fill="#ffff00"/>
411     </clpoint>
412     </classification>
413     </layer>
414     </map>
415     </session>
416     '''
417    
418     def test(self):
419     """Test that the size attribute for point symbols is correctly
420     loaded for a layer."""
421     eq = self.assertEquals
422     session = load_session(self.filename())
423     self.session = session
424    
425     map = session.Maps()[0] # only one map in the sample
426    
427     expected = [("cultural_landmark-point", 2,
428     [("default", (), "",
429     ("#000000", 1, "#000000", 3)),
430     ("single", "RUINS", "",
431     ("#000000", 1, "#ffffff", 6)),
432     ("single", "FARM", "",
433     ("#000000", 1, "#ffff00", 9))])]
434    
435     self.TestLayers(map.Layers(), expected)
436    
437     self.check_format()
438    
439    
440 bh 957 class TestClassification(ClassificationTest):
441    
442     file_contents = '''\
443     <?xml version="1.0" encoding="UTF-8"?>
444 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
445     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
446 bh 1976 title="single map&amp;layer">
447     <fileshapesource filetype="shapefile" id="D138389860"
448     filename="../../Data/iceland/political.shp"/>
449     <fileshapesource filetype="shapefile" id="D138504492"
450     filename="../../Data/iceland/political.shp"/>
451     <map title="Test Map">
452     <projection name="">
453     <parameter value="zone=26"/>
454     <parameter value="proj=utm"/>
455     <parameter value="ellps=clrk66"/>
456     </projection>
457     <layer shapestore="D138389860" visible="true" stroke="#000000"
458     title="My Layer" stroke_width="1" fill="None">
459 jonathan 690 <classification field="POPYREG" field_type="string">
460 bh 1976 <clnull label="">
461 jonathan 690 <cldata stroke="#000000" stroke_width="1" fill="None"/>
462     </clnull>
463 bh 1976 <clpoint label="" value="1">
464 jonathan 690 <cldata stroke="#000000" stroke_width="2" fill="None"/>
465     </clpoint>
466 bh 1976 <clpoint label="" value="1">
467 jonathan 690 <cldata stroke="#000000" stroke_width="10" fill="None"/>
468     </clpoint>
469 bh 1976 <clpoint label="\xc3\x9cml\xc3\xa4uts"
470     value="\xc3\xa4\xc3\xb6\xc3\xbc">
471     <cldata stroke="#000000" stroke_width="1" fill="None"/>
472 bh 1417 </clpoint>
473 jonathan 690 </classification>
474     </layer>
475 bh 1976 <layer shapestore="D138504492" visible="true" stroke="#000000"
476     title="My Layer 2" stroke_width="2" fill="None">
477 jonathan 690 <classification field="AREA" field_type="double">
478 bh 1976 <clnull label="">
479 jonathan 690 <cldata stroke="#000000" stroke_width="2" fill="None"/>
480     </clnull>
481 bh 1976 <clrange label="" range="[0;1[">
482 jonathan 692 <cldata stroke="#111111" stroke_width="1" fill="None"/>
483 jonathan 690 </clrange>
484 bh 1976 <clpoint label="" value="0.5">
485 jonathan 692 <cldata stroke="#000000" stroke_width="1" fill="#111111"/>
486 jonathan 690 </clpoint>
487 bh 1976 <clrange label="" range="[-1;0[">
488 jonathan 690 <cldata stroke="#000000" stroke_width="1" fill="None"/>
489     </clrange>
490 bh 1976 <clpoint label="" value="-0.5">
491 jonathan 690 <cldata stroke="#000000" stroke_width="1" fill="None"/>
492     </clpoint>
493     </classification>
494     </layer>
495 bh 1976 </map>
496 jonathan 690 </session>
497     '''
498 bh 292
499 bh 957 def test(self):
500 bh 1247 """Load a Thuban session with a map and classified layers."""
501 bh 957 session = load_session(self.filename())
502     self.session = session
503    
504     map = self.session.Maps()[0] # only one map in the sample
505    
506 bh 1417 expected = [("My Layer", 3,
507 bh 957 [("default", (), "",
508     ("#000000", 1, "None")),
509     ("single", "1", "",
510     ("#000000", 2, "None")),
511     ("single", "1", "",
512 bh 1417 ("#000000", 10, "None")),
513     ("single", "\xe4\xf6\xfc", "\xdcml\xe4uts",
514     ("#000000", 1, "None"))]),
515 bh 957 ("My Layer 2", 4,
516     [("default", (), "",
517     ("#000000", 2, "None")),
518     ("range", (0, 1), "",
519     ("#111111", 1, "None")),
520     ("single", .5, "",
521     ("#000000", 1, "#111111")),
522     ("range", (-1, 0), "",
523     ("#000000", 1, "None")),
524     ("single", -.5, "",
525     ("#000000", 1, "None"))])]
526    
527     self.TestLayers(map.Layers(), expected)
528    
529 bh 1976 self.check_format()
530 bh 957
531 bh 1976
532 bh 957 class TestLabels(ClassificationTest):
533    
534     file_contents = '''\
535 jonathan 690 <?xml version="1.0" encoding="UTF-8"?>
536 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
537     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
538 bh 1268 title="single map&amp;layer">
539     <fileshapesource filetype="shapefile" id="D1"
540     filename="../../Data/iceland/political.shp"/>
541     <map title="Test Map">
542     <projection name="Unknown">
543     <parameter value="zone=26"/>
544     <parameter value="proj=utm"/>
545     <parameter value="ellps=clrk66"/>
546     </projection>
547     <layer shapestore="D1" visible="true" stroke="#000000"
548     title="My Layer" stroke_width="1" fill="None">
549 jonathan 690 <classification field="POPYREG" field_type="string">
550     <clnull label="hallo">
551     <cldata stroke="#000000" stroke_width="1" fill="None"/>
552     </clnull>
553     <clpoint label="welt" value="1">
554     <cldata stroke="#000000" stroke_width="2" fill="None"/>
555     </clpoint>
556     </classification>
557     </layer>
558     </map>
559     </session>
560     '''
561    
562 bh 957 def test(self):
563     """Load a session and test for reading the group labels."""
564     eq = self.assertEquals
565     session = load_session(self.filename())
566     self.session = session
567    
568     map = self.session.Maps()[0] # only one map in the sample
569    
570     expected = [("My Layer", 1,
571     [("default", (), "hallo",
572     ("#000000", 1, "None")),
573     ("single", "1", "welt",
574     ("#000000", 2, "None"))])]
575    
576     self.TestLayers(map.Layers(), expected)
577 bh 1257 self.check_format()
578 bh 957
579    
580     class TestLayerProjection(LoadSessionTest):
581    
582     file_contents = '''\
583 jonathan 746 <?xml version="1.0" encoding="UTF-8"?>
584 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
585     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
586 bh 1268 title="single map&amp;layer">
587     <fileshapesource filetype="shapefile" id="D2"
588     filename="../../Data/iceland/roads-line.shp"/>
589     <fileshapesource filetype="shapefile" id="D4"
590     filename="../../Data/iceland/political.shp"/>
591     <map title="Test Map">
592     <projection name="Unknown">
593     <parameter value="zone=26"/>
594     <parameter value="proj=utm"/>
595     <parameter value="ellps=clrk66"/>
596     </projection>
597     <layer shapestore="D4" visible="true" stroke="#000000"
598     title="My Layer" stroke_width="1" fill="None">
599     <projection name="hello">
600     <parameter value="zone=13"/>
601     <parameter value="proj=tmerc"/>
602     <parameter value="ellps=clrk66"/>
603     </projection>
604 jonathan 746 <classification field="POPYREG" field_type="string">
605     <clnull label="hallo">
606     <cldata stroke="#000000" stroke_width="1" fill="None"/>
607     </clnull>
608     <clpoint label="welt" value="1">
609     <cldata stroke="#000000" stroke_width="2" fill="None"/>
610     </clpoint>
611     </classification>
612     </layer>
613 bh 1268 <layer shapestore="D2" visible="true" stroke="#000000"
614     title="My Layer" stroke_width="1" fill="None">
615     <projection name="Unknown">
616     <parameter value="proj=lcc"/>
617 bh 1687 <parameter value="lat_1=10"/>
618     <parameter value="lat_2=20"/>
619 bh 1268 <parameter value="ellps=clrk66"/>
620     </projection>
621 jonathan 746 </layer>
622     </map>
623     </session>
624     '''
625    
626 bh 957 def test(self):
627     """Test loading layers with projections"""
628 bh 292 eq = self.assertEquals
629 jonathan 746 neq = self.assertNotEqual
630    
631 bh 957 session = load_session(self.filename())
632 jonathan 746 self.session = session
633    
634     map = self.session.Maps()[0] # only one map in the sample
635    
636     layers = map.Layers() # two layers in the sample
637    
638     # test layer with a named projection
639     proj = layers[0].GetProjection()
640     neq(proj, None)
641     eq(proj.GetName(), "hello")
642     eq(proj.GetParameter("proj"), "tmerc")
643     eq(proj.GetParameter("zone"), "13")
644     eq(proj.GetParameter("ellps"), "clrk66")
645    
646     # test layer with an unnamed projection
647     proj = layers[1].GetProjection()
648     neq(proj, None)
649     eq(proj.GetName(), "Unknown")
650     eq(proj.GetParameter("proj"), "lcc")
651 bh 1687 eq(proj.GetParameter("lat_1"), "10")
652     eq(proj.GetParameter("lat_2"), "20")
653 jonathan 746 eq(proj.GetParameter("ellps"), "clrk66")
654    
655 bh 1257 self.check_format()
656 bh 957
657 bh 1257
658 bh 957 class TestRasterLayer(LoadSessionTest):
659    
660     file_contents = '''\
661     <?xml version="1.0" encoding="UTF-8"?>
662 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
663     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
664 bh 1268 title="single map&amp;layer">
665     <map title="Test Map">
666 jonathan 2552 <rasterlayer visible="false" filename="../../Data/iceland/island.tif"
667 jonathan 2620 title="My RasterLayer" opacity="0.4" masktype="alpha"/>
668 bh 957 </map>
669     </session>
670     '''
671    
672     def test(self):
673 jonathan 947 eq = self.assertEquals
674     neq = self.assertNotEqual
675    
676 bh 957 session = load_session(self.filename())
677 jonathan 947 self.session = session
678    
679     map = self.session.Maps()[0] # only one map in the sample
680    
681     layer = map.Layers()[0] # one layer in the sample
682    
683     eq(layer.Title(), "My RasterLayer")
684 jonathan 2620 eq(layer.Opacity(), 0.4)
685     eq(layer.MaskType(), layer.MASK_ALPHA)
686    
687 jonathan 947 self.failIf(layer.Visible())
688     self.failUnless(filenames_equal(layer.GetImageFilename(),
689     os.path.join(self.temp_dir(),
690     os.pardir, os.pardir,
691     "Data", "iceland",
692     "island.tif")))
693 bh 1257 self.check_format()
694 jonathan 947
695 bh 1268
696     class TestJoinedTable(LoadSessionTest):
697    
698     file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
699 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
700     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd" title="A Joined Table session">
701 bh 1282 <fileshapesource filetype="shapefile" id="D137227612"
702     filename="../../Data/iceland/roads-line.shp"/>
703     <filetable filetype="DBF" filename="load_joinedtable.dbf" id="D136171140"
704     title="Some Title"/>
705 bh 1375 <jointable id="D136169900" title="Joined"
706     right="D136171140" left="D137227612"
707     leftcolumn="RDLNTYPE" rightcolumn="RDTYPE"
708     jointype="LEFT OUTER"/>
709 bh 1282 <derivedshapesource table="D136169900" shapesource="D137227612"
710     id="D136170932"/>
711 bh 1268 <map title="Test Map">
712 bh 1282 <layer shapestore="D136170932" visible="true" stroke="#000000"
713     title="My Layer" stroke_width="1" fill="None"/>
714 bh 1268 </map>
715 bh 1282 </session>
716     '''
717 bh 1268
718     def setUp(self):
719     """Extend inherited method to create the dbffile for the join"""
720     LoadSessionTest.setUp(self)
721     dbffile = self.temp_file_name("load_joinedtable.dbf")
722     dbf = dbflib.create(dbffile)
723     dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
724     dbf.add_field("TEXT", dbflib.FTString, 10, 0)
725     dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
726     dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
727     dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
728     dbf.close()
729    
730     def test(self):
731     """Test loading a session containing a joined table"""
732     session = load_session(self.filename())
733     self.session = session
734    
735     tables = session.Tables()
736     self.assertEquals(len(tables), 3)
737     # FIXME: The tests shouldn't assume a certain order of the tables
738     self.assertEquals(tables[0].Title(), "Some Title")
739     self.assertEquals(tables[1].Title(), "Joined")
740 bh 1375 self.assertEquals(tables[1].JoinType(), "LEFT OUTER")
741 bh 1282 self.check_format()
742 bh 1268
743    
744 bh 2034 class TestLabelLayer(LoadSessionTest):
745 bh 1646
746 bh 2034 # Note that the labels deliberately contain non-ascii characters to
747     # test whether they're supported correctly.
748    
749     file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
750 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
751     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd" title="Thuban sample session">
752 bh 2034 <fileshapesource filetype="shapefile" id="D145265052"
753     filename="../../Data/iceland/political.shp"/>
754     <fileshapesource filetype="shapefile" id="D145412868"
755     filename="../../Data/iceland/cultural_landmark-point.shp"/>
756     <map title="Iceland map">
757     <projection name="Unknown">
758     <parameter value="zone=26"/>
759     <parameter value="proj=utm"/>
760     <parameter value="ellps=clrk66"/>
761     </projection>
762     <layer shapestore="D145265052" visible="true" stroke="#000000"
763     title="political" stroke_width="1" fill="#c0c0c0">
764     <projection name="Geographic">
765     <parameter value="proj=latlong"/>
766     <parameter value="to_meter=0.017453"/>
767     <parameter value="ellps=clrk66"/>
768     </projection>
769     </layer>
770     <layer shapestore="D145412868" visible="true" stroke="#000000"
771     title="landmarks" stroke_width="1" fill="#ffff00">
772     <projection name="Geographic">
773     <parameter value="proj=latlong"/>
774     <parameter value="to_meter=0.017453"/>
775     <parameter value="ellps=clrk66"/>
776     </projection>
777     </layer>
778     <labellayer>
779     <label x="-21.5" y="64.25" text="RUINS"
780     halign="left" valign="center"/>
781     <label x="-15.125" y="64.75" text="H\xc3\xbctte"
782     halign="right" valign="top"/>
783     </labellayer>
784     </map>
785     </session>
786     '''
787    
788     def test(self):
789     """Test loading a session with a label layer"""
790     session = load_session(self.filename())
791     self.session = session
792    
793     label_layer = self.session.Maps()[0].LabelLayer()
794     expected_labels = [(-21.5, 64.25, "RUINS", ALIGN_LEFT, ALIGN_CENTER),
795     (-15.125, 64.75, "H\xfctte", ALIGN_RIGHT, ALIGN_TOP),
796     ]
797     for label, values in zip(label_layer.Labels(), expected_labels):
798     self.assertEquals((label.x, label.y, label.text, label.halign,
799     label.valign),
800     values)
801     self.check_format()
802    
803    
804 bh 1646 class TestPostGISLayer(LoadSessionTest):
805    
806     file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
807 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
808     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
809 bh 1646 title="unnamed session">
810     <dbconnection port="%(port)s" host="%(host)s" user="%(user)s"
811     dbtype="postgis" id="D142684948" dbname="%(dbname)s"/>
812 bh 2104 <dbshapesource id="D143149420" dbconn="D142684948"
813     tablename="landmarks_point_id" id_column="point_id"
814     geometry_column="the_geom" />
815 bh 1646 <map title="unnamed map">
816     <layer shapestore="D143149420" visible="true" stroke="#000000"
817     title="landmarks" stroke_width="1" fill="None"/>
818     </map>
819     </session>
820     '''
821    
822     def setUp(self):
823     """Extend the inherited method to start the postgis server
824    
825     Furthermore, patch the file contents with the real postgis db
826     information
827     """
828     postgissupport.skip_if_no_postgis()
829     self.server = postgissupport.get_test_server()
830     self.postgisdb = self.server.get_default_static_data_db()
831    
832     self.file_contents = self.__class__.file_contents % {
833     "dbname": self.postgisdb.dbname,
834     "user": self.server.user_name,
835     "port": self.server.port,
836     "host": self.server.host}
837     LoadSessionTest.setUp(self)
838    
839     def test(self):
840     """Test loading a session containing a postgis shapestore"""
841     session = load_session(self.filename())
842     self.session = session
843     connections = session.DBConnections()
844     self.assertEquals(len(connections), 1)
845     conn = connections[0]
846     for attr, value in [("host", self.server.host),
847     ("port", str(self.server.port)),
848     ("user", self.server.user_name),
849     ("dbname", self.postgisdb.dbname)]:
850     self.assertEquals(getattr(conn, attr), value)
851     layer = session.Maps()[0].Layers()[0]
852     self.failUnless(layer.ShapeStore().DBConnection() is conn)
853    
854    
855     class TestPostGISLayerPassword(LoadSessionTest):
856    
857     file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
858 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
859     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
860 bh 1646 title="unnamed session">
861     <dbconnection port="%(port)s" host="%(host)s" user="%(user)s"
862     dbtype="postgis" id="D142684948" dbname="%(dbname)s"/>
863     <dbshapesource tablename="landmarks" id="D143149420" dbconn="D142684948"/>
864     <map title="unnamed map">
865     <layer shapestore="D143149420" visible="true" stroke="#000000"
866     title="landmarks" stroke_width="1" fill="None"/>
867     </map>
868     </session>
869     '''
870    
871     def setUp(self):
872     """Extend the inherited method to start the postgis server
873    
874     Furthermore, patch the file contents with the real postgis db
875     information
876     """
877     postgissupport.skip_if_no_postgis()
878     self.server = postgissupport.get_test_server()
879     self.postgisdb = self.server.get_default_static_data_db()
880    
881     self.file_contents = self.__class__.file_contents % {
882     "dbname": self.postgisdb.dbname,
883     "user": self.server.user_name,
884     "port": self.server.port,
885     "host": self.server.host}
886     LoadSessionTest.setUp(self)
887    
888     self.db_connection_callback_called = False
889     self.server.require_authentication(True)
890    
891     def tearDown(self):
892     """Extend the inherited method to switch off postgresql authentication
893     """
894     self.server.require_authentication(False)
895     LoadSessionTest.tearDown(self)
896    
897     def db_connection_callback(self, params, message):
898     """Implementation of Thuban.Model.hooks.query_db_connection_parameters
899     """
900     self.assertEquals(params,
901     {"dbname": self.postgisdb.dbname,
902     "user": self.server.user_name,
903     "port": str(self.server.port),
904     "host": self.server.host})
905     self.db_connection_callback_called = True
906     params = params.copy()
907     params["password"] = self.server.user_password
908     return params
909    
910     def test_with_callback(self):
911     """Test loading a session with postgis, authentication and a callback
912     """
913     session = load_session(self.filename(),
914     db_connection_callback = self.db_connection_callback)
915     self.session = session
916     connections = session.DBConnections()
917     self.assertEquals(len(connections), 1)
918     conn = connections[0]
919     for attr, value in [("host", self.server.host),
920     ("port", str(self.server.port)),
921     ("user", self.server.user_name),
922     ("dbname", self.postgisdb.dbname)]:
923     self.assertEquals(getattr(conn, attr), value)
924     layer = session.Maps()[0].Layers()[0]
925     self.failUnless(layer.ShapeStore().DBConnection() is conn)
926     self.failUnless(self.db_connection_callback_called)
927    
928     def test_without_callback(self):
929     """Test loading a session with postgis, authentication and no callback
930     """
931     # A password is required and there's no callback, so we should
932     # get a ConnectionError
933     self.assertRaises(ConnectionError, load_session, self.filename())
934    
935     def test_cancel(self):
936     """Test loading a session with postgis and cancelling authentication
937     """
938     def cancel(*args):
939     self.db_connection_callback_called = True
940     return None
941    
942     # If the user cancels, i.e. if the callbakc returns None, a
943     # LoadCancelled exception is raised.
944     self.assertRaises(LoadCancelled,
945     load_session, self.filename(), cancel)
946     self.failUnless(self.db_connection_callback_called)
947    
948    
949 bh 1268 class TestLoadError(LoadSessionTest):
950    
951     file_contents = '''\
952     <?xml version="1.0" encoding="UTF-8"?>
953 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
954     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
955 bh 1268 title="single map&amp;layer">
956     <fileshapesource id="D1" filename="../../Data/iceland/political.shp"/>
957     <map title="Test Map">
958     <projection name="Unknown">
959     <parameter value="zone=26"/>
960     <parameter value="proj=utm"/>
961     <parameter value="ellps=clrk66"/>
962     </projection>
963     <layer shapestore="D1" visible="true"
964     stroke="#000000" title="My Layer" stroke_width="1"
965     fill="None"/>
966     </map>
967     </session>
968     '''
969    
970     def test(self):
971     """Test loading a session missing a required attribute"""
972     # Don't use assertRaises to make sure that if a session is
973     # actually returned it gets destroyed properly.
974     try:
975     self.session = load_session(self.filename())
976     except LoadError, value:
977 bh 1642 # Check the actual messge in value to make sure the
978     # LoadError really was about the missing attribute
979     self.assertEquals(str(value),
980     "Element "
981 bh 2104 "(u'http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd',"
982 bh 1642 " u'fileshapesource') requires an attribute 'filetype'")
983 bh 1268 else:
984     self.fail("Missing filetype attribute doesn't raise LoadError")
985    
986 frank 2446 class Shapefile_CallBack:
987    
988     def __init__(self, params):
989     """Initialize the callback return values.
990    
991     params must be a dictionary of the potential CB modes (keys),
992     with lists of tuples of return values as values.
993     Depending on the test the callback can be called multiple,
994     each time a return value is poped from the list
995     """
996    
997     self.params = params
998    
999    
1000     def s_cb(self, filename, mode = None, second_try= 0):
1001     if self.params.has_key(mode):
1002     return self.params[mode].pop(0)
1003     else:
1004     raise LoadError
1005    
1006     class TestAltPath(LoadSessionTest):
1007    
1008     """Test the various cases in the alternative path feature.
1009    
1010     The test checks the reasonable cases:
1011     - First recognition of a path error, fixed with user interaction.
1012     - First recognition of a path error, load cancelled.
1013     - Path error fixed from list, confirmed by user.
1014     - Path error fixed from list, changed by user.
1015     - Path error fixed from list, cancelled by user.
1016     - Path error wrongly fixed from list, manual fix forced.
1017     """
1018    
1019     file_contents = '''\
1020     <?xml version="1.0" encoding="UTF-8"?>
1021     <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
1022 frank 2456 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd" title="AltPath Test session">
1023 frank 2446 <fileshapesource filetype="shapefile" id="D1108450956" filename="../../Data/iceland/political.shp"/>
1024     <fileshapesource filetype="shapefile" id="D1108900076" filename="../Data/iceland/roads-line.shp"/>
1025     <fileshapesource filetype="shapefile" id="D1108947244" filename="../../Data/iceland/cultural_landmark-point.shp"/>
1026     <map title="not the iceland map">
1027     <layer title="political" stroke_width="1" shapestore="D1108450956" visible="true" stroke="#000000" fill="#c0c0c0"/>
1028     <layer title="roads-line" stroke_width="1" shapestore="D1108900076" visible="true" stroke="#000000" fill="None"/>
1029     <layer title="something else" stroke_width="1" shapestore="D1108947244" visible="true" stroke="#000000" fill="None"/>
1030     </map>
1031     </session>
1032     '''
1033    
1034 frank 2456 def checkSession(self, session):
1035     """Check if session has been loaded successfully."""
1036    
1037     eq = self.assertEquals
1038    
1039     map = session.Maps()[0]
1040     layers = map.Layers()
1041    
1042     eq("AltPath Test session", session.Title())
1043     eq("not the iceland map", map.Title())
1044     eq(3,len(layers))
1045     eq("political",layers[0].Title())
1046     eq("roads-line",layers[1].Title())
1047     eq("something else",layers[2].Title())
1048    
1049 frank 2446 def test_01_single_path_error_fix(self):
1050     """Test single file path error fix."""
1051     # The usual initial case
1052     s_cb = Shapefile_CallBack({
1053     "search": [("../Data/iceland/roads-line.shp",0)],
1054     "check": [(None, None)]})
1055     self.session = load_session(self.filename(),
1056     shapefile_callback =s_cb.s_cb)
1057 frank 2456 self.checkSession(self.session)
1058    
1059 frank 2446 def test_02_path_error_fix_from_list(self):
1060     """Test single file path error fix."""
1061     # This represents the usual case for "from_list"
1062     s_cb = Shapefile_CallBack({
1063     "search": [("../Data/iceland/roads-line.shp",1)],
1064     "check": [(os.path.abspath("../Data/iceland/roads-line.shp"),1)]
1065     })
1066     self.session = load_session(self.filename(),
1067     shapefile_callback =s_cb.s_cb)
1068 frank 2456 self.checkSession(self.session)
1069 frank 2446
1070     def test_03_single_path_error_cancelled(self):
1071     """Test alternative path cancelled."""
1072     s_cb = Shapefile_CallBack({
1073     "search": [(None,0)],
1074     "check": [(None, None)]})
1075     self.assertRaises(LoadCancelled,
1076     load_session, self.filename(), None, s_cb.s_cb)
1077    
1078     def test_04_path_error_fix_from_list_cancelled(self):
1079     """Test alternative path from list cancelled."""
1080     s_cb = Shapefile_CallBack({
1081     "search": [("../Data/iceland/roads-line.shp",1)],
1082     "check": [(None,1)]
1083     })
1084     self.assertRaises(LoadCancelled,
1085     load_session, self.filename(), None, s_cb.s_cb)
1086    
1087     def test_05_path_error_fix_from_list_changed(self):
1088     """Test alternative path from list changed."""
1089     s_cb = Shapefile_CallBack({
1090     "search": [("../Data/iceland/roads-line.shp",1)],
1091     "check": [("../Data/iceland/roads-line.shp",0)]
1092     })
1093     self.session = load_session(self.filename(),
1094     shapefile_callback =s_cb.s_cb)
1095 frank 2456 self.checkSession(self.session)
1096 frank 2446
1097     def test_06_path_error_fix_from_list_fails(self):
1098     """Test alternative path recovery from list."""
1099     s_cb = Shapefile_CallBack({
1100     "search": [("../wrong/iceland/roads-line.shp",1),
1101     ("../Data/iceland/roads-line.shp",0)],
1102     "check": [(None,None)]
1103     })
1104     self.session = load_session(self.filename(),
1105     shapefile_callback =s_cb.s_cb)
1106     self.assertRaises(IndexError,
1107     s_cb.s_cb, None, "search")
1108    
1109    
1110    
1111 bh 292 if __name__ == "__main__":
1112 bh 1683 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