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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 684 by jonathan, Tue Apr 15 21:55:12 2003 UTC revision 1931 by bh, Tue Nov 11 13:24:45 2003 UTC
# Line 1  Line 1 
1  # Copyright (c) 2002 by Intevation GmbH  # Copyright (c) 2002, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4  #  #
# Line 7  Line 7 
7    
8  """  """
9  Test loading a thuban session from a file  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$"  __version__ = "$Revision$"
# Line 19  import unittest Line 34  import unittest
34  import support  import support
35  support.initthuban()  support.initthuban()
36    
37  from Thuban.Model.load import load_session, parse_color  import postgissupport
38  from Thuban.Model.session import Session  from xmlsupport import sax_eventlist
 from Thuban.Model.map import Map  
 from Thuban.Model.layer import Layer  
 from Thuban.Model.proj import Projection  
 from Thuban.Model.color import Color  
39    
40  from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, FIELDTYPE_STRING  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,\  from Thuban.Model.classification import ClassGroupProperties, ClassGroupRange,\
47      ClassGroupSingleton, ClassGroupDefault      ClassGroupSingleton, ClassGroupDefault
48    from Thuban.Model.postgisdb import ConnectionError
49    
50  def filenames_equal(name1, name2):  def filenames_equal(name1, name2):
51      """Return true if the filenames name1 and name2 are equal.      """Return true if the filenames name1 and name2 are equal.
# Line 43  def filenames_equal(name1, name2): Line 59  def filenames_equal(name1, name2):
59      return os.path.normpath(name1) == os.path.normpath(name2)      return os.path.normpath(name1) == os.path.normpath(name2)
60    
61    
 contents_single_map = '''\  
 <?xml version="1.0" encoding="UTF-8"?>  
 <!DOCTYPE session SYSTEM "thuban.dtd">  
 <session title="single map&amp;layer">  
         <map title="Test Map">  
                 <projection>  
                         <parameter value="zone=26"/>  
                         <parameter value="proj=utm"/>  
                         <parameter value="ellps=clrk66"/>  
                 </projection>  
                 <layer title="My Layer" stroke_width="1" fill="None"  
                     filename="../../Data/iceland/political.shp"  
                     stroke="#000000"/>  
         </map>  
 </session>  
 '''  
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  class LoadSessionTest(unittest.TestCase, support.FileTestMixin):      file_extension = ".thuban"
73    
74      def setUp(self):      def setUp(self):
75          """Create the test files"""          """Create the test files"""
76          file = open(self.temp_file_name("load_singlelayer.thuban"), "w")          support.FileLoadTestCase.setUp(self)
         file.write(contents_single_map)  
         file.close()  
