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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1931 - (show annotations)
Tue Nov 11 13:24:45 2003 UTC (21 years, 3 months ago) by bh
Original Path: trunk/thuban/test/test_load.py
File MIME type: text/x-python
File size: 29225 byte(s)
(TestSingleLayer.test_leak): New. test for the
resource leak in load_session

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 loading a thuban session from a file
10
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 to the last released version for the first, the tests here should be
20 copied to the version specific test file. The round-trip tests which
21 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 """
26
27 __version__ = "$Revision$"
28 # $Source$
29 # $Id$
30
31 import os
32 import unittest
33
34 import support
35 support.initthuban()
36
37 import postgissupport
38 from xmlsupport import sax_eventlist
39
40 import dbflib
41
42 from Thuban.Model.save import save_session
43 from Thuban.Model.load import load_session, parse_color, LoadError, \
44 LoadCancelled
45 from Thuban.Model.color import Transparent
46 from Thuban.Model.classification import ClassGroupProperties, ClassGroupRange,\
47 ClassGroupSingleton, ClassGroupDefault
48 from Thuban.Model.postgisdb import ConnectionError
49
50 def filenames_equal(name1, name2):
51 """Return true if the filenames name1 and name2 are equal.
52
53 On systems where it is available, simply use os.path.samefile,
54 otherwise return whether the normalized versions of the filenames
55 according to os.path.normpath are equal.
56 """
57 if hasattr(os.path, "samefile"):
58 return os.path.samefile(name1, name2)
59 return os.path.normpath(name1) == os.path.normpath(name2)
60
61
62
63 class LoadSessionTest(support.FileLoadTestCase):
64
65 """Base class for .thuban file loading tests
66
67 Basically the same as the FileLoadTestCase, except that all tests
68 use the '.thuban' extension by default and that setUp and tearDown
69 handle sessions.
70 """
71
72 file_extension = ".thuban"
73
74 def setUp(self):
75 """Create the test files"""
76 support.FileLoadTestCase.setUp(self)
77 self.session = None
78
79 def tearDown(self):
80 if self.session is not None:
81 self.session.Destroy()
82 self.session = None
83
84
85 dtd = "http://thuban.intevation.org/dtds/thuban-1.0-dev.dtd"
86 thubanids = [((dtd, n), (None, "id")) for n in
87 ["fileshapesource", "filetable", "jointable",
88 "derivedshapesource"]]
89 thubanidrefs = [((dtd, n), (None, m)) for n, m in
90 [("layer", "shapestore"),
91 ("jointable", "left"),
92 ("jointable", "right"),
93 ("derivedshapesource", "table"),
94 ("derivedshapesource", "shapesource")]]
95 filenames = [((dtd, n), (None, m)) for n, m in
96 [("fileshapesource", "filename"),
97 ("rasterlayer", "filename"),
98 ("filetable", "filename")]]
99 del n, m, dtd
100
101 def check_format(self):
102 """Check whether the file we loaded from matches the one that
103 would be written. Call this from each test case after loading
104 the session
105 """
106 filename = self.temp_file_name(self.id() + ".roundtrip.thuban")
107 save_session(self.session, filename)
108 el1 = sax_eventlist(filename = filename, ids = self.thubanids,
109 idrefs = self.thubanidrefs,
110 filenames = self.filenames)
111 el2 = sax_eventlist(filename = self.filename(), ids = self.thubanids,
112 idrefs = self.thubanidrefs,
113 filenames = self.filenames)
114 if 0:
115 for a, b in zip(el1, el2):
116 print a != b and "***************" or ""
117 print a
118 print b
119 self.assertEquals(el1, el2,
120 "loaded file not equivalent to the saved file")
121
122
123 class ClassificationTest(LoadSessionTest):
124
125 """
126 Base class for tests that do some detailed checking of classifications
127 """
128
129 def TestLayers(self, layers, expected):
130 TITLE = 0
131 NUM_GROUPS = 1
132 CLASSES = 2
133 GROUP_TYPE = 0
134 GROUP_DATA = 1
135 GROUP_LABEL = 2
136 GROUP_PROPS = 3
137
138 eq = self.assertEquals
139
140 eq(len(layers), len(expected))
141
142 for layer, data in zip(layers, expected):
143 eq(layer.Title(), data[TITLE])
144
145 clazz = layer.GetClassification()
146 eq(clazz.GetNumGroups(), data[NUM_GROUPS])
147 eq(clazz.GetNumGroups() + 1, len(data[CLASSES]))
148
149 i = 0
150 for group in clazz:
151 props = ClassGroupProperties()
152 props.SetLineColor(
153 parse_color(data[CLASSES][i][GROUP_PROPS][0]))
154 props.SetLineWidth(data[CLASSES][i][GROUP_PROPS][1])
155 props.SetFill(
156 parse_color(data[CLASSES][i][GROUP_PROPS][2]))
157
158 if data[CLASSES][i][GROUP_TYPE] == "default":
159 g = ClassGroupDefault(props, data[CLASSES][i][GROUP_LABEL])
160 elif data[CLASSES][i][GROUP_TYPE] == "range":
161 g = ClassGroupRange((data[CLASSES][i][GROUP_DATA][0],
162 data[CLASSES][i][GROUP_DATA][1]),
163 props, data[CLASSES][i][GROUP_LABEL])
164 elif data[CLASSES][i][GROUP_TYPE] == "single":
165 g = ClassGroupSingleton(data[CLASSES][i][GROUP_DATA],
166 props, data[CLASSES][i][GROUP_LABEL])
167
168 eq(group, g)
169
170 i += 1
171
172
173
174 class TestSingleLayer(LoadSessionTest):
175
176 # Note: The use of &amp; and non-ascii characters is deliberate. We
177 # want to test whether the loading code handles that correctly.
178 file_contents = '''\
179 <?xml version="1.0" encoding="UTF-8"?>
180 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
181 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0-dev.dtd"
182 title="Stra\xc3\x9fen &amp; Landmarken">
183 <fileshapesource filetype="shapefile" id="D1"
184 filename="../../Data/iceland/political.shp"/>
185 <map title="\xc3\x9cbersicht">
186 <projection epsg="32627" name="WGS 84 / UTM zone 27N">
187 <parameter value="datum=WGS84"/>
188 <parameter value="ellps=WGS84"/>
189 <parameter value="proj=utm"/>
190 <parameter value="units=m"/>
191 <parameter value="zone=27"/>
192 </projection>
193 <layer shapestore="D1" visible="true"
194 stroke="#000000" title="K\xc3\xbcste" stroke_width="1"
195 fill="None"/>
196 </map>
197 </session>
198 '''
199
200 def test(self):
201 """Load a session with a single map with a single layer"""
202 eq = self.assertEquals
203 session = load_session(self.filename())
204 self.session = session
205
206 # Check the title
207 eq(session.Title(), "Stra\xdfen & Landmarken")
208
209 # the session has one map.
210 maps = session.Maps()
211 eq(len(maps), 1)
212
213 # Check the map's attributes
214 map = maps[0]
215 eq(map.Title(), "\xdcbersicht")
216 proj = map.GetProjection()
217 eq(proj.GetName(), "WGS 84 / UTM zone 27N")
218 eq(proj.EPSGCode(), "32627")
219 params = proj.GetAllParameters()
220 params.sort()
221 eq(params, ["datum=WGS84", "ellps=WGS84", "proj=utm", "units=m",
222 "zone=27"])
223
224 # the map has a single layer
225 layers = map.Layers()
226 eq(len(layers), 1)
227
228 # Check the layer attributes
229 layer = layers[0]
230 eq(layer.Title(), "K\xfcste")
231 self.failUnless(filenames_equal(layer.ShapeStore().FileName(),
232 os.path.join(self.temp_dir(),
233 os.pardir, os.pardir,
234 "Data", "iceland",
235 "political.shp")))
236 eq(layer.GetClassification().GetDefaultFill(), Transparent)
237 eq(layer.GetClassification().GetDefaultLineColor().hex(), "#000000")
238 eq(layer.Visible(), True)
239
240 self.check_format()
241
242 self.session.Destroy()
243 self.session = None
244
245 def test_leak(self):
246 """Test load_session for resource leaks
247
248 The load_session function had a resource leak in that it created
249 cyclic references. The objects would have been eventually
250 collected by the garbage collector but too late. One symptom is
251 that when layers are removed so that the last normal reference
252 owned indirectly by the session to a shape store goes away, the
253 shape store is not actually removed from the session even though
254 the session only keeps weak references because there are still
255 references owned by the cyclic garbage.
256 """
257 session = load_session(self.filename())
258 self.session = session
259
260 # sanity check
261 self.assertEquals(len(session.ShapeStores()), 1)
262
263 # remove the map. The shapestore should go away too
264 session.RemoveMap(session.Maps()[0])
265 self.assertEquals(len(session.ShapeStores()), 0)
266
267
268 class TestLayerVisibility(LoadSessionTest):
269
270 file_contents = '''\
271 <?xml version="1.0" encoding="UTF-8"?>
272 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
273 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0-dev.dtd"
274 title="single map&amp;layer">
275 <fileshapesource filetype="shapefile" id="D1"
276 filename="../../Data/iceland/political.shp"/>
277 <map title="Test Map">
278 <projection name="Unknown">
279 <parameter value="zone=26"/>
280 <parameter value="proj=utm"/>
281 <parameter value="ellps=clrk66"/>
282 </projection>
283 <layer shapestore="D1" visible="false" stroke="#000000"
284 title="My Layer" stroke_width="1" fill="None"/>
285 </map>
286 </session>
287 '''
288
289 def test(self):
290 """Test that the visible flag is correctly loaded for a layer."""
291 eq = self.assertEquals
292 session = load_session(self.filename())
293 self.session = session
294 maps = session.Maps()
295 eq(len(maps), 1)
296 map = maps[0]
297 layers = map.Layers()
298 eq(len(layers), 1)
299 layer = layers[0]
300
301 eq(layer.Visible(), False)
302
303 self.check_format()
304
305
306 class TestClassification(ClassificationTest):
307
308 file_contents = '''\
309 <?xml version="1.0" encoding="UTF-8"?>
310 <!DOCTYPE session SYSTEM "thuban.dtd">
311 <session title="single map&amp;layer">
312 <map title="Test Map">
313 <projection>
314 <parameter value="zone=26"/>
315 <parameter value="proj=utm"/>
316 <parameter value="ellps=clrk66"/>
317 </projection>
318 <layer title="My Layer" stroke_width="1" fill="None"
319 filename="../../Data/iceland/political.shp"
320 stroke="#000000">
321 <classification field="POPYREG" field_type="string">
322 <clnull>
323 <cldata stroke="#000000" stroke_width="1" fill="None"/>
324 </clnull>
325 <clpoint value="1">
326 <cldata stroke="#000000" stroke_width="2" fill="None"/>
327 </clpoint>
328 <clpoint value="1">
329 <cldata stroke="#000000" stroke_width="10" fill="None"/>
330 </clpoint>
331 <clpoint value="\xc3\xa4\xc3\xb6\xc3\xbc"
332 label="\xc3\x9cml\xc3\xa4uts">
333 <cldata fill="None" stroke="#000000" stroke_width="1"/>
334 </clpoint>
335 </classification>
336 </layer>
337 <layer title="My Layer 2" stroke_width="1" fill="None"
338 filename="../../Data/iceland/political.shp"
339 stroke="#000000">
340 <classification field="AREA" field_type="double">
341 <clnull>
342 <cldata stroke="#000000" stroke_width="2" fill="None"/>
343 </clnull>
344 <clrange min="0" max="1">
345 <cldata stroke="#111111" stroke_width="1" fill="None"/>
346 </clrange>
347 <clpoint value=".5">
348 <cldata stroke="#000000" stroke_width="1" fill="#111111"/>
349 </clpoint>
350 <clrange min="-1" max="0">
351 <cldata stroke="#000000" stroke_width="1" fill="None"/>
352 </clrange>
353 <clpoint value="-.5">
354 <cldata stroke="#000000" stroke_width="1" fill="None"/>
355 </clpoint>
356 </classification>
357 </layer>
358 </map>
359 </session>
360 '''
361
362 def test(self):
363 """Load a Thuban session with a map and classified layers."""
364 session = load_session(self.filename())
365 self.session = session
366
367 map = self.session.Maps()[0] # only one map in the sample
368
369 expected = [("My Layer", 3,
370 [("default", (), "",
371 ("#000000", 1, "None")),
372 ("single", "1", "",
373 ("#000000", 2, "None")),
374 ("single", "1", "",
375 ("#000000", 10, "None")),
376 ("single", "\xe4\xf6\xfc", "\xdcml\xe4uts",
377 ("#000000", 1, "None"))]),
378 ("My Layer 2", 4,
379 [("default", (), "",
380 ("#000000", 2, "None")),
381 ("range", (0, 1), "",
382 ("#111111", 1, "None")),
383 ("single", .5, "",
384 ("#000000", 1, "#111111")),
385 ("range", (-1, 0), "",
386 ("#000000", 1, "None")),
387 ("single", -.5, "",
388 ("#000000", 1, "None"))])]
389
390 self.TestLayers(map.Layers(), expected)
391
392
393 class TestLabels(ClassificationTest):
394
395 file_contents = '''\
396 <?xml version="1.0" encoding="UTF-8"?>
397 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
398 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0-dev.dtd"
399 title="single map&amp;layer">
400 <fileshapesource filetype="shapefile" id="D1"
401 filename="../../Data/iceland/political.shp"/>
402 <map title="Test Map">
403 <projection name="Unknown">
404 <parameter value="zone=26"/>
405 <parameter value="proj=utm"/>
406 <parameter value="ellps=clrk66"/>
407 </projection>
408 <layer shapestore="D1" visible="true" stroke="#000000"
409 title="My Layer" stroke_width="1" fill="None">
410 <classification field="POPYREG" field_type="string">
411 <clnull label="hallo">
412 <cldata stroke="#000000" stroke_width="1" fill="None"/>
413 </clnull>
414 <clpoint label="welt" value="1">
415 <cldata stroke="#000000" stroke_width="2" fill="None"/>
416 </clpoint>
417 </classification>
418 </layer>
419 </map>
420 </session>
421 '''
422
423 def test(self):
424 """Load a session and test for reading the group labels."""
425 eq = self.assertEquals
426 session = load_session(self.filename())
427 self.session = session
428
429 map = self.session.Maps()[0] # only one map in the sample
430
431 expected = [("My Layer", 1,
432 [("default", (), "hallo",
433 ("#000000", 1, "None")),
434 ("single", "1", "welt",
435 ("#000000", 2, "None"))])]
436
437 self.TestLayers(map.Layers(), expected)
438 self.check_format()
439
440
441 class TestLayerProjection(LoadSessionTest):
442
443 file_contents = '''\
444 <?xml version="1.0" encoding="UTF-8"?>
445 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
446 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0-dev.dtd"
447 title="single map&amp;layer">
448 <fileshapesource filetype="shapefile" id="D2"
449 filename="../../Data/iceland/roads-line.shp"/>
450 <fileshapesource filetype="shapefile" id="D4"
451 filename="../../Data/iceland/political.shp"/>
452 <map title="Test Map">
453 <projection name="Unknown">
454 <parameter value="zone=26"/>
455 <parameter value="proj=utm"/>
456 <parameter value="ellps=clrk66"/>
457 </projection>
458 <layer shapestore="D4" visible="true" stroke="#000000"
459 title="My Layer" stroke_width="1" fill="None">
460 <projection name="hello">
461 <parameter value="zone=13"/>
462 <parameter value="proj=tmerc"/>
463 <parameter value="ellps=clrk66"/>
464 </projection>
465 <classification field="POPYREG" field_type="string">
466 <clnull label="hallo">
467 <cldata stroke="#000000" stroke_width="1" fill="None"/>
468 </clnull>
469 <clpoint label="welt" value="1">
470 <cldata stroke="#000000" stroke_width="2" fill="None"/>
471 </clpoint>
472 </classification>
473 </layer>
474 <layer shapestore="D2" visible="true" stroke="#000000"
475 title="My Layer" stroke_width="1" fill="None">
476 <projection name="Unknown">
477 <parameter value="proj=lcc"/>
478 <parameter value="lat_1=10"/>
479 <parameter value="lat_2=20"/>
480 <parameter value="ellps=clrk66"/>
481 </projection>
482 </layer>
483 </map>
484 </session>
485 '''
486
487 def test(self):
488 """Test loading layers with projections"""
489 eq = self.assertEquals
490 neq = self.assertNotEqual
491
492 session = load_session(self.filename())
493 self.session = session
494
495 map = self.session.Maps()[0] # only one map in the sample
496
497 layers = map.Layers() # two layers in the sample
498
499 # test layer with a named projection
500 proj = layers[0].GetProjection()
501 neq(proj, None)
502 eq(proj.GetName(), "hello")
503 eq(proj.GetParameter("proj"), "tmerc")
504 eq(proj.GetParameter("zone"), "13")
505 eq(proj.GetParameter("ellps"), "clrk66")
506
507 # test layer with an unnamed projection
508 proj = layers[1].GetProjection()
509 neq(proj, None)
510 eq(proj.GetName(), "Unknown")
511 eq(proj.GetParameter("proj"), "lcc")
512 eq(proj.GetParameter("lat_1"), "10")
513 eq(proj.GetParameter("lat_2"), "20")
514 eq(proj.GetParameter("ellps"), "clrk66")
515
516 self.check_format()
517
518
519 class TestRasterLayer(LoadSessionTest):
520
521 file_contents = '''\
522 <?xml version="1.0" encoding="UTF-8"?>
523 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
524 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0-dev.dtd"
525 title="single map&amp;layer">
526 <map title="Test Map">
527 <rasterlayer visible="false" filename="../../Data/iceland/island.tif"
528 title="My RasterLayer"/>
529 </map>
530 </session>
531 '''
532
533 def test(self):
534 eq = self.assertEquals
535 neq = self.assertNotEqual
536
537 session = load_session(self.filename())
538 self.session = session
539
540 map = self.session.Maps()[0] # only one map in the sample
541
542 layer = map.Layers()[0] # one layer in the sample
543
544 eq(layer.Title(), "My RasterLayer")
545 self.failIf(layer.Visible())
546 self.failUnless(filenames_equal(layer.GetImageFilename(),
547 os.path.join(self.temp_dir(),
548 os.pardir, os.pardir,
549 "Data", "iceland",
550 "island.tif")))
551 self.check_format()
552
553
554 class TestJoinedTable(LoadSessionTest):
555
556 file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
557 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
558 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0-dev.dtd" title="A Joined Table session">
559 <fileshapesource filetype="shapefile" id="D137227612"
560 filename="../../Data/iceland/roads-line.shp"/>
561 <filetable filetype="DBF" filename="load_joinedtable.dbf" id="D136171140"
562 title="Some Title"/>
563 <jointable id="D136169900" title="Joined"
564 right="D136171140" left="D137227612"
565 leftcolumn="RDLNTYPE" rightcolumn="RDTYPE"
566 jointype="LEFT OUTER"/>
567 <derivedshapesource table="D136169900" shapesource="D137227612"
568 id="D136170932"/>
569 <map title="Test Map">
570 <layer shapestore="D136170932" visible="true" stroke="#000000"
571 title="My Layer" stroke_width="1" fill="None"/>
572 </map>
573 </session>
574 '''
575
576 def setUp(self):
577 """Extend inherited method to create the dbffile for the join"""
578 LoadSessionTest.setUp(self)
579 dbffile = self.temp_file_name("load_joinedtable.dbf")
580 dbf = dbflib.create(dbffile)
581 dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
582 dbf.add_field("TEXT", dbflib.FTString, 10, 0)
583 dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
584 dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
585 dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
586 dbf.close()
587
588 def test(self):
589 """Test loading a session containing a joined table"""
590 session = load_session(self.filename())
591 self.session = session
592
593 tables = session.Tables()
594 self.assertEquals(len(tables), 3)
595 # FIXME: The tests shouldn't assume a certain order of the tables
596 self.assertEquals(tables[0].Title(), "Some Title")
597 self.assertEquals(tables[1].Title(), "Joined")
598 self.assertEquals(tables[1].JoinType(), "LEFT OUTER")
599 self.check_format()
600
601
602
603 class TestPostGISLayer(LoadSessionTest):
604
605 file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
606 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
607 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0-dev.dtd"
608 title="unnamed session">
609 <dbconnection port="%(port)s" host="%(host)s" user="%(user)s"
610 dbtype="postgis" id="D142684948" dbname="%(dbname)s"/>
611 <dbshapesource tablename="landmarks" id="D143149420" dbconn="D142684948"/>
612 <map title="unnamed map">
613 <layer shapestore="D143149420" visible="true" stroke="#000000"
614 title="landmarks" stroke_width="1" fill="None"/>
615 </map>
616 </session>
617 '''
618
619 def setUp(self):
620 """Extend the inherited method to start the postgis server
621
622 Furthermore, patch the file contents with the real postgis db
623 information
624 """
625 postgissupport.skip_if_no_postgis()
626 self.server = postgissupport.get_test_server()
627 self.postgisdb = self.server.get_default_static_data_db()
628
629 self.file_contents = self.__class__.file_contents % {
630 "dbname": self.postgisdb.dbname,
631 "user": self.server.user_name,
632 "port": self.server.port,
633 "host": self.server.host}
634 LoadSessionTest.setUp(self)
635
636 def test(self):
637 """Test loading a session containing a postgis shapestore"""
638 session = load_session(self.filename())
639 self.session = session
640 connections = session.DBConnections()
641 self.assertEquals(len(connections), 1)
642 conn = connections[0]
643 for attr, value in [("host", self.server.host),
644 ("port", str(self.server.port)),
645 ("user", self.server.user_name),
646 ("dbname", self.postgisdb.dbname)]:
647 self.assertEquals(getattr(conn, attr), value)
648 layer = session.Maps()[0].Layers()[0]
649 self.failUnless(layer.ShapeStore().DBConnection() is conn)
650
651
652 class TestPostGISLayerPassword(LoadSessionTest):
653
654 file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
655 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
656 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0-dev.dtd"
657 title="unnamed session">
658 <dbconnection port="%(port)s" host="%(host)s" user="%(user)s"
659 dbtype="postgis" id="D142684948" dbname="%(dbname)s"/>
660 <dbshapesource tablename="landmarks" id="D143149420" dbconn="D142684948"/>
661 <map title="unnamed map">
662 <layer shapestore="D143149420" visible="true" stroke="#000000"
663 title="landmarks" stroke_width="1" fill="None"/>
664 </map>
665 </session>
666 '''
667
668 def setUp(self):
669 """Extend the inherited method to start the postgis server
670
671 Furthermore, patch the file contents with the real postgis db
672 information
673 """
674 postgissupport.skip_if_no_postgis()
675 self.server = postgissupport.get_test_server()
676 self.postgisdb = self.server.get_default_static_data_db()
677
678 self.file_contents = self.__class__.file_contents % {
679 "dbname": self.postgisdb.dbname,
680 "user": self.server.user_name,
681 "port": self.server.port,
682 "host": self.server.host}
683 LoadSessionTest.setUp(self)
684
685 self.db_connection_callback_called = False
686 self.server.require_authentication(True)
687
688 def tearDown(self):
689 """Extend the inherited method to switch off postgresql authentication
690 """
691 self.server.require_authentication(False)
692 LoadSessionTest.tearDown(self)
693
694 def db_connection_callback(self, params, message):
695 """Implementation of Thuban.Model.hooks.query_db_connection_parameters
696 """
697 self.assertEquals(params,
698 {"dbname": self.postgisdb.dbname,
699 "user": self.server.user_name,
700 "port": str(self.server.port),
701 "host": self.server.host})
702 self.db_connection_callback_called = True
703 params = params.copy()
704 params["password"] = self.server.user_password
705 return params
706
707 def test_with_callback(self):
708 """Test loading a session with postgis, authentication and a callback
709 """
710 session = load_session(self.filename(),
711 db_connection_callback = self.db_connection_callback)
712 self.session = session
713 connections = session.DBConnections()
714 self.assertEquals(len(connections), 1)
715 conn = connections[0]
716 for attr, value in [("host", self.server.host),
717 ("port", str(self.server.port)),
718 ("user", self.server.user_name),
719 ("dbname", self.postgisdb.dbname)]:
720 self.assertEquals(getattr(conn, attr), value)
721 layer = session.Maps()[0].Layers()[0]
722 self.failUnless(layer.ShapeStore().DBConnection() is conn)
723 self.failUnless(self.db_connection_callback_called)
724
725 def test_without_callback(self):
726 """Test loading a session with postgis, authentication and no callback
727 """
728 # A password is required and there's no callback, so we should
729 # get a ConnectionError
730 self.assertRaises(ConnectionError, load_session, self.filename())
731
732 def test_cancel(self):
733 """Test loading a session with postgis and cancelling authentication
734 """
735 def cancel(*args):
736 self.db_connection_callback_called = True
737 return None
738
739 # If the user cancels, i.e. if the callbakc returns None, a
740 # LoadCancelled exception is raised.
741 self.assertRaises(LoadCancelled,
742 load_session, self.filename(), cancel)
743 self.failUnless(self.db_connection_callback_called)
744
745
746 class TestLoadError(LoadSessionTest):
747
748 file_contents = '''\
749 <?xml version="1.0" encoding="UTF-8"?>
750 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
751 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0-dev.dtd"
752 title="single map&amp;layer">
753 <fileshapesource id="D1" filename="../../Data/iceland/political.shp"/>
754 <map title="Test Map">
755 <projection name="Unknown">
756 <parameter value="zone=26"/>
757 <parameter value="proj=utm"/>
758 <parameter value="ellps=clrk66"/>
759 </projection>
760 <layer shapestore="D1" visible="true"
761 stroke="#000000" title="My Layer" stroke_width="1"
762 fill="None"/>
763 </map>
764 </session>
765 '''
766
767 def test(self):
768 """Test loading a session missing a required attribute"""
769 # Don't use assertRaises to make sure that if a session is
770 # actually returned it gets destroyed properly.
771 try:
772 self.session = load_session(self.filename())
773 except LoadError, value:
774 # Check the actual messge in value to make sure the
775 # LoadError really was about the missing attribute
776 self.assertEquals(str(value),
777 "Element "
778 "(u'http://thuban.intevation.org/dtds/thuban-1.0-dev.dtd',"
779 " u'fileshapesource') requires an attribute 'filetype'")
780 else:
781 self.fail("Missing filetype attribute doesn't raise LoadError")
782
783 if __name__ == "__main__":
784 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