77          self.session = None          self.session = None
78    
79      def tearDown(self):      def tearDown(self):
80          if self.session is not None:          if self.session is not None:
81              self.session.Destroy()              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      def testSingleLayer(self):  
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"""          """Load a session with a single map with a single layer"""
202          eq = self.assertEquals          eq = self.assertEquals
203          session = load_session(self.temp_file_name("load_singlelayer.thuban"))          session = load_session(self.filename())
204          self.session = session          self.session = session
205    
206          # Check the title          # Check the title
207          eq(session.Title(), "single map&layer")          eq(session.Title(), "Stra\xdfen & Landmarken")
208    
209          # the session has one map.          # the session has one map.
210          maps = session.Maps()          maps = session.Maps()
# Line 89  class LoadSessionTest(unittest.TestCase, Line 212  class LoadSessionTest(unittest.TestCase,
212    
213          # Check the map's attributes          # Check the map's attributes
214          map = maps[0]          map = maps[0]
215          eq(map.Title(), "Test Map")          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          # the map has a single layer
225          layers = map.Layers()          layers = map.Layers()
# Line 97  class LoadSessionTest(unittest.TestCase, Line 227  class LoadSessionTest(unittest.TestCase,
227    
228          # Check the layer attributes          # Check the layer attributes
229          layer = layers[0]          layer = layers[0]
230          eq(layer.Title(), "My Layer")          eq(layer.Title(), "K\xfcste")
231          self.failUnless(filenames_equal(layer.filename,          self.failUnless(filenames_equal(layer.ShapeStore().FileName(),
232                                          os.path.join(self.temp_dir(),                                          os.path.join(self.temp_dir(),
233                                                       os.pardir, os.pardir,                                                       os.pardir, os.pardir,
234                                                       "Data", "iceland",                                                       "Data", "iceland",
235                                                       "political.shp")))                                                       "political.shp")))
236          eq(layer.GetClassification().GetDefaultFill(), Color.Transparent)          eq(layer.GetClassification().GetDefaultFill(), Transparent)
237          eq(layer.GetClassification().GetDefaultLineColor().hex(), "#000000")          eq(layer.GetClassification().GetDefaultLineColor().hex(), "#000000")
238            eq(layer.Visible(), True)
239    
240            self.check_format()
241    
242          self.session.Destroy()          self.session.Destroy()
243          self.session = None          self.session = None
244    
245      def testClassification(self):      def test_leak(self):
246          """Load a session with a map and classified layers."""          """Test load_session for resource leaks
247    
248          eq = self.assertEquals          The load_session function had a resource leak in that it created
249          session = load_session("../Data/iceland_sample_test.thuban")          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          self.session = session
259    
260          map = self.session.Maps()[0] # only one map in the sample          # 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()          layers = map.Layers()
298          eq(len(layers), 3)          eq(len(layers), 1)
299            layer = layers[0]
300    
301          expected = (("political", 0,          eq(layer.Visible(), False)
302                          [("default", (), "",  
303                              ("#000000", 1, "#c0c0c0"))]),          self.check_format()
304                      ("roads-line", 5,  
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", (), "",                          [("default", (), "",
371                              ("#000000", 1, "None")),                              ("#000000", 1, "None")),
372                           ("range", (0.001, 0.3996), "short roads",                           ("single", "1", "",
373                              ("#ffffff", 1, "#ffffff")),                              ("#000000", 2, "None")),
374                           ("range", (0.3996, 0.7982), "less short",                           ("single", "1", "",
375                              ("#ccf4cc", 1, "#ccf4cc")),                              ("#000000", 10, "None")),
376                           ("range", (0.7982, 1.1968), "bit longer",                           ("single", "\xe4\xf6\xfc", "\xdcml\xe4uts",
377                              ("#99ea99", 1, "#99ea99")),                              ("#000000", 1, "None"))]),
378                           ("range", (1.1968, 1.5954), "where's the end?",                       ("My Layer 2", 4,
379                              ("#66e066", 1, "#66e066")),                           [("default", (), "",
380                           ("range", (1.5954, 1.994), "long roads",                              ("#000000", 2, "None")),
381                              ("#33d633", 1, "#33d633"))]),                            ("range", (0, 1), "",
382                      ("something else", 6,                              ("#111111", 1, "None")),
383                          [("default", (), "",                            ("single", .5, "",
384                                ("#000000", 1, "#111111")),
385                              ("range", (-1, 0), "",
386                              ("#000000", 1, "None")),                              ("#000000", 1, "None")),
387                           ("single", ("BUILDING"),  "",                            ("single", -.5, "",
388                              ("#0000ff", 1, "#0000ff")),                              ("#000000", 1, "None"))])]
                          ("single", ("FARM"), "",  
                             ("#00aaff", 1, "#00aaff")),  
                          ("single", ("HUT"), "",  
                             ("#00ffaa", 1, "#00ffaa")),  
                          ("single", ("LIGHTHOUSE"), "",  
                             ("#00ff00", 1, "#00ff00")),  
                          ("single", ("OTHER/UNKNOWN"), "",  
                             ("#aaff00", 1, "#aaff00")),  
                          ("single", ("RUINS"), "",  
                             ("#ffaa00", 1, "#ffaa00"))]))  
389    
390          eq(len(layers), len(expected))          self.TestLayers(map.Layers(), expected)
391    
         TITLE = 0  
         NUM_GROUPS = 1  
         CLASSES = 2  
         GROUP_TYPE = 0  
         GROUP_DATA = 1  
         GROUP_LABEL = 2  
         GROUP_PROPS = 3  
392    
393          for layer, data in zip(layers, expected):  class TestLabels(ClassificationTest):
             eq(layer.Title(), data[TITLE])  
394    
395              clazz = layer.GetClassification()      file_contents = '''\
396              eq(clazz.GetNumGroups(), data[NUM_GROUPS])  <?xml version="1.0" encoding="UTF-8"?>
397              eq(clazz.GetNumGroups() + 1, len(data[CLASSES]))  <!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              i = 0      def test(self):
424              for group in clazz:          """Load a session and test for reading the group labels."""
425                            eq = self.assertEquals
426                  props = ClassGroupProperties()          session = load_session(self.filename())
427                  props.SetLineColor(          self.session = session
                     parse_color(data[CLASSES][i][GROUP_PROPS][0]))  
                 props.SetLineWidth(data[CLASSES][i][GROUP_PROPS][1])  
                 props.SetFill(  
                     parse_color(data[CLASSES][i][GROUP_PROPS][2]))  
428    
429                  if data[CLASSES][i][GROUP_TYPE] == "default":          map = self.session.Maps()[0] # only one map in the sample
                     g = ClassGroupDefault(props, data[CLASSES][i][GROUP_LABEL])  
                 elif data[CLASSES][i][GROUP_TYPE] == "range":  
                     g = ClassGroupRange(data[CLASSES][i][GROUP_DATA][0],  
                                         data[CLASSES][i][GROUP_DATA][1],  
                                         props, data[CLASSES][i][GROUP_LABEL])  
                 elif data[CLASSES][i][GROUP_TYPE] == "single":  
                     g = ClassGroupSingleton(data[CLASSES][i][GROUP_DATA],  
                                           props, data[CLASSES][i][GROUP_LABEL])  
430    
431                  eq(group, g)          expected = [("My Layer", 1,
432                            [("default", (), "hallo",
433                                ("#000000", 1, "None")),
434                             ("single", "1", "welt",
435                                ("#000000", 2, "None"))])]
436    
437                  i += 1          self.TestLayers(map.Layers(), expected)
438            self.check_format()
439    
 if __name__ == "__main__":  
     unittest.main()  
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()

Legend:
Removed from v.684  
changed lines
  Added in v.1931

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26